From 709befda0820d0de50ee323002e4083c7deeba40 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Sun, 9 Aug 2015 20:12:48 +0100 Subject: [PATCH] Sync only once per tick, rather than once per tick and once per order. This greatly improves performance by not syncing the world state for every single order processed as this becomes very expensive, at the cost of being unable to directly pinpoint the order that causes a desync. Instead the granularity of detecting desyncs is reduced to the tick level. --- OpenRA.Game/Network/OrderIO.cs | 5 ++-- OpenRA.Game/Network/OrderManager.cs | 44 ++--------------------------- 2 files changed, 5 insertions(+), 44 deletions(-) diff --git a/OpenRA.Game/Network/OrderIO.cs b/OpenRA.Game/Network/OrderIO.cs index 6e8d1448fb..38e77e3301 100644 --- a/OpenRA.Game/Network/OrderIO.cs +++ b/OpenRA.Game/Network/OrderIO.cs @@ -35,14 +35,13 @@ namespace OpenRA.Network return ret; } - public static byte[] SerializeSync(this List sync) + public static byte[] SerializeSync(int sync) { var ms = new MemoryStream(); using (var writer = new BinaryWriter(ms)) { writer.Write((byte)0x65); - foreach (var s in sync) - writer.Write(s); + writer.Write(sync); } return ms.ToArray(); diff --git a/OpenRA.Game/Network/OrderManager.cs b/OpenRA.Game/Network/OrderManager.cs index 0f7ef48b0b..f6ea45c423 100644 --- a/OpenRA.Game/Network/OrderManager.cs +++ b/OpenRA.Game/Network/OrderManager.cs @@ -43,8 +43,6 @@ namespace OpenRA.Network public bool GameStarted { get { return NetFrameNumber != 0; } } public IConnection Connection { get; private set; } - public readonly int SyncHeaderSize = 9; - List localOrders = new List(); List chatCache = new List(); @@ -55,14 +53,10 @@ namespace OpenRA.Network static void OutOfSync(int frame) { + syncReport.DumpSyncReport(frame); throw new InvalidOperationException("Out of sync in frame {0}.\n Compare syncreport.log with other players.".F(frame)); } - static void OutOfSync(int frame, string blame) - { - throw new InvalidOperationException("Out of sync in frame {0}: Blame {1}.\n Compare syncreport.log with other players.".F(frame, blame)); - } - public void StartGame() { if (GameStarted) return; @@ -145,41 +139,16 @@ namespace OpenRA.Network if (syncForFrame.TryGetValue(frame, out existingSync)) { if (packet.Length != existingSync.Length) - { - syncReport.DumpSyncReport(frame); OutOfSync(frame); - } else - { for (var i = 0; i < packet.Length; i++) - { if (packet[i] != existingSync[i]) - { - syncReport.DumpSyncReport(frame); - - if (i < SyncHeaderSize) - OutOfSync(frame, "Tick"); - else - OutOfSync(frame, (i - SyncHeaderSize) / 4); - } - } - } + OutOfSync(frame); } else syncForFrame.Add(frame, packet); } - void OutOfSync(int frame, int index) - { - var orders = frameData.OrdersForFrame(World, frame); - - // Invalid index - if (index >= orders.Count()) - OutOfSync(frame); - - throw new InvalidOperationException("Out of sync in frame {0}.\n {1}\n Compare syncreport.log with other players.".F(frame, orders.ElementAt(index).Order.ToString())); - } - public bool IsReadyForNextFrame { get { return NetFrameNumber >= 1 && frameData.IsReadyForFrame(NetFrameNumber); } @@ -204,17 +173,10 @@ namespace OpenRA.Network Connection.Send(NetFrameNumber + FramesAhead, localOrders.Select(o => o.Serialize()).ToList()); localOrders.Clear(); - var sync = new List(); - sync.Add(World.SyncHash()); - foreach (var order in frameData.OrdersForFrame(World, NetFrameNumber)) - { UnitOrders.ProcessOrder(this, World, order.Client, order.Order); - sync.Add(World.SyncHash()); - } - var ss = sync.SerializeSync(); - Connection.SendSync(NetFrameNumber, ss); + Connection.SendSync(NetFrameNumber, OrderIO.SerializeSync(World.SyncHash())); syncReport.UpdateSyncReport();