Cache the global mix database in MixLoader
We can reuse this global database as it doesn't change, rather than loading a new copy each time a new mix file is parsed.
This commit is contained in:
@@ -32,7 +32,7 @@ namespace OpenRA.Mods.Cnc.FileSystem
|
||||
readonly long dataStart;
|
||||
readonly Stream s;
|
||||
|
||||
public MixFile(Stream s, string filename, HashSet<string> 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<string, PackageEntry> ParseIndex(Dictionary<uint, PackageEntry> entries, HashSet<string> allPossibleFilenames)
|
||||
Dictionary<string, PackageEntry> ParseIndex(Dictionary<uint, PackageEntry> entries, string[] globalFilenames)
|
||||
{
|
||||
var classicIndex = new Dictionary<string, PackageEntry>();
|
||||
var crcIndex = new Dictionary<string, PackageEntry>();
|
||||
IEnumerable<string> 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<string>();
|
||||
if (globalFilenames == null)
|
||||
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);
|
||||
globalFilenames = db.Entries.Distinct().ToArray();
|
||||
|
||||
package = new MixFile(s, filename, allPossibleFilenames);
|
||||
package = new MixFile(s, filename, globalFilenames ?? Array.Empty<string>());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user