diff --git a/OpenRA.Game/FileSystem/BagFile.cs b/OpenRA.Game/FileSystem/BagFile.cs index 481851a21c..6de2349034 100644 --- a/OpenRA.Game/FileSystem/BagFile.cs +++ b/OpenRA.Game/FileSystem/BagFile.cs @@ -27,11 +27,13 @@ namespace OpenRA.FileSystem readonly Stream s; readonly int bagFilePriority; readonly Dictionary index; + readonly FileSystem context; - public BagFile(string filename, int priority) + public BagFile(FileSystem context, string filename, int priority) { bagFilename = filename; bagFilePriority = priority; + this.context = context; // A bag file is always accompanied with an .idx counterpart // For example: audio.bag requires the audio.idx file @@ -39,14 +41,14 @@ namespace OpenRA.FileSystem // Build the index and dispose the stream, it is no longer needed after this List entries; - using (var indexStream = Game.ModData.ModFiles.Open(indexFilename)) + using (var indexStream = context.Open(indexFilename)) entries = new IdxReader(indexStream).Entries; index = entries.ToDictionaryWithConflictLog(x => x.Hash, "{0} (bag format)".F(filename), null, x => "(offs={0}, len={1})".F(x.Offset, x.Length)); - s = Game.ModData.ModFiles.Open(filename); + s = context.Open(filename); } public int Priority { get { return 1000 + bagFilePriority; } } @@ -159,9 +161,9 @@ namespace OpenRA.FileSystem public IEnumerable AllFileNames() { var lookup = new Dictionary(); - if (Game.ModData.ModFiles.Exists("global mix database.dat")) + if (context.Exists("global mix database.dat")) { - var db = new XccGlobalDatabase(Game.ModData.ModFiles.Open("global mix database.dat")); + var db = new XccGlobalDatabase(context.Open("global mix database.dat")); foreach (var e in db.Entries) { var hash = IdxEntry.HashFilename(e, PackageHashType.CRC32); @@ -175,7 +177,7 @@ namespace OpenRA.FileSystem public void Write(Dictionary contents) { - Game.ModData.ModFiles.Unmount(this); + context.Unmount(this); throw new NotImplementedException("Updating bag files unsupported"); } diff --git a/OpenRA.Game/FileSystem/BigFile.cs b/OpenRA.Game/FileSystem/BigFile.cs index 5bb01e2cc6..5482f05ac4 100644 --- a/OpenRA.Game/FileSystem/BigFile.cs +++ b/OpenRA.Game/FileSystem/BigFile.cs @@ -22,12 +22,12 @@ namespace OpenRA.FileSystem readonly Dictionary entries = new Dictionary(); readonly Stream s; - public BigFile(string filename, int priority) + public BigFile(FileSystem context, string filename, int priority) { Name = filename; Priority = priority; - s = Game.ModData.ModFiles.Open(filename); + s = context.Open(filename); try { if (s.ReadASCII(4) != "BIGF") diff --git a/OpenRA.Game/FileSystem/D2kSoundResources.cs b/OpenRA.Game/FileSystem/D2kSoundResources.cs index 7ffc27c0e0..2b74b133f2 100644 --- a/OpenRA.Game/FileSystem/D2kSoundResources.cs +++ b/OpenRA.Game/FileSystem/D2kSoundResources.cs @@ -24,12 +24,12 @@ namespace OpenRA.FileSystem readonly Dictionary index = new Dictionary(); - public D2kSoundResources(string filename, int priority) + public D2kSoundResources(FileSystem context, string filename, int priority) { this.filename = filename; this.priority = priority; - s = Game.ModData.ModFiles.Open(filename); + s = context.Open(filename); try { filenames = new List(); diff --git a/OpenRA.Game/FileSystem/FileSystem.cs b/OpenRA.Game/FileSystem/FileSystem.cs index a239eed881..778f3f5f46 100644 --- a/OpenRA.Game/FileSystem/FileSystem.cs +++ b/OpenRA.Game/FileSystem/FileSystem.cs @@ -28,14 +28,14 @@ namespace OpenRA.FileSystem Cache> crcHashIndex = new Cache>(_ => new List()); Cache> classicHashIndex = new Cache>(_ => new List()); - public static IFolder CreatePackage(string filename, int order, Dictionary content) + public IFolder CreatePackage(string filename, int order, Dictionary content) { if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase)) - return new MixFile(filename, order, content); + return new MixFile(this, filename, order, content); if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) - return new ZipFile(filename, order, content); + return new ZipFile(this, filename, order, content); if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase)) - return new ZipFile(filename, order, content); + return new ZipFile(this, filename, order, content); if (filename.EndsWith(".RS", StringComparison.InvariantCultureIgnoreCase)) throw new NotImplementedException("The creation of .RS archives is unimplemented"); if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase)) @@ -50,7 +50,7 @@ namespace OpenRA.FileSystem return new Folder(filename, order, content); } - public static IFolder OpenPackage(string filename, string annotation, int order) + public IFolder OpenPackage(string filename, string annotation, int order) { if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase)) { @@ -58,25 +58,25 @@ namespace OpenRA.FileSystem ? PackageHashType.Classic : FieldLoader.GetValue("(value)", annotation); - return new MixFile(filename, type, order); + return new MixFile(this, filename, type, order); } if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) - return new ZipFile(filename, order); + return new ZipFile(this, filename, order); if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase)) - return new ZipFile(filename, order); + return new ZipFile(this, filename, order); if (filename.EndsWith(".RS", StringComparison.InvariantCultureIgnoreCase)) - return new D2kSoundResources(filename, order); + return new D2kSoundResources(this, filename, order); if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase)) - return new InstallShieldPackage(filename, order); + return new InstallShieldPackage(this, filename, order); if (filename.EndsWith(".PAK", StringComparison.InvariantCultureIgnoreCase)) - return new PakFile(filename, order); + return new PakFile(this, filename, order); if (filename.EndsWith(".big", StringComparison.InvariantCultureIgnoreCase)) - return new BigFile(filename, order); + return new BigFile(this, filename, order); if (filename.EndsWith(".bag", StringComparison.InvariantCultureIgnoreCase)) - return new BagFile(filename, order); + return new BagFile(this, filename, order); if (filename.EndsWith(".hdr", StringComparison.InvariantCultureIgnoreCase)) - return new InstallShieldCABExtractor(filename, order); + return new InstallShieldCABExtractor(this, filename, order); return new Folder(filename, order); } diff --git a/OpenRA.Game/FileSystem/InstallShieldCABExtractor.cs b/OpenRA.Game/FileSystem/InstallShieldCABExtractor.cs index c76e23f6e5..9086d90c33 100644 --- a/OpenRA.Game/FileSystem/InstallShieldCABExtractor.cs +++ b/OpenRA.Game/FileSystem/InstallShieldCABExtractor.cs @@ -186,6 +186,7 @@ namespace OpenRA.FileSystem class CabReader : IDisposable { + readonly FileSystem context; readonly FileDescriptor fileDes; public uint RemainingArchiveStream; public uint RemainingFileStream; @@ -194,11 +195,12 @@ namespace OpenRA.FileSystem ushort volumeNumber; Stream cabFile; - public CabReader(FileDescriptor fileDes, uint index, string commonName) + public CabReader(FileSystem context, FileDescriptor fileDes, uint index, string commonName) { this.fileDes = fileDes; this.index = index; this.commonName = commonName; + this.context = context; volumeNumber = (ushort)((uint)fileDes.Volume - 1u); RemainingArchiveStream = 0; if ((fileDes.Flags & FileCompressed) > 0) @@ -207,7 +209,7 @@ namespace OpenRA.FileSystem RemainingFileStream = fileDes.ExpandedSize; cabFile = null; - NextFile(); + NextFile(context); } public void CopyTo(Stream dest) @@ -257,7 +259,7 @@ namespace OpenRA.FileSystem var read = cabFile.Read(outArray, 0, (int)RemainingArchiveStream); if (RemainingFileStream > RemainingArchiveStream) { - NextFile(); + NextFile(context); RemainingArchiveStream -= (uint)cabFile.Read(outArray, read, (int)count - read); } @@ -270,13 +272,13 @@ namespace OpenRA.FileSystem cabFile.Dispose(); } - public void NextFile() + void NextFile(FileSystem context) { if (cabFile != null) cabFile.Dispose(); ++volumeNumber; - cabFile = Game.ModData.ModFiles.Open("{0}{1}.cab".F(commonName, volumeNumber)); + cabFile = context.Open("{0}{1}.cab".F(commonName, volumeNumber)); if (cabFile.ReadUInt32() != 0x28635349) throw new InvalidDataException("Not an Installshield CAB package"); @@ -328,19 +330,21 @@ namespace OpenRA.FileSystem readonly Dictionary directoryNames = new Dictionary(); readonly Dictionary fileDescriptors = new Dictionary(); readonly Dictionary fileLookup = new Dictionary(); + readonly FileSystem context; int priority; string commonName; public int Priority { get { return priority; } } public string Name { get { return commonName; } } - public InstallShieldCABExtractor(string hdrFilename, int priority = -1) + public InstallShieldCABExtractor(FileSystem context, string hdrFilename, int priority = -1) { var fileGroups = new List(); var fileGroupOffsets = new List(); + hdrFile = context.Open(hdrFilename); this.priority = priority; - hdrFile = Game.ModData.ModFiles.Open(hdrFilename); + this.context = context; // Strips archive number AND file extension commonName = Regex.Replace(hdrFilename, @"\d*\.[^\.]*$", ""); @@ -471,7 +475,7 @@ namespace OpenRA.FileSystem var output = new MemoryStream((int)fileDes.ExpandedSize); - using (var reader = new CabReader(fileDes, index, commonName)) + using (var reader = new CabReader(context, fileDes, index, commonName)) reader.CopyTo(output); if (output.Length != fileDes.ExpandedSize) @@ -496,7 +500,7 @@ namespace OpenRA.FileSystem if ((fileDes.Flags & FileObfuscated) != 0) throw new NotImplementedException("Haven't implemented obfuscated files"); - using (var reader = new CabReader(fileDes, index, commonName)) + using (var reader = new CabReader(context, fileDes, index, commonName)) reader.CopyTo(output); if (output.Length != fileDes.ExpandedSize) diff --git a/OpenRA.Game/FileSystem/InstallShieldPackage.cs b/OpenRA.Game/FileSystem/InstallShieldPackage.cs index 227a55f375..80127f936f 100644 --- a/OpenRA.Game/FileSystem/InstallShieldPackage.cs +++ b/OpenRA.Game/FileSystem/InstallShieldPackage.cs @@ -24,14 +24,14 @@ namespace OpenRA.FileSystem readonly int priority; readonly string filename; - public InstallShieldPackage(string filename, int priority) + public InstallShieldPackage(FileSystem context, string filename, int priority) { this.filename = filename; this.priority = priority; filenames = new List(); - s = Game.ModData.ModFiles.Open(filename); + s = context.Open(filename); try { // Parse package header diff --git a/OpenRA.Game/FileSystem/MixFile.cs b/OpenRA.Game/FileSystem/MixFile.cs index 6c53ef4680..bf65f4fc6d 100644 --- a/OpenRA.Game/FileSystem/MixFile.cs +++ b/OpenRA.Game/FileSystem/MixFile.cs @@ -25,14 +25,16 @@ namespace OpenRA.FileSystem readonly Stream s; readonly int priority; readonly string filename; + readonly FileSystem context; readonly PackageHashType type; // Save a mix to disk with the given contents - public MixFile(string filename, int priority, Dictionary contents) + public MixFile(FileSystem context, string filename, int priority, Dictionary contents) { this.filename = filename; this.priority = priority; this.type = PackageHashType.Classic; + this.context = context; if (File.Exists(filename)) File.Delete(filename); @@ -51,13 +53,14 @@ namespace OpenRA.FileSystem } } - public MixFile(string filename, PackageHashType type, int priority) + public MixFile(FileSystem context, string filename, PackageHashType type, int priority) { this.filename = filename; this.priority = priority; this.type = type; + this.context = context; - s = Game.ModData.ModFiles.Open(filename); + s = context.Open(filename); try { // Detect format type @@ -223,9 +226,9 @@ namespace OpenRA.FileSystem } } - if (Game.ModData.ModFiles.Exists("global mix database.dat")) + if (context.Exists("global mix database.dat")) { - var db = new XccGlobalDatabase(Game.ModData.ModFiles.Open("global mix database.dat")); + var db = new XccGlobalDatabase(context.Open("global mix database.dat")); foreach (var e in db.Entries) { var hash = PackageEntry.HashFilename(e, type); @@ -249,7 +252,7 @@ namespace OpenRA.FileSystem { // Cannot modify existing mixfile - rename existing file and // create a new one with original content plus modifications - Game.ModData.ModFiles.Unmount(this); + context.Unmount(this); // TODO: Add existing data to the contents list if (index.Count > 0) diff --git a/OpenRA.Game/FileSystem/Pak.cs b/OpenRA.Game/FileSystem/Pak.cs index 1793b297f6..51f69113f8 100644 --- a/OpenRA.Game/FileSystem/Pak.cs +++ b/OpenRA.Game/FileSystem/Pak.cs @@ -28,13 +28,13 @@ namespace OpenRA.FileSystem readonly Dictionary index; readonly Stream stream; - public PakFile(string filename, int priority) + public PakFile(FileSystem context, string filename, int priority) { this.filename = filename; this.priority = priority; index = new Dictionary(); - stream = Game.ModData.ModFiles.Open(filename); + stream = context.Open(filename); try { index = new Dictionary(); diff --git a/OpenRA.Game/FileSystem/ZipFile.cs b/OpenRA.Game/FileSystem/ZipFile.cs index 92cfbf6caf..cbf9b720bf 100644 --- a/OpenRA.Game/FileSystem/ZipFile.cs +++ b/OpenRA.Game/FileSystem/ZipFile.cs @@ -28,10 +28,11 @@ namespace OpenRA.FileSystem ZipConstants.DefaultCodePage = Encoding.Default.CodePage; } - public ZipFile(string filename, int priority) + public ZipFile(FileSystem context, string filename, int priority) { this.filename = filename; this.priority = priority; + try { // Pull the file into memory, don't keep it open. @@ -44,7 +45,7 @@ namespace OpenRA.FileSystem } // Create a new zip with the specified contents. - public ZipFile(string filename, int priority, Dictionary contents) + public ZipFile(FileSystem context, string filename, int priority, Dictionary contents) { this.priority = priority; this.filename = filename; diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 94b43faf63..9cec9efdcd 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -317,7 +317,7 @@ namespace OpenRA public Map(string path) { Path = path; - Container = FileSystem.FileSystem.OpenPackage(path, null, int.MaxValue); + Container = Game.ModData.ModFiles.OpenPackage(path, null, int.MaxValue); AssertExists("map.yaml"); AssertExists("map.bin"); @@ -650,7 +650,7 @@ namespace OpenRA Path = toPath; // Create a new map package - Container = FileSystem.FileSystem.CreatePackage(Path, int.MaxValue, entries); + Container = Game.ModData.ModFiles.CreatePackage(Path, int.MaxValue, entries); } // Update existing package diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index 8553119475..60ea3d44c0 100644 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -170,7 +170,7 @@ namespace OpenRA ModFiles.LoadFromManifest(Manifest); // Mount map package so custom assets can be used. TODO: check priority. - ModFiles.Mount(FS.OpenPackage(map.Path, null, int.MaxValue)); + ModFiles.Mount(ModFiles.OpenPackage(map.Path, null, int.MaxValue)); using (new Support.PerfTimer("Map.PreloadRules")) map.PreloadRules(); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromCDLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromCDLogic.cs index 89a096cf73..1d5b2be5cf 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromCDLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromCDLogic.cs @@ -94,7 +94,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic new Thread(() => { - using (var cabExtractor = new InstallShieldCABExtractor(source)) + using (var cabExtractor = new InstallShieldCABExtractor(Game.ModData.ModFiles, source)) { var denom = installData.InstallShieldCABFileIds.Count; var extractFiles = installData.ExtractFilesFromCD;