17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-18 07:59:19 +02:00
Files
maszyna/network/message.h
Hirek193 3f62fd5927 multiplayer stage 3: crew model, claim handshake and AI handover
A vehicle is not owned by one player: two people share a cab, so the session
needs a crew relation rather than an owner field. The server keeps it and is
the only one allowed to change it.

- network/session: vehicle_crew { entity_id, crew, ai_before_claim } and a
  crew_registry holding the roster. the host goes through exactly the same
  path as a remote peer (claim -> crew -> grant), only without transport
- CLAIM_VEHICLE / CLAIM_GRANTED / CLAIM_DENIED / LEAVE_VEHICLE / CREW_UPDATE;
  the server validates the vehicle exists, is present in the scenario and has
  room in the crew, and answers a refusal with a reason the lobby shows
- the cab of a claimed vehicle is created by the authority posting the
  ordinary replicated entervehicle, so every peer builds it and the vehicle is
  never moved. the claiming peer only walks in once the cab appears locally
- AI transitions follow the crew size: 0 -> 1 remembers whether an AI was
  really driving and takes the vehicle over, 1 -> 2 and 2 -> 1 change nothing,
  1 -> 0 hands the vehicle back but only if there was an AI driver to begin
  with. driver mode no longer fires aidriverdisable of its own in multiplayer
- losing a connection removes that peer from every crew it was on; a vehicle
  with somebody still on board carries on untouched
- the lobby lists who is on board, offers "join crew" for a vehicle another
  player already occupies, and lets a player step off

The AI and cab handling runs as a reconciliation pass rather than as edge
triggered actions, so a request that has not taken effect yet (the cab needs a
frame to appear) is simply repeated, with a cooldown to keep it off the wire.
2026-09-06 18:08:06 +00:00

171 lines
4.3 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,
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;
};
// 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;
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 };
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;
};
// 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;
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;
double sync;
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