perf(content): remove exception-driven setup probes
This commit is contained in:
parent
f05afc07c1
commit
230a7df454
11 changed files with 598 additions and 47 deletions
|
|
@ -146,6 +146,53 @@ public sealed class DatCollectionAdapter : IDatReaderWriter {
|
|||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Direct, allocation-free production lookup. Portal precedence is
|
||||
/// load-bearing: the legacy ResolveId ordering is HighRes-first and its
|
||||
/// callers historically re-sorted the materialized results to make Portal
|
||||
/// win. Encode that rule once instead.
|
||||
/// </summary>
|
||||
public bool TryResolvePreferred(
|
||||
uint id,
|
||||
[NotNullWhen(true)] out IDatDatabase? database,
|
||||
out DBObjType type) {
|
||||
if (TryResolve(_portal, id, out type)) {
|
||||
database = _portal;
|
||||
return true;
|
||||
}
|
||||
if (TryResolve(_highRes, id, out type)) {
|
||||
database = _highRes;
|
||||
return true;
|
||||
}
|
||||
if (TryResolve(_language, id, out type)) {
|
||||
database = _language;
|
||||
return true;
|
||||
}
|
||||
if (TryResolve(_cell, id, out type)) {
|
||||
database = _cell;
|
||||
return true;
|
||||
}
|
||||
|
||||
database = null;
|
||||
type = DBObjType.Unknown;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryResolve(
|
||||
DatDatabaseWrapper database,
|
||||
uint id,
|
||||
out DBObjType type) {
|
||||
DatDatabase raw = database.RawDatabase;
|
||||
if (raw.Tree.TryGetFile(id, out _)) {
|
||||
type = raw.TypeFromId(id);
|
||||
if (type != DBObjType.Unknown)
|
||||
return true;
|
||||
}
|
||||
|
||||
type = DBObjType.Unknown;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TrySave<T>(T obj, int iteration = 0) where T : IDBObj =>
|
||||
throw new NotSupportedException("DatCollectionAdapter is read-only.");
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,57 @@ public interface IDatReaderWriter : IDisposable, IDatObjectSource {
|
|||
/// Resolves a data ID to all possible databases and types.
|
||||
/// </summary>
|
||||
public IEnumerable<IdResolution> ResolveId(uint id);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves one data ID using acdream's canonical precedence without
|
||||
/// materializing a result collection: Portal, HighRes, Language, Cell.
|
||||
/// Production's concrete adapter overrides this with direct B-tree probes.
|
||||
/// </summary>
|
||||
bool TryResolvePreferred(
|
||||
uint id,
|
||||
[NotNullWhen(true)] out IDatDatabase? database,
|
||||
out DBObjType type)
|
||||
{
|
||||
IDatDatabase? highRes = null;
|
||||
DBObjType highResType = DBObjType.Unknown;
|
||||
IDatDatabase? language = null;
|
||||
DBObjType languageType = DBObjType.Unknown;
|
||||
IDatDatabase? cell = null;
|
||||
DBObjType cellType = DBObjType.Unknown;
|
||||
|
||||
foreach (IdResolution resolution in ResolveId(id))
|
||||
{
|
||||
if (ReferenceEquals(resolution.Database, Portal))
|
||||
{
|
||||
database = resolution.Database;
|
||||
type = resolution.Type;
|
||||
return true;
|
||||
}
|
||||
if (ReferenceEquals(resolution.Database, HighRes))
|
||||
{
|
||||
highRes = resolution.Database;
|
||||
highResType = resolution.Type;
|
||||
}
|
||||
else if (ReferenceEquals(resolution.Database, Language))
|
||||
{
|
||||
language = resolution.Database;
|
||||
languageType = resolution.Type;
|
||||
}
|
||||
else if (ReferenceEquals(resolution.Database, Cell))
|
||||
{
|
||||
cell = resolution.Database;
|
||||
cellType = resolution.Type;
|
||||
}
|
||||
}
|
||||
|
||||
database = highRes ?? language ?? cell;
|
||||
type = highRes is not null
|
||||
? highResType
|
||||
: language is not null
|
||||
? languageType
|
||||
: cellType;
|
||||
return database is not null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -356,7 +356,11 @@ public sealed class DatPreparedAssetSource : IPreparedAssetSource
|
|||
};
|
||||
if (expected == DBObjType.Unknown)
|
||||
return PreparedAssetPresence.Missing;
|
||||
return _dats.ResolveId(sourceFileId).Any(r => r.Type == expected)
|
||||
return _dats.TryResolvePreferred(
|
||||
sourceFileId,
|
||||
out _,
|
||||
out DBObjType actual)
|
||||
&& actual == expected
|
||||
? PreparedAssetPresence.Available
|
||||
: PreparedAssetPresence.Missing;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,12 +87,11 @@ public sealed class MeshExtractor {
|
|||
try {
|
||||
// Use the low 32 bits as the DAT file ID
|
||||
var datId = (uint)(id & 0xFFFFFFFFu);
|
||||
var resolutions = _dats.ResolveId(datId);
|
||||
var selectedResolution = resolutions.OrderByDescending(r => r.Database == _dats.Portal).FirstOrDefault();
|
||||
if (selectedResolution == null) return null;
|
||||
|
||||
var type = selectedResolution.Type;
|
||||
var db = selectedResolution.Database;
|
||||
if (!_dats.TryResolvePreferred(
|
||||
datId,
|
||||
out IDatDatabase? db,
|
||||
out DBObjType type))
|
||||
return null;
|
||||
|
||||
if (type == DBObjType.Setup) {
|
||||
if (!db.TryGet<Setup>(datId, out var setup)) return null;
|
||||
|
|
@ -203,12 +202,11 @@ public sealed class MeshExtractor {
|
|||
}
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
var resolutions = _dats.ResolveId(id);
|
||||
var selectedResolution = resolutions.OrderByDescending(r => r.Database == _dats.Portal).FirstOrDefault();
|
||||
if (selectedResolution == null) return;
|
||||
|
||||
var type = selectedResolution.Type;
|
||||
var db = selectedResolution.Database;
|
||||
if (!_dats.TryResolvePreferred(
|
||||
id,
|
||||
out IDatDatabase? db,
|
||||
out DBObjType type))
|
||||
return;
|
||||
|
||||
if (type == DBObjType.Setup) {
|
||||
if (!db.TryGet<Setup>(id, out var setup)) return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue