From 53cda0cbc2b504293802a9f1f1db452915f7211a Mon Sep 17 00:00:00 2001 From: MrMaho Date: Sun, 27 Sep 2026 16:51:48 +0200 Subject: [PATCH] Relay vehicle controls; on shutdown tell players to reconnect (restart) instead of a final disconnect Co-Authored-By: Claude Opus 5.5 --- GameServer.cs | 7 ++++--- Protocol.cs | 3 ++- Tests/Program.cs | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/GameServer.cs b/GameServer.cs index 7adf782..4faf01f 100644 --- a/GameServer.cs +++ b/GameServer.cs @@ -162,8 +162,9 @@ public sealed class GameServer foreach (var c in clients.Values) { - // Grund mitschicken: die Spieler sehen ihn im Hauptmenü - if (c.State == ClientState.Joined) c.Conn.Send(MsgType.Reject, Wire.Build(w => w.Write("The server was shut down."))); + // Meist ein Neustart (Update, docker compose up): die Spieler verbinden sich automatisch neu, sobald der + // Server wieder da ist. Bleibt er aus, bekommen sie nach ein paar Versuchen einen Hinweis im Hauptmenü. + if (c.State == ClientState.Joined) c.Conn.Send(MsgType.Reconnect, Wire.Build(w => w.Write("The server is restarting - reconnecting..."))); c.Conn.CloseAfterSend("Server shutting down"); } // Kurz warten, bis die Spieler die Meldung gelesen haben (sauber trennen statt hart abbrechen) @@ -291,7 +292,7 @@ public sealed class GameServer t is MsgType.Player or MsgType.ObjStates or MsgType.ObjOwn or MsgType.ObjRelease or MsgType.FsmEvent or MsgType.VehicleFx or MsgType.WorldTime or MsgType.MoneyDelta or MsgType.DoorState or MsgType.Chat or MsgType.VarSync or MsgType.SpawnItem or MsgType.ItemAppeared or MsgType.ObjDestroy or MsgType.VehicleDamage - or MsgType.TrafficStates or MsgType.WorldVars or MsgType.HingeStates; + or MsgType.TrafficStates or MsgType.WorldVars or MsgType.HingeStates or MsgType.VehicleControls; /// Uhrzeit/Wetter gibt der Spieler mit der kleinsten ID vor (so rechnen es auch die Clients). int WorldAuthorityId => clients.Values.Where(c => c.State == ClientState.Joined).Select(c => c.Id).DefaultIfEmpty(-1).Min(); diff --git a/Protocol.cs b/Protocol.cs index 8f44b8a..b69aa29 100644 --- a/Protocol.cs +++ b/Protocol.cs @@ -46,7 +46,8 @@ public enum MsgType : byte VehicleDamage = 39, // Unfallschaden (verformte Karosserie): int Mesh-Schlüssel, int Eckpunkte, int n, je [int Index, 3 float] TrafficStates = 40, // Verkehr, nur von der Welt-Autorität: int n, je [int Schlüssel, 3 float Pos, 4 float Rot, 3 float Geschw.] WorldVars = 41, // Jobs/Laden: int n, je [int Schlüssel, byte Typ, Wert] - HingeStates = 42 // Autotüren/Haube/Kofferraum: int n, je [int Schlüssel, 3 float Pos, 4 float Rot relativ zum Auto] + HingeStates = 42, // Autotüren/Haube/Kofferraum: int n, je [int Schlüssel, 3 float Pos, 4 float Rot relativ zum Auto] + VehicleControls = 43 // Zündung/Motor/Licht ...: int n, je [int FSM-Schlüssel, string Zustand] } public readonly record struct Message(MsgType Type, byte[] Payload) diff --git a/Tests/Program.cs b/Tests/Program.cs index 8cc49c8..f0bd457 100644 --- a/Tests/Program.cs +++ b/Tests/Program.cs @@ -128,6 +128,8 @@ try Check(await bob.WaitFor(MsgType.WorldVars) != null, "Job/shop values are relayed"); alice.Send(MsgType.HingeStates, Wire.Build(w => { w.Write(0); })); Check(await bob.WaitFor(MsgType.HingeStates) != null, "Car door angles are relayed"); + alice.Send(MsgType.VehicleControls, Wire.Build(w => { w.Write(1); w.Write(123); w.Write("Lights"); })); + Check(await bob.WaitFor(MsgType.VehicleControls) != null, "Vehicle controls (ignition, lights ...) are relayed"); byte[] trafficPayload = Wire.Build(w => { w.Write(0); }); bob.Send(MsgType.TrafficStates, trafficPayload); Check(await alice.WaitFor(MsgType.TrafficStates, 800) == null, "Traffic from a player who is not the world authority is ignored");