mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-18 03:19:19 +02:00
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.
259 lines
7.1 KiB
C++
259 lines
7.1 KiB
C++
#include "stdafx.h"
|
|
#include "network/message.h"
|
|
#include "scene/sn_utils.h"
|
|
|
|
void network::client_hello::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_int32(stream, version);
|
|
sn_utils::ls_uint32(stream, start_packet);
|
|
sn_utils::s_str(stream, app_version);
|
|
}
|
|
|
|
void network::client_hello::deserialize(std::istream &stream)
|
|
{
|
|
version = sn_utils::ld_int32(stream);
|
|
start_packet = sn_utils::ld_uint32(stream);
|
|
app_version = sn_utils::d_str(stream);
|
|
}
|
|
|
|
void network::server_reject::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::s_str(stream, reason);
|
|
}
|
|
|
|
void network::server_reject::deserialize(std::istream &stream)
|
|
{
|
|
reason = sn_utils::d_str(stream);
|
|
}
|
|
|
|
void network::server_hello::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_uint32(stream, seed);
|
|
sn_utils::ls_int64(stream, timestamp);
|
|
sn_utils::ls_int64(stream, config);
|
|
sn_utils::s_str(stream, scenario);
|
|
sn_utils::s_str(stream, app_version);
|
|
sn_utils::ls_uint32(stream, peer_id);
|
|
}
|
|
|
|
void network::server_hello::deserialize(std::istream &stream)
|
|
{
|
|
seed = sn_utils::ld_uint32(stream);
|
|
timestamp = sn_utils::ld_int64(stream);
|
|
config = sn_utils::ld_int64(stream);
|
|
scenario = sn_utils::d_str(stream);
|
|
app_version = sn_utils::d_str(stream);
|
|
peer_id = sn_utils::ld_uint32(stream);
|
|
}
|
|
|
|
void network::vehicle_list::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_uint32(stream, (uint32_t)vehicles.size());
|
|
for (auto const &entry : vehicles)
|
|
{
|
|
sn_utils::ls_uint32(stream, entry.id);
|
|
sn_utils::s_str(stream, entry.name);
|
|
sn_utils::s_uint8(stream, entry.crew_count);
|
|
sn_utils::s_uint8(stream, entry.crew_capacity);
|
|
sn_utils::s_uint8(stream, (uint8_t)((entry.ai_active ? 1 : 0) | (entry.claimable ? 2 : 0)));
|
|
}
|
|
}
|
|
|
|
void network::vehicle_list::deserialize(std::istream &stream)
|
|
{
|
|
vehicles.clear();
|
|
|
|
uint32_t const count = sn_utils::ld_uint32(stream);
|
|
vehicles.reserve(count);
|
|
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
vehicle_entry entry;
|
|
entry.id = sn_utils::ld_uint32(stream);
|
|
entry.name = sn_utils::d_str(stream);
|
|
entry.crew_count = sn_utils::d_uint8(stream);
|
|
entry.crew_capacity = sn_utils::d_uint8(stream);
|
|
uint8_t const flags = sn_utils::d_uint8(stream);
|
|
entry.ai_active = (flags & 1) != 0;
|
|
entry.claimable = (flags & 2) != 0;
|
|
vehicles.emplace_back(entry);
|
|
}
|
|
}
|
|
|
|
void network::claim_vehicle::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_uint32(stream, entity_id);
|
|
}
|
|
|
|
void network::claim_vehicle::deserialize(std::istream &stream)
|
|
{
|
|
entity_id = sn_utils::ld_uint32(stream);
|
|
}
|
|
|
|
void network::claim_granted::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_uint32(stream, entity_id);
|
|
}
|
|
|
|
void network::claim_granted::deserialize(std::istream &stream)
|
|
{
|
|
entity_id = sn_utils::ld_uint32(stream);
|
|
}
|
|
|
|
void network::claim_denied::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_uint32(stream, entity_id);
|
|
sn_utils::s_str(stream, reason);
|
|
}
|
|
|
|
void network::claim_denied::deserialize(std::istream &stream)
|
|
{
|
|
entity_id = sn_utils::ld_uint32(stream);
|
|
reason = sn_utils::d_str(stream);
|
|
}
|
|
|
|
void network::leave_vehicle::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_uint32(stream, entity_id);
|
|
}
|
|
|
|
void network::leave_vehicle::deserialize(std::istream &stream)
|
|
{
|
|
entity_id = sn_utils::ld_uint32(stream);
|
|
}
|
|
|
|
void network::crew_update::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_uint32(stream, entity_id);
|
|
sn_utils::ls_uint32(stream, (uint32_t)crew.size());
|
|
for (PeerId const peer : crew)
|
|
sn_utils::ls_uint32(stream, peer);
|
|
}
|
|
|
|
void network::crew_update::deserialize(std::istream &stream)
|
|
{
|
|
entity_id = sn_utils::ld_uint32(stream);
|
|
|
|
crew.clear();
|
|
uint32_t const count = sn_utils::ld_uint32(stream);
|
|
crew.reserve(count);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
crew.emplace_back(sn_utils::ld_uint32(stream));
|
|
}
|
|
|
|
void ::network::request_command::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_uint32(stream, commands.size());
|
|
for (auto const &kv : commands)
|
|
{
|
|
sn_utils::ls_uint32(stream, kv.first);
|
|
sn_utils::ls_uint32(stream, kv.second.size());
|
|
for (command_data const &data : kv.second)
|
|
{
|
|
sn_utils::ls_uint32(stream, (uint32_t)data.command);
|
|
sn_utils::ls_int32(stream, data.action);
|
|
sn_utils::ls_float64(stream, data.param1);
|
|
sn_utils::ls_float64(stream, data.param2);
|
|
sn_utils::ls_float64(stream, data.time_delta);
|
|
|
|
sn_utils::s_bool(stream, data.freefly);
|
|
sn_utils::s_vec3(stream, data.location);
|
|
|
|
sn_utils::s_str(stream, data.payload);
|
|
}
|
|
}
|
|
}
|
|
|
|
void network::request_command::deserialize(std::istream &stream)
|
|
{
|
|
uint32_t commands_size = sn_utils::ld_uint32(stream);
|
|
for (uint32_t i = 0; i < commands_size; i++)
|
|
{
|
|
uint32_t recipient = sn_utils::ld_uint32(stream);
|
|
uint32_t sequence_size = sn_utils::ld_uint32(stream);
|
|
|
|
command_queue::commanddata_sequence sequence;
|
|
for (uint32_t i = 0; i < sequence_size; i++)
|
|
{
|
|
command_data data;
|
|
data.command = (user_command)sn_utils::ld_uint32(stream);
|
|
data.action = sn_utils::ld_int32(stream);
|
|
data.param1 = sn_utils::ld_float64(stream);
|
|
data.param2 = sn_utils::ld_float64(stream);
|
|
data.time_delta = sn_utils::ld_float64(stream);
|
|
|
|
data.freefly = sn_utils::d_bool(stream);
|
|
data.location = sn_utils::d_vec3(stream);
|
|
|
|
data.payload = sn_utils::d_str(stream);
|
|
|
|
sequence.emplace_back(data);
|
|
}
|
|
|
|
commands.emplace(recipient, sequence);
|
|
}
|
|
}
|
|
|
|
void network::frame_info::serialize(std::ostream &stream) const
|
|
{
|
|
sn_utils::ls_float64(stream, render_dt);
|
|
sn_utils::ls_float64(stream, dt);
|
|
sn_utils::ls_float64(stream, sync);
|
|
|
|
request_command::serialize(stream);
|
|
}
|
|
|
|
void network::frame_info::deserialize(std::istream &stream)
|
|
{
|
|
render_dt = sn_utils::ld_float64(stream);
|
|
dt = sn_utils::ld_float64(stream);
|
|
sync = sn_utils::ld_float64(stream);
|
|
|
|
request_command::deserialize(stream);
|
|
}
|
|
|
|
std::shared_ptr<network::message> network::deserialize_message(std::istream &stream)
|
|
{
|
|
message::type_e type = (message::type_e)sn_utils::ld_uint16(stream);
|
|
|
|
std::shared_ptr<message> msg;
|
|
|
|
if (type == message::CLIENT_HELLO)
|
|
msg = std::make_shared<client_hello>();
|
|
else if (type == message::SERVER_HELLO)
|
|
msg = std::make_shared<server_hello>();
|
|
else if (type == message::FRAME_INFO)
|
|
msg = std::make_shared<frame_info>();
|
|
else if (type == message::REQUEST_COMMAND)
|
|
msg = std::make_shared<request_command>();
|
|
else if (type == message::SERVER_REJECT)
|
|
msg = std::make_shared<server_reject>();
|
|
else if (type == message::VEHICLE_LIST)
|
|
msg = std::make_shared<vehicle_list>();
|
|
else if (type == message::CLAIM_VEHICLE)
|
|
msg = std::make_shared<claim_vehicle>();
|
|
else if (type == message::CLAIM_GRANTED)
|
|
msg = std::make_shared<claim_granted>();
|
|
else if (type == message::CLAIM_DENIED)
|
|
msg = std::make_shared<claim_denied>();
|
|
else if (type == message::LEAVE_VEHICLE)
|
|
msg = std::make_shared<leave_vehicle>();
|
|
else if (type == message::CREW_UPDATE)
|
|
msg = std::make_shared<crew_update>();
|
|
|
|
if (!msg) {
|
|
// unknown message type; hand back a marker the peer handlers treat as a protocol error
|
|
return std::make_shared<message>(message::TYPE_MAX);
|
|
}
|
|
|
|
msg->deserialize(stream);
|
|
|
|
return msg;
|
|
}
|
|
|
|
void network::serialize_message(const message &msg, std::ostream &stream)
|
|
{
|
|
sn_utils::ls_uint16(stream, (uint16_t)msg.type);
|
|
msg.serialize(stream);
|
|
}
|