mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-19 02:39:19 +02:00
multiplayer: replicate what a vehicle is heard and seen doing
The horn never reached anybody else. It is not a command a bystander can carry out: OnCommand_hornlowactivate sets MoverParameters->WarningSignal from inside a cab, and a peer that is not sitting in that cab has no TTrain for the vehicle, so the command was dropped on arrival. Only the result of it can travel, and it was not being sent. The vehicle state now carries what a vehicle is heard and seen doing rather than only what it is being told to do: the horn flags, the emergency brake horn and its alarm chain, the wheel revolutions and the engine revolutions. The last two are what turn the driven wheels and set the engine note, so somebody else's locomotive no longer sounds and looks like it is standing still while it rolls past. The state also goes out a little sooner, every sixth frame instead of every tenth: a horn can be pressed and let go inside a couple of frames, and an update that arrives after it is over is no use.
This commit is contained in:
@@ -34,7 +34,9 @@ namespace network
|
||||
|
||||
// how often the authoritative state goes out, and how often it goes out whole
|
||||
// rather than as what changed since the last one
|
||||
static const int STATE_INTERVAL_FRAMES = 10;
|
||||
// a horn can be pressed and let go inside a couple of frames, so the state does not
|
||||
// wait long before it goes out
|
||||
static const int STATE_INTERVAL_FRAMES = 6;
|
||||
static const int STATE_FULL_EVERY = 60;
|
||||
|
||||
std::vector<vehicle_entry> last_published_list;
|
||||
|
||||
@@ -207,6 +207,13 @@ struct vehicle_state
|
||||
std::array<bool, 2> pantdisabled{{false, false}};
|
||||
std::array<bool, 2> pantactive{{false, false}};
|
||||
int32_t lights[2]{0, 0};
|
||||
// what the vehicle is heard and seen doing. a peer that is not in this cab has no
|
||||
// TTrain for it, so the commands that set these never reach it - only the result does
|
||||
int32_t warningsignal{0};
|
||||
int32_t emergencywarningsignal{0};
|
||||
bool alarmchain{false};
|
||||
double wheelrevolutions{0.0};
|
||||
double enginerevolutions{0.0};
|
||||
// door open/close intent, one entry per side; the local model derives the rest
|
||||
std::array<bool, 2> dooropen{{false, false}};
|
||||
std::array<bool, 2> doorpermit{{false, false}};
|
||||
@@ -249,6 +256,11 @@ void serialize_vehicle(std::ostream &Stream, vehicle_state const &State)
|
||||
}
|
||||
sn_utils::ls_int32(Stream, State.lights[0]);
|
||||
sn_utils::ls_int32(Stream, State.lights[1]);
|
||||
sn_utils::ls_int32(Stream, State.warningsignal);
|
||||
sn_utils::ls_int32(Stream, State.emergencywarningsignal);
|
||||
sn_utils::s_bool(Stream, State.alarmchain);
|
||||
sn_utils::ls_float64(Stream, State.wheelrevolutions);
|
||||
sn_utils::ls_float64(Stream, State.enginerevolutions);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
sn_utils::s_bool(Stream, State.dooropen[i]);
|
||||
@@ -295,6 +307,11 @@ vehicle_state deserialize_vehicle(std::istream &Stream)
|
||||
}
|
||||
state.lights[0] = sn_utils::ld_int32(Stream);
|
||||
state.lights[1] = sn_utils::ld_int32(Stream);
|
||||
state.warningsignal = sn_utils::ld_int32(Stream);
|
||||
state.emergencywarningsignal = sn_utils::ld_int32(Stream);
|
||||
state.alarmchain = sn_utils::d_bool(Stream);
|
||||
state.wheelrevolutions = sn_utils::ld_float64(Stream);
|
||||
state.enginerevolutions = sn_utils::ld_float64(Stream);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
state.dooropen[i] = sn_utils::d_bool(Stream);
|
||||
@@ -345,6 +362,11 @@ vehicle_state read_from(TDynamicObject const &Vehicle)
|
||||
}
|
||||
state.lights[0] = mover.iLights[0];
|
||||
state.lights[1] = mover.iLights[1];
|
||||
state.warningsignal = mover.WarningSignal;
|
||||
state.emergencywarningsignal = mover.EmergencyBrakeWarningSignal;
|
||||
state.alarmchain = mover.AlarmChainFlag;
|
||||
state.wheelrevolutions = mover.nrot;
|
||||
state.enginerevolutions = mover.enrot;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
state.dooropen[i] = mover.Doors.instances[i].is_open;
|
||||
@@ -403,6 +425,14 @@ void apply_controls(TDynamicObject &Vehicle, vehicle_state const &State)
|
||||
mover.iLights[0] = State.lights[0];
|
||||
mover.iLights[1] = State.lights[1];
|
||||
|
||||
// the horn, the wheels and the engine note. these are set from a cab this peer does
|
||||
// not have, so nothing but the result of them ever reaches it
|
||||
mover.WarningSignal = State.warningsignal;
|
||||
mover.EmergencyBrakeWarningSignal = State.emergencywarningsignal;
|
||||
mover.AlarmChainFlag = State.alarmchain;
|
||||
mover.nrot = State.wheelrevolutions;
|
||||
mover.enrot = State.enginerevolutions;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
auto const side = (i == 0 ? side::right : side::left);
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace network
|
||||
{
|
||||
|
||||
// layout of the snapshot container. a reader refuses a blob it does not understand
|
||||
constexpr uint32_t SNAPSHOT_VERSION = 2;
|
||||
constexpr uint32_t SNAPSHOT_VERSION = 3;
|
||||
|
||||
// the sections a snapshot is built from. a reader skips over any id it does not know,
|
||||
// which is what makes the format extensible: a peer built before a section existed can
|
||||
|
||||
Reference in New Issue
Block a user