From 492b5aec8270d3de76068113f6778629ac5eacfe Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 13 Apr 2019 17:10:46 +0000 Subject: [PATCH] Save and restore viewport position / selection / control groups. --- OpenRA.Game/Selection.cs | 37 +++++++++++++ OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + .../Traits/World/GameSaveViewportManager.cs | 53 +++++++++++++++++++ mods/cnc/rules/player.yaml | 1 + mods/d2k/rules/player.yaml | 1 + mods/ra/rules/player.yaml | 1 + mods/ts/rules/player.yaml | 1 + 7 files changed, 95 insertions(+) create mode 100644 OpenRA.Mods.Common/Traits/World/GameSaveViewportManager.cs diff --git a/OpenRA.Game/Selection.cs b/OpenRA.Game/Selection.cs index b8519c38c5..fdc7aad0e8 100644 --- a/OpenRA.Game/Selection.cs +++ b/OpenRA.Game/Selection.cs @@ -200,5 +200,42 @@ namespace OpenRA .Select(g => (int?)g.Key) .FirstOrDefault(); } + + public List Serialize() + { + var groups = controlGroups + .Where(cg => cg.Value.Any()) + .Select(cg => new MiniYamlNode(cg.Key.ToString(), + FieldSaver.FormatValue(cg.Value.Select(a => a.ActorID).ToArray()))) + .ToList(); + + return new List() + { + new MiniYamlNode("Selection", FieldSaver.FormatValue(Actors.Select(a => a.ActorID).ToArray())), + new MiniYamlNode("Groups", new MiniYaml("", groups)) + }; + } + + public void Deserialize(World world, List data) + { + var selectionNode = data.FirstOrDefault(n => n.Key == "Selection"); + if (selectionNode != null) + { + var selected = FieldLoader.GetValue("Selection", selectionNode.Value.Value) + .Select(a => world.GetActorById(a)); + Combine(world, selected, false, false); + } + + var groupsNode = data.FirstOrDefault(n => n.Key == "Groups"); + if (groupsNode != null) + { + foreach (var n in groupsNode.Value.Nodes) + { + var group = FieldLoader.GetValue(n.Key, n.Value.Value) + .Select(a => world.GetActorById(a)); + controlGroups[int.Parse(n.Key)].AddRange(group); + } + } + } } } diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 6b79a2f267..7d8d549a89 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -568,6 +568,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/World/GameSaveViewportManager.cs b/OpenRA.Mods.Common/Traits/World/GameSaveViewportManager.cs new file mode 100644 index 0000000000..39705f1e2b --- /dev/null +++ b/OpenRA.Mods.Common/Traits/World/GameSaveViewportManager.cs @@ -0,0 +1,53 @@ +#region Copyright & License Information +/* + * Copyright 2007-2019 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + public class GameSaveViewportManagerInfo : ITraitInfo + { + public object Create(ActorInitializer init) { return new GameSaveViewportManager(); } + } + + public class GameSaveViewportManager : IWorldLoaded, IGameSaveTraitData + { + WorldRenderer worldRenderer; + + void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr) { worldRenderer = wr; } + + List IGameSaveTraitData.IssueTraitData(Actor self) + { + if (worldRenderer.World.LocalPlayer == null || self != worldRenderer.World.LocalPlayer.PlayerActor) + return null; + + return new List() + { + new MiniYamlNode("Viewport", FieldSaver.FormatValue(worldRenderer.Viewport.CenterPosition)), + new MiniYamlNode("Selection", "", self.World.Selection.Serialize()) + }; + } + + void IGameSaveTraitData.ResolveTraitData(Actor self, List data) + { + var viewportNode = data.FirstOrDefault(n => n.Key == "Viewport"); + if (viewportNode != null) + worldRenderer.Viewport.Center(FieldLoader.GetValue("data", viewportNode.Value.Value)); + + var selectionNode = data.FirstOrDefault(n => n.Key == "Selection"); + if (selectionNode != null) + self.World.Selection.Deserialize(self.World, selectionNode.Value.Nodes); + } + } +} diff --git a/mods/cnc/rules/player.yaml b/mods/cnc/rules/player.yaml index ed2e430061..8410a4a234 100644 --- a/mods/cnc/rules/player.yaml +++ b/mods/cnc/rules/player.yaml @@ -59,3 +59,4 @@ Player: ResourceStorageWarning: PlayerExperience: ConditionManager: + GameSaveViewportManager: diff --git a/mods/d2k/rules/player.yaml b/mods/d2k/rules/player.yaml index 4e34fba55d..3618a33c29 100644 --- a/mods/d2k/rules/player.yaml +++ b/mods/d2k/rules/player.yaml @@ -145,3 +145,4 @@ Player: AdviceInterval: 26 PlayerExperience: ConditionManager: + GameSaveViewportManager: diff --git a/mods/ra/rules/player.yaml b/mods/ra/rules/player.yaml index 7bb33aaa6c..659e3a30ce 100644 --- a/mods/ra/rules/player.yaml +++ b/mods/ra/rules/player.yaml @@ -144,3 +144,4 @@ Player: ResourceStorageWarning: PlayerExperience: ConditionManager: + GameSaveViewportManager: diff --git a/mods/ts/rules/player.yaml b/mods/ts/rules/player.yaml index 6cf755fa07..f6afb8cd43 100644 --- a/mods/ts/rules/player.yaml +++ b/mods/ts/rules/player.yaml @@ -120,3 +120,4 @@ Player: ResourceStorageWarning: PlayerExperience: ConditionManager: + GameSaveViewportManager: