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 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; }
public string Path { get { return Package.Name; } }
// Yaml map data
public string Uid { get; private set; }
@@ -251,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));
}
@@ -260,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.
/// </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);
Grid = Game.ModData.Manifest.Get<MapGrid>();
Grid = modData.Manifest.Get<MapGrid>();
var tileRef = new TerrainTile(tileset.Templates.First().Key, 0);
Title = "Name your map here";
@@ -302,18 +305,21 @@ namespace OpenRA
/// <summary>Initializes a map loaded from disk.</summary>
public Map(string path)
: this(Game.ModData, Game.ModData.ModFiles.OpenPackage(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(() =>
{
@@ -345,19 +351,19 @@ namespace OpenRA
MapResources = Exts.Lazy(LoadResourceTiles);
MapHeight = Exts.Lazy(LoadMapHeight);
Grid = Game.ModData.Manifest.Get<MapGrid>();
Grid = modData.Manifest.Get<MapGrid>();
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();
Uid = ComputeUID(Container);
Uid = ComputeUID(Package);
}
void PostInit()
@@ -366,7 +372,7 @@ namespace OpenRA
{
try
{
return Game.ModData.RulesetCache.Load(this, this);
return modData.RulesetCache.Load(this, this);
}
catch (Exception e)
{
@@ -374,7 +380,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]);
@@ -489,6 +495,11 @@ namespace OpenRA
}
public void Save(string toPath)
{
Save(modData.ModFiles.CreatePackage(toPath, new Dictionary<string, byte[]>()));
}
public void Save(IReadWritePackage toContainer)
{
MapFormat = 8;
@@ -538,37 +549,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<TerrainTile> LoadMapTiles()
{
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);
if (header.TilesOffset > 0)
@@ -600,7 +605,7 @@ namespace OpenRA
public CellLayer<byte> LoadMapHeight()
{
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);
if (header.HeightsOffset > 0)
@@ -622,7 +627,7 @@ namespace OpenRA
{
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);
if (header.ResourcesOffset > 0)
@@ -1173,16 +1178,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)
@@ -1190,21 +1195,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);
}
}
}

View File

@@ -60,7 +60,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"

View File

@@ -55,7 +55,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);

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
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();

View File

@@ -309,7 +309,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"

View File

@@ -221,7 +221,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]);