diff --git a/OpenRA.Game/FileSystem/FileSystem.cs b/OpenRA.Game/FileSystem/FileSystem.cs index 63333c01b9..e980e4a03b 100644 --- a/OpenRA.Game/FileSystem/FileSystem.cs +++ b/OpenRA.Game/FileSystem/FileSystem.cs @@ -34,8 +34,9 @@ namespace OpenRA.FileSystem Cache> fileIndex = new Cache>(_ => new List()); - public IReadWritePackage CreatePackage(string filename, Dictionary content) + public IReadWritePackage CreatePackage(string filename) { + var content = new Dictionary(); if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) return new ZipFile(this, filename, content); if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase)) diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index f81bbcb013..e8c7cd928e 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -114,12 +114,13 @@ namespace OpenRA public const int MaxTilesInCircleRange = 50; public readonly MapGrid Grid; + readonly ModData modData; [FieldLoader.Ignore] public readonly WVec[] SubCellOffsets; public readonly SubCell DefaultSubCell; public readonly SubCell LastSubCell; - [FieldLoader.Ignore] public IReadWritePackage Container; - public string Path { get; private set; } + + public IReadOnlyPackage Package { get; private set; } // Yaml map data public string Uid { get; private set; } @@ -252,7 +253,7 @@ namespace OpenRA void AssertExists(string filename) { - using (var s = Container.GetStream(filename)) + using (var s = Package.GetStream(filename)) if (s == null) throw new InvalidOperationException("Required file {0} not present in this map".F(filename)); } @@ -261,10 +262,11 @@ namespace OpenRA /// Initializes a new map created by the editor or importer. /// The map will not receive a valid UID until after it has been saved and reloaded. /// - public Map(TileSet tileset, int width, int height) + public Map(ModData modData, TileSet tileset, int width, int height) { + this.modData = modData; var size = new Size(width, height); - Grid = Game.ModData.Manifest.Get(); + Grid = modData.Manifest.Get(); var tileRef = new TerrainTile(tileset.Templates.First().Key, 0); Title = "Name your map here"; @@ -301,20 +303,19 @@ namespace OpenRA PostInit(); } - /// Initializes a map loaded from disk. - public Map(string path) + public Map(ModData modData, IReadOnlyPackage package) { - Path = path; - Container = Game.ModData.ModFiles.OpenWritablePackage(path); + this.modData = modData; + Package = package; AssertExists("map.yaml"); AssertExists("map.bin"); - var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetStream("map.yaml"), path)); + var yaml = new MiniYaml(null, MiniYaml.FromStream(Package.GetStream("map.yaml"), package.Name)); FieldLoader.Load(this, yaml); if (MapFormat != SupportedMapFormat) - throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path)); + throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, package.Name)); SpawnPoints = Exts.Lazy(() => { @@ -346,25 +347,19 @@ namespace OpenRA MapResources = Exts.Lazy(LoadResourceTiles); MapHeight = Exts.Lazy(LoadMapHeight); - Grid = Game.ModData.Manifest.Get(); + Grid = modData.Manifest.Get(); SubCellOffsets = Grid.SubCellOffsets; LastSubCell = (SubCell)(SubCellOffsets.Length - 1); DefaultSubCell = (SubCell)Grid.SubCellDefaultIndex; - if (Container.Contains("map.png")) - using (var dataStream = Container.GetStream("map.png")) + if (Package.Contains("map.png")) + using (var dataStream = Package.GetStream("map.png")) CustomPreview = new Bitmap(dataStream); PostInit(); - // The Uid is calculated from the data on-disk, so - // format changes must be flushed to disk. - // TODO: this isn't very nice - if (MapFormat < 8) - Save(path); - - Uid = ComputeUID(Container); + Uid = ComputeUID(Package); } void PostInit() @@ -373,7 +368,7 @@ namespace OpenRA { try { - return Game.ModData.RulesetCache.Load(this, this); + return modData.RulesetCache.Load(this, this); } catch (Exception e) { @@ -381,7 +376,7 @@ namespace OpenRA Log.Write("debug", "Failed to load rules for {0} with error {1}", Title, e.Message); } - return Game.ModData.DefaultRules; + return modData.DefaultRules; }); cachedTileSet = Exts.Lazy(() => Rules.TileSets[Tileset]); @@ -495,7 +490,7 @@ namespace OpenRA return rules.Value; } - public void Save(string toPath) + public void Save(IReadWritePackage toContainer) { MapFormat = 8; @@ -545,37 +540,31 @@ namespace OpenRA entries.Add("map.yaml", Encoding.UTF8.GetBytes(s)); // Add any custom assets - if (Container != null) + if (Package != null) { - foreach (var file in Container.Contents) + foreach (var file in Package.Contents) { if (file == "map.bin" || file == "map.yaml") continue; - entries.Add(file, Container.GetStream(file).ReadAllBytes()); + entries.Add(file, Package.GetStream(file).ReadAllBytes()); } } // Saving the map to a new location - if (toPath != Path || Container == null) - { - Path = toPath; - - // Create a new map package - Container = Game.ModData.ModFiles.CreatePackage(Path, entries); - } + Package = toContainer; // Update existing package - Container.Write(entries); + toContainer.Write(entries); // Update UID to match the newly saved data - Uid = ComputeUID(Container); + Uid = ComputeUID(toContainer); } public CellLayer LoadMapTiles() { var tiles = new CellLayer(this); - using (var s = Container.GetStream("map.bin")) + using (var s = Package.GetStream("map.bin")) { var header = new BinaryDataHeader(s, MapSize); if (header.TilesOffset > 0) @@ -607,7 +596,7 @@ namespace OpenRA public CellLayer LoadMapHeight() { var tiles = new CellLayer(this); - using (var s = Container.GetStream("map.bin")) + using (var s = Package.GetStream("map.bin")) { var header = new BinaryDataHeader(s, MapSize); if (header.HeightsOffset > 0) @@ -629,7 +618,7 @@ namespace OpenRA { var resources = new CellLayer(this); - using (var s = Container.GetStream("map.bin")) + using (var s = Package.GetStream("map.bin")) { var header = new BinaryDataHeader(s, MapSize); if (header.ResourcesOffset > 0) @@ -1180,16 +1169,16 @@ namespace OpenRA public Stream Open(string filename) { // Explicit package paths never refer to a map - if (!filename.Contains("|") && Container.Contains(filename)) - return Container.GetStream(filename); + if (!filename.Contains("|") && Package.Contains(filename)) + return Package.GetStream(filename); - return Game.ModData.DefaultFileSystem.Open(filename); + return modData.DefaultFileSystem.Open(filename); } public bool TryGetPackageContaining(string path, out IReadOnlyPackage package, out string filename) { // Packages aren't supported inside maps - return Game.ModData.DefaultFileSystem.TryGetPackageContaining(path, out package, out filename); + return modData.DefaultFileSystem.TryGetPackageContaining(path, out package, out filename); } public bool TryOpen(string filename, out Stream s) @@ -1197,21 +1186,21 @@ namespace OpenRA // Explicit package paths never refer to a map if (!filename.Contains("|")) { - s = Container.GetStream(filename); + s = Package.GetStream(filename); if (s != null) return true; } - return Game.ModData.DefaultFileSystem.TryOpen(filename, out s); + return modData.DefaultFileSystem.TryOpen(filename, out s); } public bool Exists(string filename) { // Explicit package paths never refer to a map - if (!filename.Contains("|") && Container.Contains(filename)) + if (!filename.Contains("|") && Package.Contains(filename)) return true; - return Game.ModData.DefaultFileSystem.Exists(filename); + return modData.DefaultFileSystem.Exists(filename); } } } diff --git a/OpenRA.Game/Map/MapCache.cs b/OpenRA.Game/Map/MapCache.cs index 558fc2aca9..5c6ce00eea 100644 --- a/OpenRA.Game/Map/MapCache.cs +++ b/OpenRA.Game/Map/MapCache.cs @@ -61,11 +61,9 @@ namespace OpenRA { using (new Support.PerfTimer(path.Key)) { - using (var package = modData.ModFiles.OpenPackage(path.Key)) - { - var uid = Map.ComputeUID(package); - previews[uid].UpdateFromMap(package, path.Value, modData.Manifest.MapCompatibility, mapGrid.Type); - } + var package = modData.ModFiles.OpenPackage(path.Key); + var uid = Map.ComputeUID(package); + previews[uid].UpdateFromMap(package, path.Value, modData.Manifest.MapCompatibility, mapGrid.Type); } } catch (Exception e) @@ -190,7 +188,7 @@ namespace OpenRA if (bitmap == null) { createdPreview = true; - var map = new Map(p.Path); + var map = new Map(modData, p.Package); bitmap = Minimap.RenderMapPreview(modData.DefaultRules.TileSets[map.Tileset], map, modData.DefaultRules, true); } diff --git a/OpenRA.Game/Map/MapPreview.cs b/OpenRA.Game/Map/MapPreview.cs index 3f7148e3ab..e5cd1964d1 100644 --- a/OpenRA.Game/Map/MapPreview.cs +++ b/OpenRA.Game/Map/MapPreview.cs @@ -59,7 +59,7 @@ namespace OpenRA MapCache cache; public readonly string Uid; - public string Path { get; private set; } + public IReadOnlyPackage Package { get; private set; } public string Title { get; private set; } public string Type { get; private set; } @@ -127,7 +127,7 @@ namespace OpenRA yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, "map.yaml")).ToDictionary(); } - Path = p.Name; + Package = p; GridType = gridType; Class = classification; diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index 99c7fdd3cc..9ef3870f9a 100644 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -166,7 +166,7 @@ namespace OpenRA throw new InvalidDataException("Invalid map uid: {0}".F(uid)); // Operate on a copy of the map to avoid gameplay state leaking into the cache - var map = new Map(MapCache[uid].Path); + var map = new Map(this, MapCache[uid].Package); LoadTranslations(map); diff --git a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs index 628b024cd9..5b8f3afc1e 100644 --- a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs @@ -949,7 +949,7 @@ namespace OpenRA.Mods.Common.Server static void LoadMap(S server) { - server.Map = new Map(server.ModData.MapCache[server.LobbyInfo.GlobalSettings.Map].Path); + server.Map = new Map(server.ModData, server.ModData.MapCache[server.LobbyInfo.GlobalSettings.Map].Package); server.MapPlayers = new MapPlayers(server.Map.PlayerDefinitions); server.LobbyInfo.Slots = server.MapPlayers.Players diff --git a/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs b/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs index 65e301dd38..9d6f9a2700 100644 --- a/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs +++ b/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs @@ -79,10 +79,10 @@ namespace OpenRA.Mods.Common.UtilityCommands modData.MapCache.LoadMaps(); maps.AddRange(modData.MapCache .Where(m => m.Status == MapStatus.Available) - .Select(m => new Map(m.Path))); + .Select(m => new Map(modData, m.Package))); } else - maps.Add(new Map(args[1])); + maps.Add(new Map(modData, modData.ModFiles.OpenPackage(args[1]))); foreach (var testMap in maps) { diff --git a/OpenRA.Mods.Common/UtilityCommands/GenerateMinimapCommand.cs b/OpenRA.Mods.Common/UtilityCommands/GenerateMinimapCommand.cs index d2904553df..d2fcae348c 100644 --- a/OpenRA.Mods.Common/UtilityCommands/GenerateMinimapCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/GenerateMinimapCommand.cs @@ -29,7 +29,7 @@ namespace OpenRA.Mods.Common.UtilityCommands { Game.ModData = modData; - var map = new Map(args[1]); + var map = new Map(modData, modData.ModFiles.OpenPackage(args[1])); var minimap = Minimap.RenderMapPreview(map.Rules.TileSets[map.Tileset], map, true); var dest = Path.GetFileNameWithoutExtension(args[1]) + ".png"; diff --git a/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs index 267b658a61..f3efe50437 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs @@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.UtilityCommands ValidateMapFormat(format); var tileset = GetTileset(mapSection); - Map = new Map(Rules.TileSets[tileset], MapSize, MapSize) + Map = new Map(modData, Rules.TileSets[tileset], MapSize, MapSize) { Title = basic.GetValue("Name", Path.GetFileNameWithoutExtension(filename)), Author = "Westwood Studios" @@ -94,9 +94,9 @@ namespace OpenRA.Mods.Common.UtilityCommands Map.FixOpenAreas(Rules); - var fileName = Path.GetFileNameWithoutExtension(args[1]); - var dest = fileName + ".oramap"; - Map.Save(dest); + var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap"; + var package = modData.ModFiles.CreatePackage(dest); + Map.Save(package); Console.WriteLine(dest + " saved."); } diff --git a/OpenRA.Mods.Common/UtilityCommands/ResizeMapCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ResizeMapCommand.cs index e399589f0b..665c456f08 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ResizeMapCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ResizeMapCommand.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; +using OpenRA.FileSystem; namespace OpenRA.Mods.Common.UtilityCommands { @@ -48,7 +49,7 @@ namespace OpenRA.Mods.Common.UtilityCommands public void Run(ModData modData, string[] args) { Game.ModData = modData; - map = new Map(args[1]); + map = new Map(modData, modData.ModFiles.OpenPackage(args[1])); Console.WriteLine("Resizing map {0} from {1} to {2},{3}", map.Title, map.MapSize, width, height); map.Resize(width, height); @@ -68,7 +69,7 @@ namespace OpenRA.Mods.Common.UtilityCommands foreach (var kv in forRemoval) map.ActorDefinitions.Remove(kv); - map.Save(map.Path); + map.Save((IReadWritePackage)map.Package); } } } diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeMapCommand.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeMapCommand.cs index ca98f2c30d..ae84f1ceef 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeMapCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeMapCommand.cs @@ -9,6 +9,8 @@ */ #endregion +using OpenRA.FileSystem; + namespace OpenRA.Mods.Common.UtilityCommands { class UpgradeMapCommand : IUtilityCommand @@ -26,15 +28,16 @@ namespace OpenRA.Mods.Common.UtilityCommands // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData; - UpgradeRules.UpgradeMapFormat(modData, args[1]); + var package = modData.ModFiles.OpenWritablePackage(args[1]); + UpgradeRules.UpgradeMapFormat(modData, package); - var map = new Map(args[1]); + var map = new Map(modData, package); var engineDate = Exts.ParseIntegerInvariant(args[2]); UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0); UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0); UpgradeRules.UpgradePlayers(engineDate, ref map.PlayerDefinitions, null, 0); UpgradeRules.UpgradeActors(engineDate, ref map.ActorDefinitions, null, 0); - map.Save(args[1]); + map.Save(package); } } } diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeModCommand.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeModCommand.cs index be03fc44d6..a47338ff34 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeModCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeModCommand.cs @@ -12,6 +12,7 @@ using System; using System.IO; using System.Linq; +using OpenRA.FileSystem; namespace OpenRA.Mods.Common.UtilityCommands { @@ -100,21 +101,21 @@ namespace OpenRA.Mods.Common.UtilityCommands } Console.WriteLine("Processing Maps:"); - var mapPaths = modData.MapCache - .Where(m => m.Status == MapStatus.Available) - .Select(m => m.Path); + var mapPreviews = modData.MapCache + .Where(m => m.Status == MapStatus.Available); - foreach (var path in mapPaths) + foreach (var p in mapPreviews) { - Console.WriteLine("\t" + path); - UpgradeRules.UpgradeMapFormat(modData, path); + var package = (IReadWritePackage)p.Package; + Console.WriteLine("\t" + package.Name); + UpgradeRules.UpgradeMapFormat(modData, package); - var map = new Map(path); + var map = new Map(modData, package); UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0); UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0); UpgradeRules.UpgradePlayers(engineDate, ref map.PlayerDefinitions, null, 0); UpgradeRules.UpgradeActors(engineDate, ref map.ActorDefinitions, null, 0); - map.Save(map.Path); + map.Save(package); } } } diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index b5870e51ac..eca15f45ea 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -16,6 +16,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; +using OpenRA.FileSystem; using OpenRA.Graphics; using OpenRA.Traits; @@ -3602,95 +3603,92 @@ namespace OpenRA.Mods.Common.UtilityCommands } } - internal static void UpgradeMapFormat(ModData modData, string path) + internal static void UpgradeMapFormat(ModData modData, IReadWritePackage package) { - using (var package = modData.ModFiles.OpenWritablePackage(path)) + if (package == null) + return; + + var yamlStream = package.GetStream("map.yaml"); + if (yamlStream == null) + return; + + var yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, package.Name)); + var nd = yaml.ToDictionary(); + var mapFormat = FieldLoader.GetValue("MapFormat", nd["MapFormat"].Value); + if (mapFormat < 6) + throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(mapFormat, package.Name)); + + // Nothing to do + if (mapFormat >= 8) + return; + + // Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum + if (mapFormat < 7) { - if (package == null) - return; + MiniYaml useAsShellmap; + if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value)) + yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("Shellmap"))); + else if (nd["Type"].Value == "Mission" || nd["Type"].Value == "Campaign") + yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("MissionSelector"))); + } - var yamlStream = package.GetStream("map.yaml"); - if (yamlStream == null) - return; - - var yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, path)); - var nd = yaml.ToDictionary(); - var mapFormat = FieldLoader.GetValue("MapFormat", nd["MapFormat"].Value); - if (mapFormat < 6) - throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(mapFormat, path)); - - // Nothing to do - if (mapFormat >= 8) - return; - - // Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum - if (mapFormat < 7) + // Format 7 -> 8 replaced normalized HSL triples with rgb(a) hex colors + if (mapFormat < 8) + { + var players = yaml.Nodes.FirstOrDefault(n => n.Key == "Players"); + if (players != null) { - MiniYaml useAsShellmap; - if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value)) - yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("Shellmap"))); - else if (nd["Type"].Value == "Mission" || nd["Type"].Value == "Campaign") - yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("MissionSelector"))); - } - - // Format 7 -> 8 replaced normalized HSL triples with rgb(a) hex colors - if (mapFormat < 8) - { - var players = yaml.Nodes.FirstOrDefault(n => n.Key == "Players"); - if (players != null) + bool noteHexColors = false; + bool noteColorRamp = false; + foreach (var player in players.Value.Nodes) { - bool noteHexColors = false; - bool noteColorRamp = false; - foreach (var player in players.Value.Nodes) + var colorRampNode = player.Value.Nodes.FirstOrDefault(n => n.Key == "ColorRamp"); + if (colorRampNode != null) { - var colorRampNode = player.Value.Nodes.FirstOrDefault(n => n.Key == "ColorRamp"); - if (colorRampNode != null) + Color dummy; + var parts = colorRampNode.Value.Value.Split(','); + if (parts.Length == 3 || parts.Length == 4) { - Color dummy; - var parts = colorRampNode.Value.Value.Split(','); - if (parts.Length == 3 || parts.Length == 4) + // Try to convert old normalized HSL value to a rgb hex color + try { - // Try to convert old normalized HSL value to a rgb hex color - try - { - HSLColor color = new HSLColor( - (byte)Exts.ParseIntegerInvariant(parts[0].Trim()).Clamp(0, 255), - (byte)Exts.ParseIntegerInvariant(parts[1].Trim()).Clamp(0, 255), - (byte)Exts.ParseIntegerInvariant(parts[2].Trim()).Clamp(0, 255)); - colorRampNode.Value.Value = FieldSaver.FormatValue(color); - noteHexColors = true; - } - catch (Exception) - { - throw new InvalidDataException("Invalid ColorRamp value.\n File: " + path); - } + HSLColor color = new HSLColor( + (byte)Exts.ParseIntegerInvariant(parts[0].Trim()).Clamp(0, 255), + (byte)Exts.ParseIntegerInvariant(parts[1].Trim()).Clamp(0, 255), + (byte)Exts.ParseIntegerInvariant(parts[2].Trim()).Clamp(0, 255)); + colorRampNode.Value.Value = FieldSaver.FormatValue(color); + noteHexColors = true; + } + catch (Exception) + { + throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name); } - else if (parts.Length != 1 || !HSLColor.TryParseRGB(parts[0], out dummy)) - throw new InvalidDataException("Invalid ColorRamp value.\n File: " + path); - - colorRampNode.Key = "Color"; - noteColorRamp = true; } + else if (parts.Length != 1 || !HSLColor.TryParseRGB(parts[0], out dummy)) + throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name); + + colorRampNode.Key = "Color"; + noteColorRamp = true; } - - Console.WriteLine("Converted " + path + " to MapFormat 8."); - if (noteHexColors) - Console.WriteLine("ColorRamp is now called Color and uses rgb(a) hex value - rrggbb[aa]."); - else if (noteColorRamp) - Console.WriteLine("ColorRamp is now called Color."); } - } - var entries = new Dictionary(); - entries.Add("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString())); - foreach (var file in package.Contents) - { - if (file == "map.yaml") - continue; - - entries.Add(file, package.GetStream(file).ReadAllBytes()); + Console.WriteLine("Converted " + package.Name + " to MapFormat 8."); + if (noteHexColors) + Console.WriteLine("ColorRamp is now called Color and uses rgb(a) hex value - rrggbb[aa]."); + else if (noteColorRamp) + Console.WriteLine("ColorRamp is now called Color."); } } + + var entries = new Dictionary(); + entries.Add("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString())); + foreach (var file in package.Contents) + { + if (file == "map.yaml") + continue; + + entries.Add(file, package.GetStream(file).ReadAllBytes()); + } } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs index d31fa851ee..8a455ba667 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs @@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var maxTerrainHeight = world.Map.Grid.MaximumTerrainHeight; var tileset = modRules.TileSets[tilesetDropDown.Text]; - var map = new Map(tileset, width + 2, height + maxTerrainHeight + 2); + var map = new Map(Game.ModData, tileset, width + 2, height + maxTerrainHeight + 2); var tl = new PPos(1, 1); var br = new PPos(width, height + maxTerrainHeight); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs index 654d648b5a..be817544d8 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs @@ -76,6 +76,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var mapDirectories = modData.Manifest.MapFolders .ToDictionary(kv => makeMapDirectory(kv.Key), kv => Enum.Parse(kv.Value)); + var mapPath = map.Package != null ? map.Package.Name : null; var directoryDropdown = widget.Get("DIRECTORY_DROPDOWN"); { Func setupItem = (option, template) => @@ -87,7 +88,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic return item; }; - var mapDirectory = map.Path != null ? Platform.UnresolvePath(Path.GetDirectoryName(map.Path)) : null; + // TODO: This won't work for maps inside oramod packages + var mapDirectory = mapPath != null ? Platform.UnresolvePath(Path.GetDirectoryName(mapPath)) : null; var initialDirectory = mapDirectories.Keys.FirstOrDefault(f => f == mapDirectory); // Prioritize MapClassification.User directories over system directories @@ -101,14 +103,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic var mapIsUnpacked = false; - if (map.Path != null) + // TODO: This won't work for maps inside oramod packages + if (mapPath != null) { - var attr = File.GetAttributes(map.Path); + var attr = File.GetAttributes(mapPath); mapIsUnpacked = attr.HasFlag(FileAttributes.Directory); } var filename = widget.Get("FILENAME"); - filename.Text = mapIsUnpacked ? Path.GetFileName(map.Path) : Path.GetFileNameWithoutExtension(map.Path); + filename.Text = mapIsUnpacked ? Path.GetFileName(mapPath) : Path.GetFileNameWithoutExtension(mapPath); var fileType = mapIsUnpacked ? MapFileType.Unpacked : MapFileType.OraMap; var fileTypes = new Dictionary() @@ -159,17 +162,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic // Create the map directory if required Directory.CreateDirectory(Platform.ResolvePath(directoryDropdown.Text)); + // TODO: This won't work for maps inside oramod packages var combinedPath = Platform.ResolvePath(Path.Combine(directoryDropdown.Text, filename.Text + fileTypes[fileType].Extension)); // Invalidate the old map metadata - if (map.Uid != null && combinedPath == map.Path) + if (map.Uid != null && combinedPath == mapPath) modData.MapCache[map.Uid].Invalidate(); - map.Save(combinedPath); + var package = modData.ModFiles.CreatePackage(combinedPath); + map.Save(package); // Update the map cache so it can be loaded without restarting the game var classification = mapDirectories[directoryDropdown.Text]; - modData.MapCache[map.Uid].UpdateFromMap(map.Container, classification, null, map.Grid.Type); + modData.MapCache[map.Uid].UpdateFromMap(map.Package, classification, null, map.Grid.Type); Console.WriteLine("Saved current map at {0}", combinedPath); Ui.CloseWindow(); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs index 2c75ba1478..b25e53f593 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs @@ -738,14 +738,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (MapPreview.Uid == uid) return; - MapPreview = Game.ModData.MapCache[uid]; + var modData = Game.ModData; + MapPreview = modData.MapCache[uid]; Map = null; if (MapPreview.Status == MapStatus.Available) { // Maps need to be validated and pre-loaded before they can be accessed new Thread(_ => { - var currentMap = Map = new Map(MapPreview.Path); + var currentMap = Map = new Map(modData, MapPreview.Package); currentMap.PreloadRules(); Game.RunAfterTick(() => { diff --git a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs index 234fb202de..ee576f8401 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs @@ -285,7 +285,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic string DeleteMap(string map) { - var path = Game.ModData.MapCache[map].Path; + var path = Game.ModData.MapCache[map].Package.Name; try { if (File.Exists(path)) diff --git a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs index 3f418698ae..483cc0d98d 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs @@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly ScrollPanelWidget missionList; readonly ScrollItemWidget headerTemplate; readonly ScrollItemWidget template; - readonly Cache mapCache = new Cache(p => new Map(p.Path)); + readonly Cache mapCache; MapPreview selectedMapPreview; Map selectedMap; @@ -56,6 +56,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic public MissionBrowserLogic(Widget widget, World world, Action onStart, Action onExit) { modData = Game.ModData; + mapCache = new Cache(p => new Map(modData, p.Package)); this.onStart = onStart; missionList = widget.Get("MISSION_LIST"); @@ -109,8 +110,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic var missionMapPaths = kv.Value.Nodes.Select(n => Path.GetFullPath(n.Key)).ToList(); var previews = modData.MapCache - .Where(p => p.Status == MapStatus.Available && missionMapPaths.Contains(Path.GetFullPath(p.Path))) - .OrderBy(p => missionMapPaths.IndexOf(Path.GetFullPath(p.Path))); + .Where(p => p.Status == MapStatus.Available && missionMapPaths.Contains(p.Package.Name)) + .OrderBy(p => missionMapPaths.IndexOf(p.Package.Name)); CreateMissionGroup(kv.Key, previews); allPreviews.AddRange(previews); diff --git a/OpenRA.Mods.D2k/UtilityCommands/D2kMapImporter.cs b/OpenRA.Mods.D2k/UtilityCommands/D2kMapImporter.cs index 6e935f2499..d15333cc62 100644 --- a/OpenRA.Mods.D2k/UtilityCommands/D2kMapImporter.cs +++ b/OpenRA.Mods.D2k/UtilityCommands/D2kMapImporter.cs @@ -310,7 +310,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands tileSet = rules.TileSets["ARRAKIS"]; - map = new Map(tileSet, mapSize.Width + 2 * MapCordonWidth, mapSize.Height + 2 * MapCordonWidth) + map = new Map(Game.ModData, tileSet, mapSize.Width + 2 * MapCordonWidth, mapSize.Height + 2 * MapCordonWidth) { Title = Path.GetFileNameWithoutExtension(mapFile), Author = "Westwood Studios" diff --git a/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs b/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs index 31bca5b5e2..387c2932b8 100644 --- a/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs +++ b/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs @@ -36,9 +36,9 @@ namespace OpenRA.Mods.D2k.UtilityCommands if (map == null) return; - var fileName = Path.GetFileNameWithoutExtension(args[1]); - var dest = fileName + ".oramap"; - map.Save(dest); + var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap"; + var package = modData.ModFiles.CreatePackage(dest); + map.Save(package); Console.WriteLine(dest + " saved."); } } diff --git a/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs b/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs index 2dddf0a5e4..7a06785b5f 100644 --- a/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs +++ b/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs @@ -172,9 +172,9 @@ namespace OpenRA.Mods.TS.UtilityCommands var mapPlayers = new MapPlayers(map.Rules, spawnCount); map.PlayerDefinitions = mapPlayers.ToMiniYaml(); - var fileName = Path.GetFileNameWithoutExtension(filename); - var dest = fileName + ".oramap"; - map.Save(dest); + var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap"; + var package = modData.ModFiles.CreatePackage(dest); + map.Save(package); Console.WriteLine(dest + " saved."); } @@ -222,7 +222,7 @@ namespace OpenRA.Mods.TS.UtilityCommands fullSize = new int2(iniSize[2], iniSize[3]); - var map = new Map(modData.DefaultRules.TileSets[tileset], size.Width, size.Height); + var map = new Map(Game.ModData, modData.DefaultRules.TileSets[tileset], size.Width, size.Height); map.Title = basic.GetValue("Name", Path.GetFileNameWithoutExtension(filename)); map.Author = "Westwood Studios"; map.Bounds = new Rectangle(iniBounds[0], iniBounds[1], iniBounds[2], 2 * iniBounds[3] + 2 * iniBounds[1]);