optimizations

This commit is contained in:
Boki 2026-03-06 00:38:30 -05:00
parent 419e2eb4a4
commit d124f2c288
44 changed files with 1663 additions and 639 deletions

View file

@ -20,6 +20,11 @@ public sealed class UIElements : RemoteObject
private readonly MsvcStringReader _strings;
// Cached quest parent pointers — resolved once, reused across reads
private nint _cachedTrackedPanelAddr; // GameUi[6][1]
private nint _cachedQuestParentAddr; // GameUi[6][1][0][0][0]
private nint _cachedForGameUi; // GameUiPtr when cache was built
/// <summary>Optional lookup for resolving quest state IDs to human-readable text.</summary>
public QuestStateLookup? QuestStateLookup { get; set; }
@ -192,6 +197,38 @@ public sealed class UIElements : RemoteObject
return node;
}
/// <summary>
/// Resolves and caches quest parent pointers from the UI tree.
/// Called lazily; cache invalidated when GameUiPtr changes.
/// </summary>
private void EnsureQuestPointerCache()
{
if (_cachedForGameUi == GameUiPtr && _cachedTrackedPanelAddr != 0)
return; // cache is valid
_cachedForGameUi = GameUiPtr;
_cachedTrackedPanelAddr = 0;
_cachedQuestParentAddr = 0;
if (GameUiPtr == 0) return;
var offsets = Ctx.Offsets;
// GameUi[6] → [1] for tracked quests
var elem6 = ReadChildAtIndex(GameUiPtr, offsets.TrackedQuestPanelChildIndex);
if (elem6 is not null)
{
var elem61 = ReadChildAtIndex(elem6.Address, offsets.TrackedQuestPanelSubChildIndex);
if (elem61 is not null)
_cachedTrackedPanelAddr = elem61.Address;
}
// GameUi[6][1][0][0][0] for quest groups
var questParent = NavigatePath(GameUiPtr, [6, 1, 0, 0, 0]);
if (questParent is not null)
_cachedQuestParentAddr = questParent.Address;
}
/// <summary>
/// Reads quest groups from the UI tree.
/// Path: GameUi[6][1][0][0][0] → quest_display → [0] → title_layout/quest_info_layout
@ -200,11 +237,10 @@ public sealed class UIElements : RemoteObject
{
if (GameUiPtr == 0) return null;
// Navigate to the parent that holds quest_display nodes
var questParent = NavigatePath(GameUiPtr, [6, 1, 0, 0, 0]);
if (questParent is null) return null;
EnsureQuestPointerCache();
if (_cachedQuestParentAddr == 0) return null;
var questDisplays = ReadChildren(questParent.Address);
var questDisplays = ReadChildren(_cachedQuestParentAddr);
if (questDisplays is null) return null;
var groups = new List<UiQuestGroup>();
@ -318,18 +354,15 @@ public sealed class UIElements : RemoteObject
var mem = Ctx.Memory;
var offsets = Ctx.Offsets;
// ── Tracked quests: [6][1]+0x318 — collect into dict keyed by QuestDatPtr ──
EnsureQuestPointerCache();
// ── Tracked quests: cached [6][1]+0x318 — collect into dict keyed by QuestDatPtr ──
var trackedMap = new Dictionary<nint, string?>();
var elem6 = ReadChildAtIndex(GameUiPtr, offsets.TrackedQuestPanelChildIndex);
if (elem6 is not null)
if (_cachedTrackedPanelAddr != 0)
{
var elem61 = ReadChildAtIndex(elem6.Address, offsets.TrackedQuestPanelSubChildIndex);
if (elem61 is not null)
{
var trackedHead = mem.ReadPointer(elem61.Address + offsets.TrackedQuestLinkedListOffset);
if (trackedHead != 0)
TraverseTrackedQuests(trackedHead, trackedMap);
}
var trackedHead = mem.ReadPointer(_cachedTrackedPanelAddr + offsets.TrackedQuestLinkedListOffset);
if (trackedHead != 0)
TraverseTrackedQuests(trackedHead, trackedMap);
}
// ── All quests: GameUi+0x358 ──
@ -563,5 +596,8 @@ public sealed class UIElements : RemoteObject
{
UiRootPtr = 0;
GameUiPtr = 0;
_cachedForGameUi = 0;
_cachedTrackedPanelAddr = 0;
_cachedQuestParentAddr = 0;
}
}