mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-19 08:29:18 +02:00
Joining meant replaying backbuffer.bin from the very first frame of the session, so the longer a session ran, the longer it took to get in - and the whole history had to be kept for it. - network/snapshot: a chunked container with a version of its own. Every section carries its length, so a peer built before a section existed reads a newer snapshot and simply walks past what it does not know. Version 1 carries the session (tick, clock, weather, the state of the random engine), the vehicles (position on the track, speed, direction, controls, brake pressures, whether the AI is driving) and the crew roster. Switches, memcells, signals and the event queue are the next sections - joining is now: handshake -> load the scenario -> CLIENT_READY -> the server takes a snapshot on the spot and sends it -> the peer goes live. Because the snapshot is taken at the moment the peer becomes active there is no backlog to replay at all; the frame by frame catch-up is gone - the server refuses a peer that loaded a different scenario, with a readable reason instead of a silent desync - reconnecting into a session that is already loaded asks for a fresh snapshot straight away rather than waiting for a loader that will not run again - a vehicle is only put back on the rails when it really is somewhere else; the arithmetic that turns the recorded bogie offset back into the nose distance place_on_track() expects mirrors what that function itself does - the session log is still written out - it is useful when picking a desync apart - but nothing depends on replaying it any more
59 lines
1.8 KiB
C++
59 lines
1.8 KiB
C++
#pragma once
|
|
#include <memory>
|
|
#include "network/network.h"
|
|
#include "input/command.h"
|
|
|
|
namespace network
|
|
{
|
|
class server_manager
|
|
{
|
|
private:
|
|
std::vector<std::shared_ptr<server>> servers;
|
|
std::shared_ptr<std::fstream> backbuffer;
|
|
|
|
public:
|
|
server_manager();
|
|
|
|
void push_delta(double render_dt, double dt, uint64_t tick, uint64_t state_hash, const command_queue::commands_map &commands);
|
|
command_queue::commands_map pop_commands();
|
|
void create_server(const std::string &backend, const std::string &conf);
|
|
// refreshes the authoritative vehicle roster and publishes it when it changed
|
|
void publish_vehicle_list();
|
|
// brings the world in line with the crew roster and announces every change
|
|
void update_crews();
|
|
// crew request coming from the local participant, which needs no transport
|
|
void apply_local_claim(NetworkEntityId entity_id);
|
|
void apply_local_leave(NetworkEntityId entity_id);
|
|
|
|
private:
|
|
// how many frames may pass between two unconditional broadcasts of the roster
|
|
static const int PUBLISH_INTERVAL_FRAMES = 120;
|
|
|
|
std::vector<vehicle_entry> last_published_list;
|
|
int publish_countdown = 0;
|
|
int crew_publish_countdown = 0;
|
|
};
|
|
|
|
class manager
|
|
{
|
|
public:
|
|
manager();
|
|
|
|
std::optional<server_manager> servers;
|
|
std::shared_ptr<network::client> client;
|
|
|
|
void create_server(const std::string &backend, const std::string &conf);
|
|
void connect(const std::string &backend, const std::string &conf);
|
|
void update();
|
|
|
|
// routes a lobby request to whoever holds the authority: straight into the crew
|
|
// registry when we are the server, over the wire when we are a client
|
|
void request_claim(NetworkEntityId entity_id);
|
|
void request_leave(NetworkEntityId entity_id);
|
|
|
|
// the local scenario is loaded; a client asks the server for a snapshot of the
|
|
// world as it stands right now
|
|
void notify_scenario_loaded();
|
|
};
|
|
}
|