17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 21:29:19 +02:00
Files
maszyna/network/manager.cpp
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

183 lines
4.4 KiB
C++

/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "network/manager.h"
#include "simulation/simulation.h"
#include "utilities/Logs.h"
#include "utilities/Globals.h"
network::server_manager::server_manager()
{
backbuffer = std::make_shared<std::fstream>("backbuffer.bin", std::ios::out | std::ios::in | std::ios::trunc | std::ios::binary);
}
command_queue::commands_map network::server_manager::pop_commands()
{
command_queue::commands_map map;
for (auto srv : servers)
add_to_dequemap(map, srv->pop_commands());
return map;
}
void network::server_manager::push_delta(double render_dt, double dt, double sync, const command_queue::commands_map &commands)
{
if (dt == 0.0 && commands.empty())
return;
frame_info msg;
msg.render_dt = render_dt;
msg.dt = dt;
msg.sync = sync;
msg.commands = commands;
for (auto srv : servers)
srv->push_delta(msg);
serialize_message(msg, *backbuffer.get());
}
void network::server_manager::create_server(const std::string &backend, const std::string &conf)
{
auto it = backend_list().find(backend);
if (it == backend_list().end()) {
ErrorLog("net: unknown backend: " + backend);
return;
}
servers.emplace_back(it->second->create_server(backbuffer, conf));
}
network::manager::manager()
{
}
void network::server_manager::publish_vehicle_list()
{
if (Entities.empty())
return;
Entities.refresh();
// resend on every change, and once in a while regardless, so that a peer which has
// just finished catching up does not have to wait for somebody to move
bool const changed = (Entities.entries() != last_published_list);
if (!changed && --publish_countdown > 0)
return;
last_published_list = Entities.entries();
publish_countdown = PUBLISH_INTERVAL_FRAMES;
vehicle_list msg;
msg.vehicles = last_published_list;
for (auto srv : servers)
srv->push_message(msg);
}
void network::server_manager::update_crews()
{
Crews.reconcile();
if (--crew_publish_countdown <= 0) {
// peers that joined after somebody took a vehicle over have to learn about it too
crew_publish_countdown = PUBLISH_INTERVAL_FRAMES;
Crews.mark_all_pending();
}
auto const changed = Crews.take_pending_updates();
for (NetworkEntityId const id : changed) {
crew_update msg;
msg.entity_id = id;
msg.crew = Crews.crew_of(id);
for (auto srv : servers)
srv->push_message(msg);
}
}
void network::server_manager::apply_local_claim(NetworkEntityId entity_id)
{
auto const result = Crews.claim(PEER_HOST, entity_id);
if (result == claim_result::granted || result == claim_result::already_member) {
Global.network_lobby_message.clear();
Global.network_pending_vehicle = Entities.name_of(entity_id);
}
else {
WriteLog("net: refused local claim of vehicle " + std::to_string(entity_id) + ": " + describe(result), logtype::net);
Global.network_lobby_message = describe(result);
}
}
void network::server_manager::apply_local_leave(NetworkEntityId entity_id)
{
if (Crews.leave(PEER_HOST, entity_id))
Global.network_leave_pending = true;
}
void network::manager::request_claim(NetworkEntityId entity_id)
{
if (client) {
client->send_claim(entity_id);
return;
}
if (servers)
servers->apply_local_claim(entity_id);
}
void network::manager::request_leave(NetworkEntityId entity_id)
{
if (client) {
client->send_leave(entity_id);
// the server owns the roster, but stepping out of our own cab is a local matter
Global.network_leave_pending = true;
return;
}
if (servers)
servers->apply_local_leave(entity_id);
}
void network::manager::update()
{
for (auto &backend : backend_list())
backend.second->update();
if (servers && simulation::is_ready) {
servers->update_crews();
servers->publish_vehicle_list();
}
if (client)
client->update();
}
void network::manager::create_server(const std::string &backend, const std::string &conf)
{
servers.emplace();
servers->create_server(backend, conf);
}
void network::manager::connect(const std::string &backend, const std::string &conf)
{
auto it = backend_list().find(backend);
if (it == backend_list().end()) {
ErrorLog("net: unknown backend: " + backend);
return;
}
client = it->second->create_client(conf);
}
//std::unordered_map<std::string, std::shared_ptr<network::backend_manager>> network::backend_list;