mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-18 16:09:19 +02:00
server_hello.config had been a TODO carrying a zero, and every peer ran with whatever its own eu07.ini happened to say - including a vehicle physics thread count, which makes the order vehicles are stepped in depend on how threads get scheduled. - the handshake now carries a bitfield of the settings that change how the physics comes out (full physics, realistic control) and a joining peer takes them on, saying in the log what changed - a multiplayer session runs the vehicle physics on one thread on every peer, host included Settings that only affect what a player sees or how comfortable the controls feel stay with the player; only what alters the outcome belongs in here.
223 lines
6.2 KiB
C++
223 lines
6.2 KiB
C++
#pragma once
|
|
#include "network/message.h"
|
|
#include "network/entities.h"
|
|
#include "input/command.h"
|
|
#include <queue>
|
|
|
|
namespace network
|
|
{
|
|
struct message
|
|
{
|
|
enum type_e
|
|
{
|
|
CLIENT_HELLO = 0,
|
|
SERVER_HELLO,
|
|
FRAME_INFO,
|
|
REQUEST_COMMAND,
|
|
SERVER_REJECT,
|
|
VEHICLE_LIST,
|
|
CLAIM_VEHICLE,
|
|
CLAIM_GRANTED,
|
|
CLAIM_DENIED,
|
|
LEAVE_VEHICLE,
|
|
CREW_UPDATE,
|
|
CLIENT_READY,
|
|
SNAPSHOT,
|
|
REQUEST_RESYNC,
|
|
TYPE_MAX
|
|
};
|
|
|
|
type_e type;
|
|
|
|
message(type_e t) : type(t) {}
|
|
virtual void serialize(std::ostream &stream) const {}
|
|
virtual void deserialize(std::istream &stream) {}
|
|
};
|
|
|
|
struct client_hello : public message
|
|
{
|
|
client_hello() : message(CLIENT_HELLO) {}
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
|
|
int32_t version;
|
|
uint32_t start_packet;
|
|
// build identification of the connecting simulator, informational only
|
|
std::string app_version;
|
|
// identity handed out by this server on an earlier connection, echoed back so that a
|
|
// player who dropped out gets their seat and their peer id back. it is a reconnect
|
|
// token, not a credential - it says "this is the same session", nothing more
|
|
uint64_t session_token{ 0 };
|
|
};
|
|
|
|
// sent by the server instead of SERVER_HELLO when the client cannot join;
|
|
// carries a human readable reason so the player learns what went wrong
|
|
struct server_reject : public message
|
|
{
|
|
server_reject() : message(SERVER_REJECT) {}
|
|
|
|
std::string reason;
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
struct server_hello : public message
|
|
{
|
|
server_hello() : message(SERVER_HELLO) {}
|
|
|
|
uint32_t seed;
|
|
int64_t timestamp;
|
|
// settings the server imposes on the whole session, see network/session.h
|
|
int64_t config;
|
|
std::string scenario;
|
|
// build identification of the server, informational only
|
|
std::string app_version;
|
|
// identity assigned to the joining peer for the rest of the session
|
|
uint32_t peer_id{ PEER_NONE };
|
|
// hand this back on a later connection to be recognised as the same participant
|
|
uint64_t session_token{ 0 };
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
// authoritative roster of the vehicles a player may take over, broadcast by the server
|
|
// whenever it changes (and periodically, so that a peer which just went active gets one)
|
|
struct vehicle_list : public message
|
|
{
|
|
vehicle_list() : message(VEHICLE_LIST) {}
|
|
|
|
std::vector<vehicle_entry> vehicles;
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
// sent once the joining peer has the scenario loaded and can take a snapshot
|
|
struct client_ready : public message
|
|
{
|
|
client_ready() : message(CLIENT_READY) {}
|
|
|
|
std::string scenario;
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
// the state of the world as of one particular tick, handed to a peer that is joining.
|
|
// this is what replaces replaying the whole session from its first frame
|
|
struct snapshot : public message
|
|
{
|
|
snapshot() : message(SNAPSHOT) {}
|
|
|
|
uint64_t tick{ 0 };
|
|
std::string blob;
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
// a peer telling the server its world has drifted too far to carry on, and asking to be
|
|
// put back in line
|
|
struct request_resync : public message
|
|
{
|
|
request_resync() : message(REQUEST_RESYNC) {}
|
|
|
|
uint64_t tick{ 0 };
|
|
uint64_t state_hash{ 0 };
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
// a peer asking the server to be put on the crew of a vehicle
|
|
struct claim_vehicle : public message
|
|
{
|
|
claim_vehicle() : message(CLAIM_VEHICLE) {}
|
|
|
|
uint32_t entity_id{ ENTITY_NONE };
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
// answer to a claim the server accepted
|
|
struct claim_granted : public message
|
|
{
|
|
claim_granted() : message(CLAIM_GRANTED) {}
|
|
|
|
uint32_t entity_id{ ENTITY_NONE };
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
// answer to a claim the server refused, with a reason the lobby can show
|
|
struct claim_denied : public message
|
|
{
|
|
claim_denied() : message(CLAIM_DENIED) {}
|
|
|
|
uint32_t entity_id{ ENTITY_NONE };
|
|
std::string reason;
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
// a peer stepping off the crew of a vehicle
|
|
struct leave_vehicle : public message
|
|
{
|
|
leave_vehicle() : message(LEAVE_VEHICLE) {}
|
|
|
|
uint32_t entity_id{ ENTITY_NONE };
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
// authoritative crew of one vehicle, broadcast whenever it changes
|
|
struct crew_update : public message
|
|
{
|
|
crew_update() : message(CREW_UPDATE) {}
|
|
|
|
uint32_t entity_id{ ENTITY_NONE };
|
|
std::vector<PeerId> crew;
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
struct request_command : public message
|
|
{
|
|
request_command(type_e type) : message(type) {}
|
|
request_command() : message(REQUEST_COMMAND) {}
|
|
|
|
command_queue::commands_map commands;
|
|
// logical step the sender was on when it produced these. the protocol is anchored to
|
|
// this counter rather than to whatever frame the renderer happened to be drawing
|
|
uint64_t tick{ 0 };
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
struct frame_info : public request_command
|
|
{
|
|
frame_info() : request_command(FRAME_INFO) {}
|
|
|
|
double render_dt;
|
|
double dt;
|
|
// digest of the authoritative world after this step; a client compares its own
|
|
uint64_t state_hash{ 0 };
|
|
uint32_t state_hash_version{ 0 };
|
|
|
|
virtual void serialize(std::ostream &stream) const override;
|
|
virtual void deserialize(std::istream &stream) override;
|
|
};
|
|
|
|
std::shared_ptr<message> deserialize_message(std::istream &stream);
|
|
void serialize_message(const message &msg, std::ostream &stream);
|
|
} // namespace network
|