17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 19:09:25 +02:00
Files
maszyna/network/manager.h
Hirek193 b255c8120a multiplayer stage 6: a logical simulation tick and a real state digest
The protocol hung off whatever frame the renderer happened to be drawing, and
the only thing standing in for synchronisation was the sum of every vehicle's
coordinates with a random number added on top - a value that cannot be equal on
two machines and therefore reported a desync on every single step.

- Global.simulation_tick: the authority counts the steps, a client takes the
  number from the authoritative frame it is executing. FRAME_INFO and the
  command requests carry it, so the network timeline has one unambiguous order
  independent of frame rates
- network/statehash: a versioned FNV digest of the gameplay critical state -
  vehicle position, speed, direction, brake pipe and cylinder pressure, plus the
  clock. Values are quantized so that float noise is not mistaken for drift, and
  vehicles are folded in under their own identity and summed, so the digest does
  not depend on the order the scenario created them in. Switches, memcells and
  the event queue are the next candidates; they go in when stage 7 pins down
  what a snapshot contains
- a client compares its own digest against the authoritative one and reports the
  drift when it starts and then only now and then, rather than every step; the
  overlay says how long it has been out of step and at which tick
- refusing to compare at all when the two builds disagree on the digest layout

EU07_NETWORK_VERSION is now 4.
2026-09-06 19:21:12 +00:00

55 lines
1.7 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);
};
}