diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 649b76561a..7d97c06b78 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -34,6 +34,7 @@ using OpenRA.Support; using OpenRA.Traits; using Timer = OpenRA.Support.Timer; using XRandom = OpenRA.Thirdparty.Random; +using System.Text; namespace OpenRA { @@ -204,6 +205,50 @@ namespace OpenRA public static int LocalTick = 0; const int NetTickScale = 3; // 120ms net tick for 40ms local tick + static Queue> syncReports = new Queue>(); + const int numSyncReports = 5; + + static void UpdateSyncReport() + { + if (!Settings.RecordSyncReports) + return; + + while (syncReports.Count >= numSyncReports) syncReports.Dequeue(); + syncReports.Enqueue(Pair.New(orderManager.FrameNumber, GenerateSyncReport())); + } + + static string GenerateSyncReport() + { + var sb = new StringBuilder(); + sb.AppendLine("Actors:"); + foreach (var a in Game.world.Actors) + sb.AppendLine("\t {0} {1} {2} ({3})".F( + a.ActorID, + a.Info.Name, + (a.Owner == null) ? "null" : a.Owner.InternalName, + Sync.CalculateSyncHash(a))); + + sb.AppendLine("Tick Actors:"); + foreach (var a in Game.world.Queries.WithTraitMultiple()) + sb.AppendLine("\t {0} {1} {2} {3} ({4})".F( + a.Actor.ActorID, + a.Actor.Info.Name, + (a.Actor.Owner == null) ? "null" : a.Actor.Owner.InternalName, + a.Trait.GetType().Name, + Sync.CalculateSyncHash(a.Trait))); + + return sb.ToString(); + } + + public static void DumpSyncReport() + { + foreach (var f in syncReports) + { + Log.Write("Sync for net frame {0} -------------", f.First); + Log.Write("{0}", f.Second); + } + } + public static void Tick() { if (packageChangePending) @@ -246,6 +291,9 @@ namespace OpenRA world.Tick(); + if (isNetTick) + UpdateSyncReport(); + PerfHistory.Tick(); } else diff --git a/OpenRA.Game/GameRules/UserSettings.cs b/OpenRA.Game/GameRules/UserSettings.cs index c68ff8d6ab..f5048085d9 100644 --- a/OpenRA.Game/GameRules/UserSettings.cs +++ b/OpenRA.Game/GameRules/UserSettings.cs @@ -27,6 +27,7 @@ namespace OpenRA.GameRules public bool PathDebug = false; public bool PerfDebug = true; public bool IndexDebug = false; + public bool RecordSyncReports = false; // Window settings public readonly int Width = 0; diff --git a/OpenRA.Game/Network/OrderManager.cs b/OpenRA.Game/Network/OrderManager.cs index bcf1bbd97b..c80985854e 100755 --- a/OpenRA.Game/Network/OrderManager.cs +++ b/OpenRA.Game/Network/OrderManager.cs @@ -24,6 +24,7 @@ using System.IO; using System.Linq; using OpenRA.FileFormats; using OpenRA.Traits; +using System.Text; namespace OpenRA.Network { @@ -118,7 +119,7 @@ namespace OpenRA.Network { if( packet.Length != existingSync.Length ) { - DumpActors(); + Game.DumpSyncReport(); OutOfSync( frame ); } else @@ -127,7 +128,7 @@ namespace OpenRA.Network { if( packet[ i ] != existingSync[ i ] ) { - DumpActors(); + Game.DumpSyncReport(); if ( i < SyncHeaderSize ) OutOfSync(frame, "Tick"); @@ -141,17 +142,6 @@ namespace OpenRA.Network syncForFrame.Add( frame, packet ); } - static void DumpActors() - { - Log.Write( "Actors:" ); - foreach( var a in Game.world.Actors ) - Log.Write( "\t {0} {1} {2} ({3})", a.ActorID, a.Info.Name, ( a.Owner == null ) ? "null" : a.Owner.InternalName, Sync.CalculateSyncHash( a ) ); - - Log.Write( "Tick Actors:" ); - foreach( var a in Game.world.Queries.WithTraitMultiple() ) - Log.Write( "\t {0} {1} {2} {3} ({4})", a.Actor.ActorID, a.Actor.Info.Name, ( a.Actor.Owner == null ) ? "null" : a.Actor.Owner.InternalName, a.Trait.GetType().Name, Sync.CalculateSyncHash( a.Trait ) ); - } - void OutOfSync( int frame , int index) { var frameData = clientQuitTimes diff --git a/OpenRA.Game/Widgets/Delegates/SettingsMenuDelegate.cs b/OpenRA.Game/Widgets/Delegates/SettingsMenuDelegate.cs index 45e46c8df0..b6777a3b81 100644 --- a/OpenRA.Game/Widgets/Delegates/SettingsMenuDelegate.cs +++ b/OpenRA.Game/Widgets/Delegates/SettingsMenuDelegate.cs @@ -14,25 +14,32 @@ namespace OpenRA.Widgets.Delegates // Checkboxes r.GetWidget("SETTINGS_CHECKBOX_UNITDEBUG").Checked = () => {return Game.Settings.UnitDebug;}; r.GetWidget("SETTINGS_CHECKBOX_UNITDEBUG").OnMouseDown = mi => { - Game.Settings.UnitDebug = !Game.Settings.UnitDebug; + Game.Settings.UnitDebug ^= true; return true; }; r.GetWidget("SETTINGS_CHECKBOX_PATHDEBUG").Checked = () => {return Game.Settings.PathDebug;}; r.GetWidget("SETTINGS_CHECKBOX_PATHDEBUG").OnMouseDown = mi => { - Game.Settings.PathDebug = !Game.Settings.PathDebug; + Game.Settings.PathDebug ^= true; return true; }; r.GetWidget("SETTINGS_CHECKBOX_INDEXDEBUG").Checked = () => {return Game.Settings.IndexDebug;}; r.GetWidget("SETTINGS_CHECKBOX_INDEXDEBUG").OnMouseDown = mi => { - Game.Settings.IndexDebug = !Game.Settings.IndexDebug; + Game.Settings.IndexDebug ^= true; return true; }; r.GetWidget("SETTINGS_CHECKBOX_PERFDEBUG").Checked = () => {return Game.Settings.PerfDebug;}; r.GetWidget("SETTINGS_CHECKBOX_PERFDEBUG").OnMouseDown = mi => { - Game.Settings.PerfDebug = !Game.Settings.PerfDebug; + Game.Settings.PerfDebug ^= true; + return true; + }; + + r.GetWidget("SETTINGS_CHECKBOX_SYNCREPORTS").Checked = () => { return Game.Settings.RecordSyncReports; }; + r.GetWidget("SETTINGS_CHECKBOX_SYNCREPORTS").OnMouseDown = mi => + { + Game.Settings.RecordSyncReports ^= true; return true; }; diff --git a/mods/ra/menus.yaml b/mods/ra/menus.yaml index 93b2067ef1..d7a38fc793 100644 --- a/mods/ra/menus.yaml +++ b/mods/ra/menus.yaml @@ -97,7 +97,7 @@ Container: X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM- HEIGHT)/2 Width: 450 - Height: 300 + Height: 350 Visible: false Children: Label@SETTINGS_LABEL_TITLE: @@ -136,6 +136,13 @@ Container: Width:300 Height:20 Text:Show Performance Information + Checkbox@SETTINGS_CHECKBOX_SYNCREPORTS: + Id:SETTINGS_CHECKBOX_SYNCREPORTS + X:100 + Y:180 + Width:300 + Height:20 + Text:Collect Sync Reports Button@SETTINGS_BUTTON_OK: Id:SETTINGS_BUTTON_OK X:PARENT_RIGHT - 180