diff --git a/OpenRA.Game/Network/OrderManager.cs b/OpenRA.Game/Network/OrderManager.cs
index 33d9a8c808..640926c3b8 100644
--- a/OpenRA.Game/Network/OrderManager.cs
+++ b/OpenRA.Game/Network/OrderManager.cs
@@ -57,7 +57,9 @@ namespace OpenRA.Network
bool generateSyncReport = false;
int sentOrdersFrame = 0;
float tickScale = 1f;
- bool outOfSync = false;
+
+ /// Should only be set in
+ public bool IsOutOfSync { get; private set; } = false;
public struct ClientOrder
{
@@ -72,12 +74,12 @@ namespace OpenRA.Network
void OutOfSync(int frame)
{
- if (outOfSync)
+ if (IsOutOfSync)
return;
syncReport.DumpSyncReport(frame);
World.OutOfSync();
- outOfSync = true;
+ IsOutOfSync = true;
TextNotificationsManager.AddSystemLine($"Out of sync in frame {frame}.\nCompare syncreport.log with other players.");
}
diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs
index f76b8f4ce6..49c8f4808b 100644
--- a/OpenRA.Game/World.cs
+++ b/OpenRA.Game/World.cs
@@ -618,6 +618,9 @@ namespace OpenRA
public void OutOfSync()
{
EndGame();
+
+ // In the event the replay goes out of sync, it becomes no longer usable. For polish we permanently pause the world.
+ ReplayTimestep = 0;
}
}
diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ReplayControlBarLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ReplayControlBarLogic.cs
index c88ea0c674..9aba4f6d56 100644
--- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ReplayControlBarLogic.cs
+++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ReplayControlBarLogic.cs
@@ -45,18 +45,21 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var speed = PlaybackSpeed.Regular;
var originalTimestep = world.Timestep;
+ // In the event the replay goes out of sync, it becomes no longer usable. For polish we permanently pause the world.
+ Func isWidgetDisabled = () => orderManager.IsOutOfSync || orderManager.NetFrameNumber >= replayNetTicks;
+
var pauseButton = widget.Get("BUTTON_PAUSE");
- pauseButton.IsVisible = () => world.ReplayTimestep != 0 && orderManager.NetFrameNumber < replayNetTicks;
+ pauseButton.IsVisible = () => world.ReplayTimestep != 0 && !isWidgetDisabled();
pauseButton.OnClick = () => world.ReplayTimestep = 0;
var playButton = widget.Get("BUTTON_PLAY");
- playButton.IsVisible = () => world.ReplayTimestep == 0 || orderManager.NetFrameNumber >= replayNetTicks;
+ playButton.IsVisible = () => world.ReplayTimestep == 0 || isWidgetDisabled();
playButton.OnClick = () => world.ReplayTimestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]);
- playButton.IsDisabled = () => orderManager.NetFrameNumber >= replayNetTicks;
+ playButton.IsDisabled = isWidgetDisabled;
var slowButton = widget.Get("BUTTON_SLOW");
slowButton.IsHighlighted = () => speed == PlaybackSpeed.Slow;
- slowButton.IsDisabled = () => orderManager.NetFrameNumber >= replayNetTicks;
+ slowButton.IsDisabled = isWidgetDisabled;
slowButton.OnClick = () =>
{
speed = PlaybackSpeed.Slow;
@@ -66,7 +69,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var normalSpeedButton = widget.Get("BUTTON_REGULAR");
normalSpeedButton.IsHighlighted = () => speed == PlaybackSpeed.Regular;
- normalSpeedButton.IsDisabled = () => orderManager.NetFrameNumber >= replayNetTicks;
+ normalSpeedButton.IsDisabled = isWidgetDisabled;
normalSpeedButton.OnClick = () =>
{
speed = PlaybackSpeed.Regular;
@@ -76,7 +79,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var fastButton = widget.Get("BUTTON_FAST");
fastButton.IsHighlighted = () => speed == PlaybackSpeed.Fast;
- fastButton.IsDisabled = () => orderManager.NetFrameNumber >= replayNetTicks;
+ fastButton.IsDisabled = isWidgetDisabled;
fastButton.OnClick = () =>
{
speed = PlaybackSpeed.Fast;
@@ -86,7 +89,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var maximumButton = widget.Get("BUTTON_MAXIMUM");
maximumButton.IsHighlighted = () => speed == PlaybackSpeed.Maximum;
- maximumButton.IsDisabled = () => orderManager.NetFrameNumber >= replayNetTicks;
+ maximumButton.IsDisabled = isWidgetDisabled;
maximumButton.OnClick = () =>
{
speed = PlaybackSpeed.Maximum;