diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 57bc24b722..019f118d50 100755 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -174,20 +174,20 @@ namespace OpenRA { var isNetTick = LocalTick % NetTickScale == 0; - if ((!isNetTick || orderManager.IsReadyForNextFrame) && !orderManager.GamePaused ) + if (!isNetTick || orderManager.IsReadyForNextFrame) { ++orderManager.LocalFrameNumber; Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local"); - if (isNetTick) orderManager.Tick(); - + if (isNetTick) + orderManager.Tick(); Sync.CheckSyncUnchanged(world, () => - { - world.OrderGenerator.Tick(world); - world.Selection.Tick(world); - }); + { + world.OrderGenerator.Tick(world); + world.Selection.Tick(world); + }); world.Tick(); diff --git a/OpenRA.Game/Network/Order.cs b/OpenRA.Game/Network/Order.cs index 0f486e987b..015851a406 100755 --- a/OpenRA.Game/Network/Order.cs +++ b/OpenRA.Game/Network/Order.cs @@ -200,17 +200,11 @@ namespace OpenRA return new Order("HandshakeResponse", null, false) { IsImmediate = true, TargetString = text }; } - public static Order PauseRequest() + public static Order PauseGame(bool paused) { - return new Order("PauseRequest", null, false) { IsImmediate = true, TargetString="" }; //TODO: targetbool? - } - - public static Order PauseGame() - { - return new Order("PauseGame", null, false) { IsImmediate = true, TargetString=""}; //TODO: targetbool? + return new Order("PauseGame", null, false) { TargetString = paused ? "Pause" : "UnPause" }; } - public static Order Command(string text) { return new Order("Command", null, false) { IsImmediate = true, TargetString = text }; diff --git a/OpenRA.Game/Network/OrderManager.cs b/OpenRA.Game/Network/OrderManager.cs index c0b2cee81f..624bbd2a35 100755 --- a/OpenRA.Game/Network/OrderManager.cs +++ b/OpenRA.Game/Network/OrderManager.cs @@ -36,7 +36,6 @@ namespace OpenRA.Network public int LastTickTime = Environment.TickCount; public bool GameStarted { get { return NetFrameNumber != 0; } } - public bool GamePaused {get; set;} public IConnection Connection { get; private set; } public readonly int SyncHeaderSize = 9; diff --git a/OpenRA.Game/Network/UnitOrders.cs b/OpenRA.Game/Network/UnitOrders.cs index 5d34febd7b..24583688aa 100755 --- a/OpenRA.Game/Network/UnitOrders.cs +++ b/OpenRA.Game/Network/UnitOrders.cs @@ -95,16 +95,20 @@ namespace OpenRA.Network Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map, false); break; } - + case "PauseGame": - { + { var client = orderManager.LobbyInfo.ClientWithIndex(clientId); - - if(client != null) + if (client != null) { - orderManager.GamePaused = !orderManager.GamePaused; - var pausetext = "The game is {0} by {1}".F( orderManager.GamePaused ? "paused" : "un-paused", client.Name ); - Game.AddChatLine(Color.White, "", pausetext); + var pause = order.TargetString == "Pause"; + if (orderManager.world.Paused != pause && !world.LobbyInfo.IsSinglePlayer) + { + var pausetext = "The game is {0} by {1}".F(pause ? "paused" : "un-paused", client.Name); + Game.AddChatLine(Color.White, "", pausetext); + } + + orderManager.world.Paused = pause; } break; } diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index 6468f0c11a..7a200a0d49 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -488,11 +488,9 @@ namespace OpenRA.Server DispatchOrdersToClient(c, fromIndex, 0, so.Serialize()); break; - case "PauseRequest": - foreach (var c in conns.ToArray()) - { var x = Order.PauseGame(); - DispatchOrdersToClient(c, fromIndex, 0, x.Serialize()); - } + case "PauseGame": + foreach (var c in conns.Except(conn).ToArray()) + DispatchOrdersToClient(c, fromIndex, 0, so.Serialize()); break; } } diff --git a/OpenRA.Game/Widgets/TimerWidget.cs b/OpenRA.Game/Widgets/TimerWidget.cs index b2f5bfb2ba..e66bbc2611 100644 --- a/OpenRA.Game/Widgets/TimerWidget.cs +++ b/OpenRA.Game/Widgets/TimerWidget.cs @@ -19,7 +19,7 @@ namespace OpenRA.Widgets var font = Game.Renderer.Fonts["Title"]; var rb = RenderBounds; - var s = WidgetUtils.FormatTime(Game.LocalTick) + (Game.orderManager.GamePaused?" (paused)":""); + var s = WidgetUtils.FormatTime(Game.LocalTick) + (Game.orderManager.world.Paused?" (paused)":""); var pos = new float2(rb.Left - font.Measure(s).X / 2, rb.Top); font.DrawTextWithContrast(s, pos, Color.White, Color.Black, 1); } diff --git a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs index 1cebd7be69..da73e51725 100644 --- a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs +++ b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs @@ -175,13 +175,7 @@ namespace OpenRA.Widgets return true; } else if (e.KeyName == Game.Settings.Keys.PauseKey) - { - world.IssueOrder(Order.PauseRequest()); - } - - bool handled = false; - - if (handled) return true; + world.IssueOrder(Order.PauseGame(!world.Paused)); } return false; } diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 58ad20884b..4d7647a1c1 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -158,37 +158,29 @@ namespace OpenRA public event Action ActorAdded = _ => { }; public event Action ActorRemoved = _ => { }; - // Will do bad things in multiplayer games - public bool EnableTick = true; + public bool Paused = false; public bool IsShellmap = false; - bool ShouldTick() - { - if (!EnableTick) return false; - return !IsShellmap || Game.Settings.Game.ShowShellmap; - } - public void Tick() { - // TODO: Expose this as an order so it can be synced - if (ShouldTick()) + if (!Paused && (!IsShellmap || Game.Settings.Game.ShowShellmap)) { - using( new PerfSample("tick_idle") ) - foreach( var ni in ActorsWithTrait() ) + using (new PerfSample("tick_idle")) + foreach (var ni in ActorsWithTrait()) if (ni.Actor.IsIdle) ni.Trait.TickIdle(ni.Actor); - using( new PerfSample("tick_activities") ) - foreach( var a in actors ) + using (new PerfSample("tick_activities")) + foreach(var a in actors) a.Tick(); - ActorsWithTrait().DoTimed( x => - { - x.Trait.Tick( x.Actor ); - }, "[{2}] Trait: {0} ({1:0.000} ms)", Game.Settings.Debug.LongTickThreshold ); + ActorsWithTrait().DoTimed(x => x.Trait.Tick(x.Actor), + "[{2}] Trait: {0} ({1:0.000} ms)", + Game.Settings.Debug.LongTickThreshold); - effects.DoTimed( e => e.Tick( this ), "[{2}] Effect: {0} ({1:0.000} ms)", - Game.Settings.Debug.LongTickThreshold ); + effects.DoTimed(e => e.Tick(this), + "[{2}] Effect: {0} ({1:0.000} ms)", + Game.Settings.Debug.LongTickThreshold); } while (frameEndActions.Count != 0) diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs index cedab28475..cb53a6dd39 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs @@ -85,6 +85,8 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic public void OptionsClicked() { + var cachedPause = world.Paused; + if (menu != MenuType.None) { Ui.CloseWindow(); @@ -93,14 +95,15 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic ingameRoot.IsVisible = () => false; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(true)); + Game.LoadWidget(world, "INGAME_MENU", Ui.Root, new WidgetArgs() { { "onExit", () => { ingameRoot.IsVisible = () => true; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(cachedPause)); } } }); diff --git a/OpenRA.Mods.RA/Player/PlayerStatistics.cs b/OpenRA.Mods.RA/Player/PlayerStatistics.cs index 97644269ef..0444936f42 100644 --- a/OpenRA.Mods.RA/Player/PlayerStatistics.cs +++ b/OpenRA.Mods.RA/Player/PlayerStatistics.cs @@ -86,7 +86,6 @@ namespace OpenRA.Mods.RA case "Chat": case "TeamChat": case "HandshakeResponse": - case "PauseRequest": case "PauseGame": case "StartGame": case "Disconnected": @@ -94,7 +93,8 @@ namespace OpenRA.Mods.RA case "SyncInfo": return; } - if (order.OrderString.StartsWith("Dev")) return; + if (order.OrderString.StartsWith("Dev")) + return; OrderCount++; } } diff --git a/OpenRA.Mods.RA/Scripting/Media.cs b/OpenRA.Mods.RA/Scripting/Media.cs index 8fbc1cca66..6bfdb5e4f6 100644 --- a/OpenRA.Mods.RA/Scripting/Media.cs +++ b/OpenRA.Mods.RA/Scripting/Media.cs @@ -32,7 +32,7 @@ namespace OpenRA.Scripting return; } - w.EnableTick = false; + w.Paused = true; // Mute world sounds var oldModifier = Sound.SoundVolumeModifier; @@ -51,7 +51,7 @@ namespace OpenRA.Scripting Ui.CloseWindow(); Sound.SoundVolumeModifier = oldModifier; - w.EnableTick = true; + w.Paused = false; onComplete(); }); } diff --git a/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs index 01e31e05d9..cad508d877 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs @@ -8,10 +8,11 @@ */ #endregion -using OpenRA.Traits; -using System.Linq; -using OpenRA.Widgets; using System.Drawing; +using System.Linq; +using OpenRA.Network; +using OpenRA.Traits; +using OpenRA.Widgets; namespace OpenRA.Mods.RA.Widgets.Logic { @@ -26,11 +27,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic gameRoot = r.Get("INGAME_ROOT"); var optionsBG = gameRoot.Get("INGAME_OPTIONS_BG"); + // TODO: RA's broken UI wiring makes it unreasonably difficult to + // cache and restore the previous pause state, so opening/closing + // the menu in a paused singleplayer game will un-pause the game. r.Get("INGAME_OPTIONS_BUTTON").OnClick = () => { optionsBG.Visible = !optionsBG.Visible; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(true)); }; var cheatsButton = gameRoot.Get("CHEATS_BUTTON"); @@ -65,7 +69,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic { optionsBG.Visible = false; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(false)); }; optionsBG.Get("SURRENDER").OnClick = () => diff --git a/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs index 047f2411b3..b38f505ca0 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic { optionsBG.Visible = !optionsBG.Visible; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(true)); }; optionsBG.Get("DISCONNECT").OnClick = () => @@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic { optionsBG.Visible = false; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(false)); }; optionsBG.Get("SURRENDER").IsVisible = () => false;