fixed stuff up

This commit is contained in:
Boki 2026-03-02 16:36:12 -05:00
parent 18d8721dd5
commit e5ebe05571
4 changed files with 69 additions and 63 deletions

View file

@ -1,3 +1,5 @@
using Roboto.GameOffsets.Components;
using Roboto.GameOffsets.Entities;
using Serilog;
namespace Roboto.Memory;
@ -36,15 +38,15 @@ public sealed class EntityReader
var hasComponentLookup = offsets.ComponentLookupEntrySize > 0;
var dirty = false;
WalkTreeInOrder(sentinel, root, maxNodes, node =>
WalkTreeInOrder(sentinel, root, maxNodes, (_, treeNode) =>
{
var entityPtr = mem.ReadPointer(node + offsets.EntityNodeValueOffset);
var entityPtr = treeNode.Data.EntityPtr;
if (entityPtr == 0) return;
var high = (ulong)entityPtr >> 32;
if (high == 0 || high >= 0x7FFF || (entityPtr & 0x3) != 0) return;
var entityId = mem.Read<uint>(entityPtr + offsets.EntityIdOffset);
var entityId = treeNode.Data.Key.EntityId;
var path = TryReadEntityPath(entityPtr);
var entity = new Entity(entityPtr, entityId, path);
@ -84,13 +86,13 @@ public sealed class EntityReader
var lifeComp = mem.ReadPointer(compFirst + lifeIdx * 8);
if (lifeComp != 0)
{
var hp = mem.Read<int>(lifeComp + offsets.LifeHealthOffset + offsets.VitalCurrentOffset);
var hpMax = mem.Read<int>(lifeComp + offsets.LifeHealthOffset + offsets.VitalTotalOffset);
if (hpMax > 0 && hpMax < 200000 && hp >= 0 && hp <= hpMax + 1000)
var life = mem.Read<Life>(lifeComp);
if (life.Health.Total > 0 && life.Health.Total < 200000 &&
life.Health.Current >= 0 && life.Health.Current <= life.Health.Total + 1000)
{
entity.HasVitals = true;
entity.LifeCurrent = hp;
entity.LifeTotal = hpMax;
entity.LifeCurrent = life.Health.Current;
entity.LifeTotal = life.Health.Total;
}
}
}
@ -109,14 +111,24 @@ public sealed class EntityReader
/// <summary>
/// Iterative in-order traversal of an MSVC std::map red-black tree.
/// Backward-compatible overload — delegates to the struct-based version.
/// </summary>
public void WalkTreeInOrder(nint sentinel, nint root, int maxNodes, Action<nint> visitor)
{
WalkTreeInOrder(sentinel, root, maxNodes, (addr, _) => visitor(addr));
}
/// <summary>
/// Iterative in-order traversal using Read&lt;EntityTreeNode&gt; — 1 kernel call per node
/// instead of separate Left/Right reads. The visitor receives both the node address
/// and the parsed struct data.
/// </summary>
public void WalkTreeInOrder(nint sentinel, nint root, int maxNodes, Action<nint, EntityTreeNode> visitor)
{
if (root == 0 || root == sentinel) return;
var offsets = _ctx.Offsets;
var mem = _ctx.Memory;
var stack = new Stack<nint>();
var stack = new Stack<(nint Addr, EntityTreeNode Node)>();
var current = root;
var count = 0;
var visited = new HashSet<nint> { sentinel };
@ -130,18 +142,19 @@ public sealed class EntityReader
current = sentinel;
break;
}
stack.Push(current);
current = mem.ReadPointer(current + offsets.EntityNodeLeftOffset);
var node = mem.Read<EntityTreeNode>(current);
stack.Push((current, node));
current = node.Left;
}
if (stack.Count == 0) break;
current = stack.Pop();
visitor(current);
var (nodeAddr, treeNode) = stack.Pop();
visitor(nodeAddr, treeNode);
count++;
if (count >= maxNodes) break;
current = mem.ReadPointer(current + offsets.EntityNodeRightOffset);
current = treeNode.Right;
}
}