diff --git a/OpenRA.Mods.Cnc/FileSystem/MixFile.cs b/OpenRA.Mods.Cnc/FileSystem/MixFile.cs index f9c9c5af7c..afc902d36b 100644 --- a/OpenRA.Mods.Cnc/FileSystem/MixFile.cs +++ b/OpenRA.Mods.Cnc/FileSystem/MixFile.cs @@ -32,7 +32,7 @@ namespace OpenRA.Mods.Cnc.FileSystem readonly long dataStart; readonly Stream s; - public MixFile(Stream s, string filename, HashSet allPossibleFilenames) + public MixFile(Stream s, string filename, string[] globalFilenames) { Name = filename; this.s = s; @@ -55,7 +55,7 @@ namespace OpenRA.Mods.Cnc.FileSystem index = ParseIndex(entries.ToDictionaryWithConflictLog(x => x.Hash, $"{filename} ({(isCncMix ? "C&C" : "RA/TS/RA2")} format, Encrypted: {isEncrypted}, DataStart: {dataStart})", - null, x => $"(offs={x.Offset}, len={x.Length})"), allPossibleFilenames); + null, x => $"(offs={x.Offset}, len={x.Length})"), globalFilenames); } catch (Exception) { @@ -64,10 +64,11 @@ namespace OpenRA.Mods.Cnc.FileSystem } } - Dictionary ParseIndex(Dictionary entries, HashSet allPossibleFilenames) + Dictionary ParseIndex(Dictionary entries, string[] globalFilenames) { var classicIndex = new Dictionary(); var crcIndex = new Dictionary(); + IEnumerable allPossibleFilenames = globalFilenames; // Try and find a local mix database var dbNameClassic = PackageEntry.HashFilename("local mix database.dat", PackageHashType.Classic); @@ -79,15 +80,14 @@ namespace OpenRA.Mods.Cnc.FileSystem using (var content = GetContent(kv.Value)) { var db = new XccLocalDatabase(content); - foreach (var e in db.Entries) - allPossibleFilenames.Add(e); + allPossibleFilenames = allPossibleFilenames.Concat(db.Entries); } break; } } - foreach (var filename in allPossibleFilenames) + foreach (var filename in allPossibleFilenames.Distinct()) { var classicHash = PackageEntry.HashFilename(filename, PackageHashType.Classic); var crcHash = PackageEntry.HashFilename(filename, PackageHashType.CRC32); @@ -223,6 +223,8 @@ namespace OpenRA.Mods.Cnc.FileSystem } } + string[] globalFilenames; + bool IPackageLoader.TryParsePackage(Stream s, string filename, FS context, out IReadOnlyPackage package) { if (!filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase)) @@ -232,13 +234,12 @@ namespace OpenRA.Mods.Cnc.FileSystem } // Load the global mix database - var allPossibleFilenames = new HashSet(); - if (context.TryOpen("global mix database.dat", out var mixDatabase)) - using (var db = new XccGlobalDatabase(mixDatabase)) - foreach (var e in db.Entries) - allPossibleFilenames.Add(e); + if (globalFilenames == null) + if (context.TryOpen("global mix database.dat", out var mixDatabase)) + using (var db = new XccGlobalDatabase(mixDatabase)) + globalFilenames = db.Entries.Distinct().ToArray(); - package = new MixFile(s, filename, allPossibleFilenames); + package = new MixFile(s, filename, globalFilenames ?? Array.Empty()); return true; } } diff --git a/OpenRA.Mods.Cnc/UtilityCommands/ListMixContentsCommand.cs b/OpenRA.Mods.Cnc/UtilityCommands/ListMixContentsCommand.cs index e06f2ec936..f9f9e741ee 100644 --- a/OpenRA.Mods.Cnc/UtilityCommands/ListMixContentsCommand.cs +++ b/OpenRA.Mods.Cnc/UtilityCommands/ListMixContentsCommand.cs @@ -10,7 +10,6 @@ #endregion using System; -using System.Collections.Generic; using System.IO; using System.Linq; using OpenRA.Mods.Cnc.FileFormats; @@ -30,12 +29,11 @@ namespace OpenRA.Mods.Cnc.UtilityCommands [Desc("ARCHIVE.MIX", "MIXDATABASE.DAT", "Lists the content ranges for a mix file")] void IUtilityCommand.Run(Utility utility, string[] args) { - var allPossibleFilenames = new HashSet(); + string[] globalFilenames; using (var db = new XccGlobalDatabase(File.OpenRead(args[2]))) - foreach (var e in db.Entries) - allPossibleFilenames.Add(e); + globalFilenames = db.Entries; - var package = new MixLoader.MixFile(File.OpenRead(args[1]), args[1], allPossibleFilenames); + var package = new MixLoader.MixFile(File.OpenRead(args[1]), args[1], globalFilenames); foreach (var kv in package.Index.OrderBy(kv => kv.Value.Offset)) { Console.WriteLine("{0}:", kv.Key);