Rework IReadWritePackage interface.

This commit is contained in:
Paul Chote
2016-02-24 22:28:47 +00:00
parent bee3eb2c0a
commit 617113fa86
10 changed files with 68 additions and 97 deletions

View File

@@ -34,17 +34,6 @@ namespace OpenRA.FileSystem
Cache<string, List<IReadOnlyPackage>> fileIndex = new Cache<string, List<IReadOnlyPackage>>(_ => new List<IReadOnlyPackage>()); Cache<string, List<IReadOnlyPackage>> fileIndex = new Cache<string, List<IReadOnlyPackage>>(_ => new List<IReadOnlyPackage>());
public IReadWritePackage CreatePackage(string filename)
{
var content = new Dictionary<string, byte[]>();
if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(this, filename, content);
if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(this, filename, content);
return new Folder(filename, content);
}
public IReadOnlyPackage OpenPackage(string filename) public IReadOnlyPackage OpenPackage(string filename)
{ {
if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))

View File

@@ -18,16 +18,6 @@ namespace OpenRA.FileSystem
{ {
readonly string path; readonly string path;
// Create a new folder package
public Folder(string path, Dictionary<string, byte[]> contents)
{
this.path = path;
if (Directory.Exists(path))
Directory.Delete(path, true);
Write(contents);
}
public Folder(string path) public Folder(string path)
{ {
this.path = path; this.path = path;
@@ -57,15 +47,22 @@ namespace OpenRA.FileSystem
return File.Exists(Path.Combine(path, filename)); return File.Exists(Path.Combine(path, filename));
} }
public void Write(Dictionary<string, byte[]> contents) public void Update(string filename, byte[] contents)
{ {
if (!Directory.Exists(path)) if (!Directory.Exists(path))
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
foreach (var file in contents) using (var s = File.Create(Path.Combine(path, filename)))
using (var dataStream = File.Create(Path.Combine(path, file.Key))) s.Write(contents, 0, contents.Length);
using (var writer = new BinaryWriter(dataStream)) }
writer.Write(file.Value);
public void Delete(string filename)
{
var filePath = Path.Combine(path, filename);
if (Directory.Exists(filePath))
Directory.Delete(filePath, true);
else if (File.Exists(filePath))
File.Delete(filePath);
} }
public void Dispose() { } public void Dispose() { }

View File

@@ -25,6 +25,7 @@ namespace OpenRA.FileSystem
public interface IReadWritePackage : IReadOnlyPackage public interface IReadWritePackage : IReadOnlyPackage
{ {
void Write(Dictionary<string, byte[]> contents); void Update(string filename, byte[] contents);
void Delete(string filename);
} }
} }

View File

@@ -27,31 +27,14 @@ namespace OpenRA.FileSystem
ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage; ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;
} }
public ZipFile(FileSystem context, string filename) public ZipFile(IReadOnlyFileSystem context, string filename, bool createOrClearContents = false)
{ {
Name = filename; Name = filename;
try if (createOrClearContents)
{ pkg = SZipFile.Create(filename);
// Pull the file into memory, don't keep it open. else
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename))); pkg = new SZipFile(filename);
}
catch (ZipException e)
{
Log.Write("debug", "Couldn't load zip file: {0}", e.Message);
}
}
// Create a new zip with the specified contents.
public ZipFile(FileSystem context, string filename, Dictionary<string, byte[]> contents)
{
Name = filename;
if (File.Exists(filename))
File.Delete(filename);
pkg = SZipFile.Create(filename);
Write(contents);
} }
public Stream GetStream(string filename) public Stream GetStream(string filename)
@@ -83,19 +66,18 @@ namespace OpenRA.FileSystem
return pkg.GetEntry(filename) != null; return pkg.GetEntry(filename) != null;
} }
public void Write(Dictionary<string, byte[]> contents) public void Update(string filename, byte[] contents)
{ {
// TODO: Clear existing content?
pkg.Close();
pkg = SZipFile.Create(Name);
pkg.BeginUpdate(); pkg.BeginUpdate();
pkg.Add(new StaticMemoryDataSource(contents), filename);
foreach (var kvp in contents) pkg.CommitUpdate();
pkg.Add(new StaticMemoryDataSource(kvp.Value), kvp.Key); }
public void Delete(string filename)
{
pkg.BeginUpdate();
pkg.Delete(filename);
pkg.CommitUpdate(); pkg.CommitUpdate();
pkg.Close();
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(Name)));
} }
public void Dispose() public void Dispose()

View File

@@ -490,7 +490,7 @@ namespace OpenRA
return rules.Value; return rules.Value;
} }
public void Save(IReadWritePackage toContainer) public void Save(IReadWritePackage toPackage)
{ {
MapFormat = 8; MapFormat = 8;
@@ -534,31 +534,17 @@ namespace OpenRA
root.Add(new MiniYamlNode("Notifications", null, NotificationDefinitions)); root.Add(new MiniYamlNode("Notifications", null, NotificationDefinitions));
root.Add(new MiniYamlNode("Translations", null, TranslationDefinitions)); root.Add(new MiniYamlNode("Translations", null, TranslationDefinitions));
var entries = new Dictionary<string, byte[]>(); if (Package != null && toPackage != Package)
entries.Add("map.bin", SaveBinaryData());
var s = root.WriteToString();
entries.Add("map.yaml", Encoding.UTF8.GetBytes(s));
// Add any custom assets
if (Package != null)
{
foreach (var file in Package.Contents) foreach (var file in Package.Contents)
{ toPackage.Update(file, Package.GetStream(file).ReadAllBytes());
if (file == "map.bin" || file == "map.yaml")
continue;
entries.Add(file, Package.GetStream(file).ReadAllBytes()); var s = root.WriteToString();
} toPackage.Update("map.yaml", Encoding.UTF8.GetBytes(s));
} toPackage.Update("map.bin", SaveBinaryData());
Package = toPackage;
// Saving the map to a new location
Package = toContainer;
// Update existing package
toContainer.Write(entries);
// Update UID to match the newly saved data // Update UID to match the newly saved data
Uid = ComputeUID(toContainer); Uid = ComputeUID(toPackage);
} }
public CellLayer<TerrainTile> LoadMapTiles() public CellLayer<TerrainTile> LoadMapTiles()

View File

@@ -14,6 +14,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using OpenRA.FileSystem;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common.FileFormats; using OpenRA.Mods.Common.FileFormats;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
@@ -95,7 +96,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
Map.FixOpenAreas(Rules); Map.FixOpenAreas(Rules);
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap"; var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
var package = modData.ModFiles.CreatePackage(dest); var package = new ZipFile(modData.ModFiles, dest, true);
Map.Save(package); Map.Save(package);
Console.WriteLine(dest + " saved."); Console.WriteLine(dest + " saved.");
} }

View File

@@ -785,17 +785,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
yaml.Nodes.First(n => n.Key == "MapFormat").Value = new MiniYaml(Map.SupportedMapFormat.ToString()); yaml.Nodes.First(n => n.Key == "MapFormat").Value = new MiniYaml(Map.SupportedMapFormat.ToString());
var entries = new Dictionary<string, byte[]>(); package.Update("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString()));
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());
}
package.Write(entries);
} }
} }
} }

View File

@@ -169,8 +169,32 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (map.Uid != null && combinedPath == mapPath) if (map.Uid != null && combinedPath == mapPath)
modData.MapCache[map.Uid].Invalidate(); modData.MapCache[map.Uid].Invalidate();
var package = modData.ModFiles.CreatePackage(combinedPath); var package = map.Package as IReadWritePackage;
map.Save(package); if (package == null || package.Name != combinedPath)
{
try
{
if (fileType == MapFileType.OraMap)
{
if (File.Exists(combinedPath))
File.Delete(combinedPath);
package = new ZipFile(modData.DefaultFileSystem, combinedPath, true);
}
else
{
if (Directory.Exists(combinedPath))
Directory.Delete(combinedPath, true);
package = new Folder(combinedPath);
}
map.Save(package);
}
catch
{
Console.WriteLine("Failed to save map at {0}", combinedPath);
}
}
// 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];

View File

@@ -11,6 +11,7 @@
using System; using System;
using System.IO; using System.IO;
using OpenRA.FileSystem;
namespace OpenRA.Mods.D2k.UtilityCommands namespace OpenRA.Mods.D2k.UtilityCommands
{ {
@@ -37,7 +38,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands
return; return;
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap"; var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
var package = modData.ModFiles.CreatePackage(dest); var package = new ZipFile(modData.DefaultFileSystem, dest, true);
map.Save(package); map.Save(package);
Console.WriteLine(dest + " saved."); Console.WriteLine(dest + " saved.");
} }

View File

@@ -179,7 +179,7 @@ namespace OpenRA.Mods.TS.UtilityCommands
map.PlayerDefinitions = mapPlayers.ToMiniYaml(); map.PlayerDefinitions = mapPlayers.ToMiniYaml();
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap"; var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
var package = modData.ModFiles.CreatePackage(dest); var package = new ZipFile(modData.DefaultFileSystem, dest, true);
map.Save(package); map.Save(package);
Console.WriteLine(dest + " saved."); Console.WriteLine(dest + " saved.");
} }