From 947239f4b165751515aa02175a2e2b243b525c0b Mon Sep 17 00:00:00 2001 From: teinarss Date: Mon, 14 Jun 2021 21:04:59 +0200 Subject: [PATCH] Refactor server orders --- OpenRA.Game/Network/Order.cs | 10 +++++++ OpenRA.Game/Network/OrderManager.cs | 8 +++-- OpenRA.Game/Network/ReplayConnection.cs | 2 +- OpenRA.Game/Server/Server.cs | 39 ++++++++++++++++++------- 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/OpenRA.Game/Network/Order.cs b/OpenRA.Game/Network/Order.cs index f3000ffc6f91..8928b268eb76 100644 --- a/OpenRA.Game/Network/Order.cs +++ b/OpenRA.Game/Network/Order.cs @@ -199,6 +199,12 @@ public static Order Deserialize(World world, BinaryReader r) return new Order(name, null, false) { Type = OrderType.Handshake, TargetString = targetString }; } + case OrderType.Disconnect: + r.ReadString(); + var extraData1 = r.ReadUInt32(); + + return new Order("disconnect", null, false) { Type = OrderType.Disconnect, ExtraData = extraData1 }; + default: { Log.Write("debug", "Received unknown order with type {0}", type); @@ -310,6 +316,10 @@ public byte[] Serialize() switch (Type) { + case OrderType.Disconnect: + w.Write(ExtraData); + break; + case OrderType.Handshake: { // Changing the Handshake order format will break cross-version switching diff --git a/OpenRA.Game/Network/OrderManager.cs b/OpenRA.Game/Network/OrderManager.cs index 7562fff0a5ed..d7052f76ee75 100644 --- a/OpenRA.Game/Network/OrderManager.cs +++ b/OpenRA.Game/Network/OrderManager.cs @@ -131,8 +131,12 @@ public void TickImmediate() return; var frame = BitConverter.ToInt32(packet, 0); - if (packet.Length == 5 && packet[4] == (byte)OrderType.Disconnect) - pendingPackets.Remove(clientId); + if (packet.Length == 20 && packet[4] == (byte)OrderType.Disconnect) + { + var disconnectPacket = packet.ToOrderList(World).First(); + + pendingPackets.Remove((int)disconnectPacket.ExtraData); + } else if (packet.Length > 4 && packet[4] == (byte)OrderType.SyncHash) { if (packet.Length != 4 + Order.SyncHashOrderLength) diff --git a/OpenRA.Game/Network/ReplayConnection.cs b/OpenRA.Game/Network/ReplayConnection.cs index b43a819c8a52..42fa1bbdc3d2 100644 --- a/OpenRA.Game/Network/ReplayConnection.cs +++ b/OpenRA.Game/Network/ReplayConnection.cs @@ -115,7 +115,7 @@ public ReplayConnection(string replayFilename) continue; var packet = tmpPacketPair.Packet; - if (packet.Length == 5 && packet[4] == (byte)OrderType.Disconnect) + if (packet.Length == 20 && packet[4] == (byte)OrderType.Disconnect) { var lastClientFrame = lastClientsFrame[client]; var lastFramePacket = BitConverter.GetBytes(lastClientFrame); diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index fb0fdf357eab..d6c178e6de1e 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -743,20 +743,38 @@ public void DispatchOrdersToClients(Connection conn, int frame, byte[] data) if (c != conn && c.Validated) DispatchFrameToClient(c, from, frameData); + RecordOrder(frame, data, @from); + } + + void RecordOrder(int frame, byte[] data, int @from) + { if (recorder != null) { - recorder.ReceiveFrame(from, frame, data); + recorder.ReceiveFrame(@from, frame, data); if (data.Length > 0 && data[0] == (byte)OrderType.SyncHash) { if (data.Length == Order.SyncHashOrderLength) HandleSyncOrder(frame, data); else - Log.Write("server", $"Dropped sync order with length {data.Length} from client {from}. Expected length {Order.SyncHashOrderLength}."); + Log.Write("server", + $"Dropped sync order with length {data.Length} from client {@from}. Expected length {Order.SyncHashOrderLength}."); } } } + public void DispatchServerOrdersToClients(byte[] data) + { + var from = 0; + var frame = 0; + var frameData = CreateFrame(from, frame, data); + foreach (var c in Conns.ToList()) + if (c.Validated) + DispatchFrameToClient(c, from, frameData); + + RecordOrder(frame, data, @from); + } + public void DispatchOrders(Connection conn, int frame, byte[] data) { if (frame == 0 && conn != null) @@ -1039,7 +1057,9 @@ public void DropClient(Connection toDrop) } } - DispatchOrders(toDrop, toDrop.MostRecentFrame, new[] { (byte)OrderType.Disconnect }); + var order = new Order("disconnect", null, false) { Type = OrderType.Disconnect, ExtraData = (uint)toDrop.PlayerIndex }; + + DispatchServerOrdersToClients(order.Serialize()); // All clients have left: clean up if (!Conns.Any(c => c.Validated)) @@ -1061,7 +1081,7 @@ public void SyncLobbyInfo() lock (LobbyInfo) { if (State == ServerState.WaitingPlayers) // Don't do this while the game is running, it breaks things! - DispatchOrders(null, 0, Order.FromTargetString("SyncInfo", LobbyInfo.Serialize(), true).Serialize()); + DispatchServerOrdersToClients(Order.FromTargetString("SyncInfo", LobbyInfo.Serialize(), true).Serialize()); foreach (var t in serverTraits.WithInterface()) t.LobbyInfoSynced(this); @@ -1078,7 +1098,7 @@ public void SyncLobbyClients() // TODO: Only need to sync the specific client that has changed to avoid conflicts! var clientData = LobbyInfo.Clients.Select(client => client.Serialize()).ToList(); - DispatchOrders(null, 0, Order.FromTargetString("SyncLobbyClients", clientData.WriteToString(), true).Serialize()); + DispatchServerOrdersToClients(Order.FromTargetString("SyncLobbyClients", clientData.WriteToString(), true).Serialize()); foreach (var t in serverTraits.WithInterface()) t.LobbyInfoSynced(this); @@ -1095,7 +1115,7 @@ public void SyncLobbySlots() // TODO: Don't sync all the slots if just one changed! var slotData = LobbyInfo.Slots.Select(slot => slot.Value.Serialize()).ToList(); - DispatchOrders(null, 0, Order.FromTargetString("SyncLobbySlots", slotData.WriteToString(), true).Serialize()); + DispatchServerOrdersToClients(Order.FromTargetString("SyncLobbySlots", slotData.WriteToString(), true).Serialize()); foreach (var t in serverTraits.WithInterface()) t.LobbyInfoSynced(this); @@ -1111,7 +1131,7 @@ public void SyncLobbyGlobalSettings() { var sessionData = new List { LobbyInfo.GlobalSettings.Serialize() }; - DispatchOrders(null, 0, Order.FromTargetString("SyncLobbyGlobalSettings", sessionData.WriteToString(), true).Serialize()); + DispatchServerOrdersToClients(Order.FromTargetString("SyncLobbyGlobalSettings", sessionData.WriteToString(), true).Serialize()); foreach (var t in serverTraits.WithInterface()) t.LobbyInfoSynced(this); @@ -1126,7 +1146,7 @@ public void SyncClientPing() var clientPings = LobbyInfo.ClientPings.Select(ping => ping.Serialize()).ToList(); // Note that syncing pings doesn't trigger INotifySyncLobbyInfo - DispatchOrders(null, 0, Order.FromTargetString("SyncClientPings", clientPings.WriteToString(), true).Serialize()); + DispatchServerOrdersToClients(Order.FromTargetString("SyncClientPings", clientPings.WriteToString(), true).Serialize()); } } @@ -1194,8 +1214,7 @@ public void StartGame() } } - DispatchOrders(null, 0, - Order.FromTargetString("StartGame", startGameData, true).Serialize()); + DispatchServerOrdersToClients(Order.FromTargetString("StartGame", startGameData, true).Serialize()); foreach (var t in serverTraits.WithInterface()) t.GameStarted(this);