diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs index c9d07117b4..8448322063 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs @@ -68,26 +68,30 @@ namespace OpenRA.Mods.Common.Widgets.Logic map.PlayerDefinitions = new MapPlayers(map.Rules, map.SpawnPoints.Value.Length).ToMiniYaml(); map.FixOpenAreas(modRules); - var userMapFolder = Game.ModData.Manifest.MapFolders.First(f => f.Value == "User").Key; + Action afterSave = uid => + { + // HACK: Work around a synced-code change check. + // It's not clear why this is needed here, but not in the other places that load maps. + Game.RunAfterTick(() => + { + ConnectionLogic.Connect(System.Net.IPAddress.Loopback.ToString(), + Game.CreateLocalServer(uid), "", + () => Game.LoadEditor(uid), + () => { Game.CloseServer(); onExit(); }); + }); - // Ignore optional flag - if (userMapFolder.StartsWith("~")) - userMapFolder = userMapFolder.Substring(1); + Ui.CloseWindow(); + onSelect(uid); + }; - var mapDir = Platform.ResolvePath(userMapFolder); - Directory.CreateDirectory(mapDir); - var tempLocation = Path.Combine(mapDir, "temp") + ".oramap"; - map.Save(tempLocation); // TODO: load it right away and save later properly - - var newMap = new Map(tempLocation); - Game.ModData.MapCache[newMap.Uid].UpdateFromMap(newMap, MapClassification.User); - - ConnectionLogic.Connect(System.Net.IPAddress.Loopback.ToString(), - Game.CreateLocalServer(newMap.Uid), - "", - () => { Game.LoadEditor(newMap.Uid); }, - () => { Game.CloseServer(); onExit(); }); - onSelect(newMap.Uid); + Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs() + { + { "onSave", afterSave }, + { "onExit", () => { Ui.CloseWindow(); onExit(); } }, + { "map", map }, + { "playerDefinitions", map.PlayerDefinitions }, + { "actorDefinitions", map.ActorDefinitions } + }); }; } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs index ee662f5cb9..399611c5e8 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic public class SaveMapLogic { [ObjectCreator.UseCtor] - public SaveMapLogic(Widget widget, Action onExit, Map map, EditorActorLayer editorActorLayer) + public SaveMapLogic(Widget widget, Action onSave, Action onExit, Map map, List playerDefinitions, List actorDefinitions) { var title = widget.Get("TITLE"); title.Text = map.Title; @@ -50,17 +50,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic visibilityDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, mapVisibility, setupItem); } + Func makeMapDirectory = dir => + { + var f = Platform.UnresolvePath(dir); + if (f.StartsWith("~")) + f = f.Substring(1); + + return f; + }; + + var mapDirectories = Game.ModData.Manifest.MapFolders + .ToDictionary(kv => makeMapDirectory(kv.Key), kv => Enum.Parse(kv.Value)); + var directoryDropdown = widget.Get("DIRECTORY_DROPDOWN"); { - var mapDirectories = Game.ModData.Manifest.MapFolders.Keys.Select(ff => - { - var f = Platform.UnresolvePath(ff); - if (f.StartsWith("~")) - f = f.Substring(1); - - return f; - }).ToList(); - Func setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, @@ -70,15 +73,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic return item; }; - var mapDirectory = Platform.UnresolvePath(Path.GetDirectoryName(map.Path)); - var initialDirectory = mapDirectories.FirstOrDefault(f => f == mapDirectory); + var mapDirectory = map.Path != null ? Platform.UnresolvePath(Path.GetDirectoryName(map.Path)) : null; + var initialDirectory = mapDirectories.Keys.FirstOrDefault(f => f == mapDirectory); if (initialDirectory == null) - initialDirectory = mapDirectories.First(); + initialDirectory = mapDirectories.Keys.First(); directoryDropdown.Text = initialDirectory; directoryDropdown.OnClick = () => - directoryDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, mapDirectories, setupItem); + directoryDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, mapDirectories.Keys, setupItem); } var filename = widget.Get("FILENAME"); @@ -101,7 +104,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic return item; }; - typeDropdown.Text = Path.GetExtension(map.Path); + typeDropdown.Text = map.Path != null ? Path.GetExtension(map.Path) : ".oramap"; if (string.IsNullOrEmpty(typeDropdown.Text)) typeDropdown.Text = fileTypes.First(t => t.Value == "").Key; @@ -122,19 +125,34 @@ namespace OpenRA.Mods.Common.Widgets.Logic map.Description = description.Text; map.Author = author.Text; map.Visibility = (MapVisibility)Enum.Parse(typeof(MapVisibility), visibilityDropdown.Text); - map.ActorDefinitions = editorActorLayer.Save(); - map.PlayerDefinitions = editorActorLayer.Players.ToMiniYaml(); + + if (actorDefinitions != null) + map.ActorDefinitions = actorDefinitions; + + if (playerDefinitions != null) + map.PlayerDefinitions = playerDefinitions; + map.RequiresMod = Game.ModData.Manifest.Mod.Id; var combinedPath = Platform.ResolvePath(Path.Combine(directoryDropdown.Text, filename.Text + fileTypes[typeDropdown.Text])); + + // Invalidate the old map metadata + if (map.Uid != null && combinedPath == map.Path) + Game.ModData.MapCache[map.Uid].Invalidate(); + map.Save(combinedPath); + // Reload map to calculate new UID + map = new Map(combinedPath); + // Update the map cache so it can be loaded without restarting the game - Game.ModData.MapCache[map.Uid].UpdateFromMap(map, MapClassification.User); + var classification = mapDirectories[directoryDropdown.Text]; + Game.ModData.MapCache[map.Uid].UpdateFromMap(map, classification); Console.WriteLine("Saved current map at {0}", combinedPath); Ui.CloseWindow(); - onExit(); + + onSave(map.Uid); }; } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs index f06b6be483..4460f912de 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs @@ -102,11 +102,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic saveMapButton.OnClick = () => { hideMenu = true; + var editorActorLayer = world.WorldActor.Trait(); Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs() { + { "onSave", (Action)(_ => hideMenu = false) }, { "onExit", () => hideMenu = false }, { "map", world.Map }, - { "editorActorLayer", world.WorldActor.Trait() } + { "playerDefinitions", editorActorLayer.Players.ToMiniYaml() }, + { "actorDefinitions", editorActorLayer.Save() } }); };