From 8e1946345091948d78c8c7c04c57d0dbc4f73970 Mon Sep 17 00:00:00 2001 From: tomas Date: Tue, 15 Mar 2022 19:59:00 +0100 Subject: [PATCH] Fix desync handling --- OpenRA.Game/Network/Connection.cs | 17 ++++++++++------- OpenRA.Game/Network/OrderManager.cs | 9 ++++++++- OpenRA.Game/World.cs | 7 +++++++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/OpenRA.Game/Network/Connection.cs b/OpenRA.Game/Network/Connection.cs index eda7dedfe5..cb0584dc54 100644 --- a/OpenRA.Game/Network/Connection.cs +++ b/OpenRA.Game/Network/Connection.cs @@ -100,9 +100,9 @@ namespace OpenRA.Network { public readonly ConnectionTarget Target; internal ReplayRecorder Recorder { get; private set; } - - readonly List queuedSyncPackets = new List(); readonly Queue<(int Frame, int SyncHash, ulong DefeatState)> sentSync = new Queue<(int, int, ulong)>(); + readonly Queue<(int Frame, int SyncHash, ulong DefeatState)> queuedSyncPackets = new Queue<(int, int, ulong)>(); + readonly Queue<(int Frame, OrderPacket Orders)> sentOrders = new Queue<(int, OrderPacket)>(); readonly Queue sentImmediateOrders = new Queue(); readonly ConcurrentQueue<(int FromClient, byte[] Data)> receivedPackets = new ConcurrentQueue<(int, byte[])>(); @@ -244,13 +244,12 @@ namespace OpenRA.Network void IConnection.SendSync(int frame, int syncHash, ulong defeatState) { - var sync = (frame, syncHash, defeatState); - sentSync.Enqueue(sync); - // Send sync packets together with the next set of orders. // This was originally explained as reducing network bandwidth // (TCP overhead?), but the original discussions have been lost to time. - queuedSyncPackets.Add(OrderIO.SerializeSync(sync)); + // Add the sync packets to the send queue before adding them to the local sync queue in the Send() method. + // Otherwise the client will process the local sync queue before sending the packet. + queuedSyncPackets.Enqueue((frame, syncHash, defeatState)); } void Send(byte[] packet) @@ -261,10 +260,14 @@ namespace OpenRA.Network ms.WriteArray(BitConverter.GetBytes(packet.Length)); ms.WriteArray(packet); - foreach (var q in queuedSyncPackets) + foreach (var s in queuedSyncPackets) { + var q = OrderIO.SerializeSync(s); + ms.WriteArray(BitConverter.GetBytes(q.Length)); ms.WriteArray(q); + + sentSync.Enqueue(s); } queuedSyncPackets.Clear(); diff --git a/OpenRA.Game/Network/OrderManager.cs b/OpenRA.Game/Network/OrderManager.cs index 26ffa0f8ea..4406844f80 100644 --- a/OpenRA.Game/Network/OrderManager.cs +++ b/OpenRA.Game/Network/OrderManager.cs @@ -59,6 +59,7 @@ namespace OpenRA.Network bool generateSyncReport = false; int sentOrdersFrame = 0; float tickScale = 1f; + bool outOfSync = false; public struct ClientOrder { @@ -73,8 +74,14 @@ namespace OpenRA.Network void OutOfSync(int frame) { + if (outOfSync) + return; + syncReport.DumpSyncReport(frame); - throw new InvalidOperationException($"Out of sync in frame {frame}.\n Compare syncreport.log with other players."); + World.OutOfSync(); + outOfSync = true; + + TextNotificationsManager.AddSystemLine($"Out of sync in frame {frame}.\nCompare syncreport.log with other players."); } public void StartGame() diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index f6d2718e54..2ad159b732 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -598,6 +598,13 @@ namespace OpenRA Game.FinishBenchmark(); } + + public void OutOfSync() + { + EndGame(); + SetPauseState(true); + PauseStateLocked = true; + } } public readonly struct TraitPair : IEquatable>