From 617113fa86ae6beb3c2fca7e73d771c877658c85 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Wed, 24 Feb 2016 22:28:47 +0000 Subject: [PATCH] Rework IReadWritePackage interface. --- OpenRA.Game/FileSystem/FileSystem.cs | 11 ----- OpenRA.Game/FileSystem/Folder.cs | 27 +++++------ OpenRA.Game/FileSystem/IPackage.cs | 3 +- OpenRA.Game/FileSystem/ZipFile.cs | 46 ++++++------------- OpenRA.Game/Map/Map.cs | 30 ++++-------- .../UtilityCommands/ImportLegacyMapCommand.cs | 3 +- .../UtilityCommands/UpgradeRules.cs | 12 +---- .../Widgets/Logic/Editor/SaveMapLogic.cs | 28 ++++++++++- .../UtilityCommands/ImportD2kMapCommand.cs | 3 +- .../UtilityCommands/ImportTSMapCommand.cs | 2 +- 10 files changed, 68 insertions(+), 97 deletions(-) diff --git a/OpenRA.Game/FileSystem/FileSystem.cs b/OpenRA.Game/FileSystem/FileSystem.cs index 65c730afb1..76be7dd17e 100644 --- a/OpenRA.Game/FileSystem/FileSystem.cs +++ b/OpenRA.Game/FileSystem/FileSystem.cs @@ -34,17 +34,6 @@ namespace OpenRA.FileSystem Cache> fileIndex = new Cache>(_ => new List()); - 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)) - return new ZipFile(this, filename, content); - - return new Folder(filename, content); - } - public IReadOnlyPackage OpenPackage(string filename) { if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase)) diff --git a/OpenRA.Game/FileSystem/Folder.cs b/OpenRA.Game/FileSystem/Folder.cs index 6f0e448f43..cfcc2a8e26 100644 --- a/OpenRA.Game/FileSystem/Folder.cs +++ b/OpenRA.Game/FileSystem/Folder.cs @@ -18,16 +18,6 @@ namespace OpenRA.FileSystem { readonly string path; - // Create a new folder package - public Folder(string path, Dictionary contents) - { - this.path = path; - if (Directory.Exists(path)) - Directory.Delete(path, true); - - Write(contents); - } - public Folder(string path) { this.path = path; @@ -57,15 +47,22 @@ namespace OpenRA.FileSystem return File.Exists(Path.Combine(path, filename)); } - public void Write(Dictionary contents) + public void Update(string filename, byte[] contents) { if (!Directory.Exists(path)) Directory.CreateDirectory(path); - foreach (var file in contents) - using (var dataStream = File.Create(Path.Combine(path, file.Key))) - using (var writer = new BinaryWriter(dataStream)) - writer.Write(file.Value); + using (var s = File.Create(Path.Combine(path, filename))) + s.Write(contents, 0, contents.Length); + } + + 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() { } diff --git a/OpenRA.Game/FileSystem/IPackage.cs b/OpenRA.Game/FileSystem/IPackage.cs index 05e56ebfd7..5e6355068e 100644 --- a/OpenRA.Game/FileSystem/IPackage.cs +++ b/OpenRA.Game/FileSystem/IPackage.cs @@ -25,6 +25,7 @@ namespace OpenRA.FileSystem public interface IReadWritePackage : IReadOnlyPackage { - void Write(Dictionary contents); + void Update(string filename, byte[] contents); + void Delete(string filename); } } diff --git a/OpenRA.Game/FileSystem/ZipFile.cs b/OpenRA.Game/FileSystem/ZipFile.cs index ed97c83786..376e797e81 100644 --- a/OpenRA.Game/FileSystem/ZipFile.cs +++ b/OpenRA.Game/FileSystem/ZipFile.cs @@ -27,31 +27,14 @@ namespace OpenRA.FileSystem ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage; } - public ZipFile(FileSystem context, string filename) + public ZipFile(IReadOnlyFileSystem context, string filename, bool createOrClearContents = false) { Name = filename; - try - { - // Pull the file into memory, don't keep it open. - pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(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 contents) - { - Name = filename; - - if (File.Exists(filename)) - File.Delete(filename); - - pkg = SZipFile.Create(filename); - Write(contents); + if (createOrClearContents) + pkg = SZipFile.Create(filename); + else + pkg = new SZipFile(filename); } public Stream GetStream(string filename) @@ -83,19 +66,18 @@ namespace OpenRA.FileSystem return pkg.GetEntry(filename) != null; } - public void Write(Dictionary contents) + public void Update(string filename, byte[] contents) { - // TODO: Clear existing content? - pkg.Close(); - pkg = SZipFile.Create(Name); pkg.BeginUpdate(); - - foreach (var kvp in contents) - pkg.Add(new StaticMemoryDataSource(kvp.Value), kvp.Key); - + pkg.Add(new StaticMemoryDataSource(contents), filename); + pkg.CommitUpdate(); + } + + public void Delete(string filename) + { + pkg.BeginUpdate(); + pkg.Delete(filename); pkg.CommitUpdate(); - pkg.Close(); - pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(Name))); } public void Dispose() diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index e8c7cd928e..b4a1303f4b 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -490,7 +490,7 @@ namespace OpenRA return rules.Value; } - public void Save(IReadWritePackage toContainer) + public void Save(IReadWritePackage toPackage) { MapFormat = 8; @@ -534,31 +534,17 @@ namespace OpenRA root.Add(new MiniYamlNode("Notifications", null, NotificationDefinitions)); root.Add(new MiniYamlNode("Translations", null, TranslationDefinitions)); - var entries = new Dictionary(); - entries.Add("map.bin", SaveBinaryData()); - var s = root.WriteToString(); - entries.Add("map.yaml", Encoding.UTF8.GetBytes(s)); - - // Add any custom assets - if (Package != null) - { + if (Package != null && toPackage != Package) foreach (var file in Package.Contents) - { - if (file == "map.bin" || file == "map.yaml") - continue; + toPackage.Update(file, Package.GetStream(file).ReadAllBytes()); - entries.Add(file, Package.GetStream(file).ReadAllBytes()); - } - } - - // Saving the map to a new location - Package = toContainer; - - // Update existing package - toContainer.Write(entries); + var s = root.WriteToString(); + toPackage.Update("map.yaml", Encoding.UTF8.GetBytes(s)); + toPackage.Update("map.bin", SaveBinaryData()); + Package = toPackage; // Update UID to match the newly saved data - Uid = ComputeUID(toContainer); + Uid = ComputeUID(toPackage); } public CellLayer LoadMapTiles() diff --git a/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs index f3efe50437..099583d101 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using OpenRA.FileSystem; using OpenRA.Graphics; using OpenRA.Mods.Common.FileFormats; using OpenRA.Mods.Common.Traits; @@ -95,7 +96,7 @@ namespace OpenRA.Mods.Common.UtilityCommands Map.FixOpenAreas(Rules); var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap"; - var package = modData.ModFiles.CreatePackage(dest); + var package = new ZipFile(modData.ModFiles, dest, true); Map.Save(package); Console.WriteLine(dest + " saved."); } diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index b6405dd13e..e1a4d69047 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -785,17 +785,7 @@ namespace OpenRA.Mods.Common.UtilityCommands yaml.Nodes.First(n => n.Key == "MapFormat").Value = new MiniYaml(Map.SupportedMapFormat.ToString()); - 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()); - } - - package.Write(entries); + package.Update("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString())); } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs index db20d5f782..e20172d45e 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs @@ -169,8 +169,32 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (map.Uid != null && combinedPath == mapPath) modData.MapCache[map.Uid].Invalidate(); - var package = modData.ModFiles.CreatePackage(combinedPath); - map.Save(package); + var package = map.Package as IReadWritePackage; + 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 var classification = mapDirectories[directoryDropdown.Text]; diff --git a/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs b/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs index 387c2932b8..e57c34c162 100644 --- a/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs +++ b/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs @@ -11,6 +11,7 @@ using System; using System.IO; +using OpenRA.FileSystem; namespace OpenRA.Mods.D2k.UtilityCommands { @@ -37,7 +38,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands return; var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap"; - var package = modData.ModFiles.CreatePackage(dest); + var package = new ZipFile(modData.DefaultFileSystem, dest, true); map.Save(package); Console.WriteLine(dest + " saved."); } diff --git a/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs b/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs index 2b2c6efb75..0f42b7e616 100644 --- a/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs +++ b/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs @@ -179,7 +179,7 @@ namespace OpenRA.Mods.TS.UtilityCommands map.PlayerDefinitions = mapPlayers.ToMiniYaml(); var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap"; - var package = modData.ModFiles.CreatePackage(dest); + var package = new ZipFile(modData.DefaultFileSystem, dest, true); map.Save(package); Console.WriteLine(dest + " saved."); }