feat(net): #13 heuristic inventory locator after gameplay_options blob
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d9a5e40203
commit
91693ea44c
2 changed files with 90 additions and 1 deletions
|
|
@ -402,7 +402,17 @@ public static class PlayerDescriptionParser
|
|||
if (optionFlags.HasFlag(CharacterOptionDataFlag.CharacterOptions2))
|
||||
options2 = ReadU32(payload, ref pos);
|
||||
|
||||
if (!optionFlags.HasFlag(CharacterOptionDataFlag.GameplayOptions))
|
||||
if (optionFlags.HasFlag(CharacterOptionDataFlag.GameplayOptions))
|
||||
{
|
||||
int gameplayStart = pos;
|
||||
if (TryHeuristicInventoryStart(payload, gameplayStart, out int invStart, out int end,
|
||||
inventory, equipped))
|
||||
{
|
||||
gameplayOptions = payload.Slice(gameplayStart, invStart - gameplayStart).ToArray();
|
||||
pos = end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Strict path: inventory + equipped follow directly.
|
||||
TryUnpackInventoryStrict(payload, ref pos, inventory, equipped);
|
||||
|
|
@ -760,6 +770,43 @@ public static class PlayerDescriptionParser
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>4-byte-aligned forward scan from <paramref name="start"/>
|
||||
/// looking for the first offset where <c>TryUnpackInventoryStrict</c>
|
||||
/// consumes exactly to end-of-buffer. Mirrors holtburger
|
||||
/// <c>find_inventory_start_after_gameplay_options</c> in events.rs:195-218.</summary>
|
||||
private static bool TryHeuristicInventoryStart(
|
||||
ReadOnlySpan<byte> src, int start,
|
||||
out int invStart, out int end,
|
||||
List<InventoryEntry> inventory, List<EquippedEntry> equipped)
|
||||
{
|
||||
invStart = end = 0;
|
||||
inventory.Clear();
|
||||
equipped.Clear();
|
||||
if (start + 8 > src.Length) return false;
|
||||
|
||||
int candidate = start;
|
||||
int misalign = candidate & 3;
|
||||
if (misalign != 0) candidate += 4 - misalign;
|
||||
|
||||
int last = src.Length - 8;
|
||||
while (candidate <= last)
|
||||
{
|
||||
int tmp = candidate;
|
||||
var tmpInv = new List<InventoryEntry>();
|
||||
var tmpEq = new List<EquippedEntry>();
|
||||
if (TryUnpackInventoryStrict(src, ref tmp, tmpInv, tmpEq) && tmp == src.Length)
|
||||
{
|
||||
invStart = candidate;
|
||||
end = tmp;
|
||||
inventory.AddRange(tmpInv);
|
||||
equipped.AddRange(tmpEq);
|
||||
return true;
|
||||
}
|
||||
candidate += 4;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static ushort ReadU16(ReadOnlySpan<byte> src, ref int pos)
|
||||
{
|
||||
if (src.Length - pos < 2) throw new FormatException("truncated u16");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue