Load and save maps using packages.

This commit is contained in:
Paul Chote
2016-02-20 17:23:49 +00:00
parent 9c3b967a47
commit 573e26c887
6 changed files with 48 additions and 43 deletions

View File

@@ -113,12 +113,14 @@ namespace OpenRA
public const int MaxTilesInCircleRange = 50; public const int MaxTilesInCircleRange = 50;
public readonly MapGrid Grid; public readonly MapGrid Grid;
readonly ModData modData;
[FieldLoader.Ignore] public readonly WVec[] SubCellOffsets; [FieldLoader.Ignore] public readonly WVec[] SubCellOffsets;
public readonly SubCell DefaultSubCell; public readonly SubCell DefaultSubCell;
public readonly SubCell LastSubCell; public readonly SubCell LastSubCell;
[FieldLoader.Ignore] public IReadWritePackage Container;
public string Path { get; private set; } public IReadOnlyPackage Package { get; private set; }
public string Path { get { return Package.Name; } }
// Yaml map data // Yaml map data
public string Uid { get; private set; } public string Uid { get; private set; }
@@ -251,7 +253,7 @@ namespace OpenRA
void AssertExists(string filename) void AssertExists(string filename)
{ {
using (var s = Container.GetStream(filename)) using (var s = Package.GetStream(filename))
if (s == null) if (s == null)
throw new InvalidOperationException("Required file {0} not present in this map".F(filename)); throw new InvalidOperationException("Required file {0} not present in this map".F(filename));
} }
@@ -260,10 +262,11 @@ namespace OpenRA
/// Initializes a new map created by the editor or importer. /// 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. /// The map will not receive a valid UID until after it has been saved and reloaded.
/// </summary> /// </summary>
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); var size = new Size(width, height);
Grid = Game.ModData.Manifest.Get<MapGrid>(); Grid = modData.Manifest.Get<MapGrid>();
var tileRef = new TerrainTile(tileset.Templates.First().Key, 0); var tileRef = new TerrainTile(tileset.Templates.First().Key, 0);
Title = "Name your map here"; Title = "Name your map here";
@@ -302,18 +305,21 @@ namespace OpenRA
/// <summary>Initializes a map loaded from disk.</summary> /// <summary>Initializes a map loaded from disk.</summary>
public Map(string path) public Map(string path)
: this(Game.ModData, Game.ModData.ModFiles.OpenPackage(path)) { }
public Map(ModData modData, IReadOnlyPackage package)
{ {
Path = path; this.modData = modData;
Container = Game.ModData.ModFiles.OpenWritablePackage(path); Package = package;
AssertExists("map.yaml"); AssertExists("map.yaml");
AssertExists("map.bin"); 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); FieldLoader.Load(this, yaml);
if (MapFormat != SupportedMapFormat) 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(() => SpawnPoints = Exts.Lazy(() =>
{ {
@@ -345,19 +351,19 @@ namespace OpenRA
MapResources = Exts.Lazy(LoadResourceTiles); MapResources = Exts.Lazy(LoadResourceTiles);
MapHeight = Exts.Lazy(LoadMapHeight); MapHeight = Exts.Lazy(LoadMapHeight);
Grid = Game.ModData.Manifest.Get<MapGrid>(); Grid = modData.Manifest.Get<MapGrid>();
SubCellOffsets = Grid.SubCellOffsets; SubCellOffsets = Grid.SubCellOffsets;
LastSubCell = (SubCell)(SubCellOffsets.Length - 1); LastSubCell = (SubCell)(SubCellOffsets.Length - 1);
DefaultSubCell = (SubCell)Grid.SubCellDefaultIndex; DefaultSubCell = (SubCell)Grid.SubCellDefaultIndex;
if (Container.Contains("map.png")) if (Package.Contains("map.png"))
using (var dataStream = Container.GetStream("map.png")) using (var dataStream = Package.GetStream("map.png"))
CustomPreview = new Bitmap(dataStream); CustomPreview = new Bitmap(dataStream);
PostInit(); PostInit();
Uid = ComputeUID(Container); Uid = ComputeUID(Package);
} }
void PostInit() void PostInit()
@@ -366,7 +372,7 @@ namespace OpenRA
{ {
try try
{ {
return Game.ModData.RulesetCache.Load(this, this); return modData.RulesetCache.Load(this, this);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -374,7 +380,7 @@ namespace OpenRA
Log.Write("debug", "Failed to load rules for {0} with error {1}", Title, e.Message); 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]); cachedTileSet = Exts.Lazy(() => Rules.TileSets[Tileset]);
@@ -489,6 +495,11 @@ namespace OpenRA
} }
public void Save(string toPath) public void Save(string toPath)
{
Save(modData.ModFiles.CreatePackage(toPath, new Dictionary<string, byte[]>()));
}
public void Save(IReadWritePackage toContainer)
{ {
MapFormat = 8; MapFormat = 8;
@@ -538,37 +549,31 @@ namespace OpenRA
entries.Add("map.yaml", Encoding.UTF8.GetBytes(s)); entries.Add("map.yaml", Encoding.UTF8.GetBytes(s));
// Add any custom assets // 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") if (file == "map.bin" || file == "map.yaml")
continue; continue;
entries.Add(file, Container.GetStream(file).ReadAllBytes()); entries.Add(file, Package.GetStream(file).ReadAllBytes());
} }
} }
// Saving the map to a new location // Saving the map to a new location
if (toPath != Path || Container == null) Package = toContainer;
{
Path = toPath;
// Create a new map package
Container = Game.ModData.ModFiles.CreatePackage(Path, entries);
}
// Update existing package // Update existing package
Container.Write(entries); toContainer.Write(entries);
// Update UID to match the newly saved data // Update UID to match the newly saved data
Uid = ComputeUID(Container); Uid = ComputeUID(toContainer);
} }
public CellLayer<TerrainTile> LoadMapTiles() public CellLayer<TerrainTile> LoadMapTiles()
{ {
var tiles = new CellLayer<TerrainTile>(this); var tiles = new CellLayer<TerrainTile>(this);
using (var s = Container.GetStream("map.bin")) using (var s = Package.GetStream("map.bin"))
{ {
var header = new BinaryDataHeader(s, MapSize); var header = new BinaryDataHeader(s, MapSize);
if (header.TilesOffset > 0) if (header.TilesOffset > 0)
@@ -600,7 +605,7 @@ namespace OpenRA
public CellLayer<byte> LoadMapHeight() public CellLayer<byte> LoadMapHeight()
{ {
var tiles = new CellLayer<byte>(this); var tiles = new CellLayer<byte>(this);
using (var s = Container.GetStream("map.bin")) using (var s = Package.GetStream("map.bin"))
{ {
var header = new BinaryDataHeader(s, MapSize); var header = new BinaryDataHeader(s, MapSize);
if (header.HeightsOffset > 0) if (header.HeightsOffset > 0)
@@ -622,7 +627,7 @@ namespace OpenRA
{ {
var resources = new CellLayer<ResourceTile>(this); var resources = new CellLayer<ResourceTile>(this);
using (var s = Container.GetStream("map.bin")) using (var s = Package.GetStream("map.bin"))
{ {
var header = new BinaryDataHeader(s, MapSize); var header = new BinaryDataHeader(s, MapSize);
if (header.ResourcesOffset > 0) if (header.ResourcesOffset > 0)
@@ -1173,16 +1178,16 @@ namespace OpenRA
public Stream Open(string filename) public Stream Open(string filename)
{ {
// Explicit package paths never refer to a map // Explicit package paths never refer to a map
if (!filename.Contains("|") && Container.Contains(filename)) if (!filename.Contains("|") && Package.Contains(filename))
return Container.GetStream(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) public bool TryGetPackageContaining(string path, out IReadOnlyPackage package, out string filename)
{ {
// Packages aren't supported inside maps // 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) public bool TryOpen(string filename, out Stream s)
@@ -1190,21 +1195,21 @@ namespace OpenRA
// Explicit package paths never refer to a map // Explicit package paths never refer to a map
if (!filename.Contains("|")) if (!filename.Contains("|"))
{ {
s = Container.GetStream(filename); s = Package.GetStream(filename);
if (s != null) if (s != null)
return true; return true;
} }
return Game.ModData.DefaultFileSystem.TryOpen(filename, out s); return modData.DefaultFileSystem.TryOpen(filename, out s);
} }
public bool Exists(string filename) public bool Exists(string filename)
{ {
// Explicit package paths never refer to a map // Explicit package paths never refer to a map
if (!filename.Contains("|") && Container.Contains(filename)) if (!filename.Contains("|") && Package.Contains(filename))
return true; return true;
return Game.ModData.DefaultFileSystem.Exists(filename); return modData.DefaultFileSystem.Exists(filename);
} }
} }
} }

View File

@@ -60,7 +60,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
ValidateMapFormat(format); ValidateMapFormat(format);
var tileset = GetTileset(mapSection); 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)), Title = basic.GetValue("Name", Path.GetFileNameWithoutExtension(filename)),
Author = "Westwood Studios" Author = "Westwood Studios"

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var maxTerrainHeight = world.Map.Grid.MaximumTerrainHeight; var maxTerrainHeight = world.Map.Grid.MaximumTerrainHeight;
var tileset = modRules.TileSets[tilesetDropDown.Text]; 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 tl = new PPos(1, 1);
var br = new PPos(width, height + maxTerrainHeight); var br = new PPos(width, height + maxTerrainHeight);

View File

@@ -168,7 +168,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// Update the map cache so it can be loaded without restarting the game // Update the map cache so it can be loaded without restarting the game
var classification = mapDirectories[directoryDropdown.Text]; 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); Console.WriteLine("Saved current map at {0}", combinedPath);
Ui.CloseWindow(); Ui.CloseWindow();

View File

@@ -309,7 +309,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands
tileSet = rules.TileSets["ARRAKIS"]; 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), Title = Path.GetFileNameWithoutExtension(mapFile),
Author = "Westwood Studios" Author = "Westwood Studios"

View File

@@ -221,7 +221,7 @@ namespace OpenRA.Mods.TS.UtilityCommands
fullSize = new int2(iniSize[2], iniSize[3]); 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.Title = basic.GetValue("Name", Path.GetFileNameWithoutExtension(filename));
map.Author = "Westwood Studios"; map.Author = "Westwood Studios";
map.Bounds = new Rectangle(iniBounds[0], iniBounds[1], iniBounds[2], 2 * iniBounds[3] + 2 * iniBounds[1]); map.Bounds = new Rectangle(iniBounds[0], iniBounds[1], iniBounds[2], 2 * iniBounds[3] + 2 * iniBounds[1]);