diff --git a/OpenRA.Game/Network/Order.cs b/OpenRA.Game/Network/Order.cs index 5e76b9d673..fe3272038f 100644 --- a/OpenRA.Game/Network/Order.cs +++ b/OpenRA.Game/Network/Order.cs @@ -269,6 +269,11 @@ namespace OpenRA return new Order(order, null, false) { IsImmediate = isImmediate, TargetString = targetString }; } + public static Order FromTargetString(string order, string targetString, bool isImmediate, uint extraData) + { + return new Order(order, null, false) { IsImmediate = isImmediate, TargetString = targetString, ExtraData = extraData }; + } + public static Order FromGroupedOrder(Order grouped, Actor subject) { return new Order( diff --git a/OpenRA.Game/Network/UnitOrders.cs b/OpenRA.Game/Network/UnitOrders.cs index 19530c7875..0a81fd043f 100644 --- a/OpenRA.Game/Network/UnitOrders.cs +++ b/OpenRA.Game/Network/UnitOrders.cs @@ -211,7 +211,7 @@ namespace OpenRA.Network case "GameSaved": foreach (var nsr in orderManager.World.WorldActor.TraitsImplementing()) - nsr.GameSaved(orderManager.World); + nsr.GameSaved(orderManager.World, order.ExtraData != 0); break; case "PauseGame": diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index 01b03de93e..403c6f9f4a 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -1056,7 +1056,7 @@ namespace OpenRA.Server Directory.CreateDirectory(baseSavePath); GameSave.Save(Path.Combine(baseSavePath, filename)); - DispatchServerOrdersToClients(Order.FromTargetString("GameSaved", filename, true)); + DispatchServerOrdersToClients(Order.FromTargetString("GameSaved", filename, true, o.ExtraData)); } break; diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 6f0d4cb6fe..84ddd089e6 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -373,7 +373,7 @@ namespace OpenRA.Traits public interface IPostWorldLoaded { void PostWorldLoaded(World w, WorldRenderer wr); } public interface INotifyGameLoading { void GameLoading(World w); } public interface INotifyGameLoaded { void GameLoaded(World w); } - public interface INotifyGameSaved { void GameSaved(World w); } + public interface INotifyGameSaved { void GameSaved(World w, bool isAutoSave); } public interface IGameSaveTraitData { diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 6ead128bc9..53fa8a5b85 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -562,7 +562,7 @@ namespace OpenRA } } - public void RequestGameSave(string filename) + public void RequestGameSave(string filename, bool isAutosave) { // Allow traits to save arbitrary data that will be passed back via IGameSaveTraitData.ResolveTraitData // at the end of the save restoration @@ -580,7 +580,8 @@ namespace OpenRA i++; } - IssueOrder(Order.FromTargetString("CreateGameSave", filename, true)); + var extraData = isAutosave ? 1u : 0u; + IssueOrder(Order.FromTargetString("CreateGameSave", filename, true, extraData)); } public bool Disposing; diff --git a/OpenRA.Mods.Common/Traits/World/AutoSave.cs b/OpenRA.Mods.Common/Traits/World/AutoSave.cs index 98e380223f..659dde6fbc 100644 --- a/OpenRA.Mods.Common/Traits/World/AutoSave.cs +++ b/OpenRA.Mods.Common/Traits/World/AutoSave.cs @@ -80,7 +80,7 @@ namespace OpenRA.Mods.Common.Traits var dateTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHHmmssZ", CultureInfo.InvariantCulture); var fileName = $"{AutoSavePattern}{dateTime}{SaveFileExtension}"; - self.World.RequestGameSave(fileName); + self.World.RequestGameSave(fileName, true); ticksUntilAutoSave = GetTicksBetweenAutosaves(self); } diff --git a/OpenRA.Mods.Common/Traits/World/StartGameNotification.cs b/OpenRA.Mods.Common/Traits/World/StartGameNotification.cs index 7272f8eda4..2714b4dd01 100644 --- a/OpenRA.Mods.Common/Traits/World/StartGameNotification.cs +++ b/OpenRA.Mods.Common/Traits/World/StartGameNotification.cs @@ -64,11 +64,13 @@ namespace OpenRA.Mods.Common.Traits } } - void INotifyGameSaved.GameSaved(World world) + void INotifyGameSaved.GameSaved(World world, bool isAutosave) { if (!world.IsReplay) { - Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", info.SavedNotification, world.RenderPlayer?.Faction.InternalName); + if (!isAutosave) + Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", info.SavedNotification, world.RenderPlayer?.Faction.InternalName); + TextNotificationsManager.AddTransientLine(null, info.SavedTextNotification); } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs index 9da4ac7d75..054a464229 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs @@ -377,7 +377,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic void Inner() { - world.RequestGameSave(filename); + world.RequestGameSave(filename, false); Ui.CloseWindow(); onExit(); }