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