import ctypes
import struct

k32 = ctypes.windll.kernel32
pid = 43084
h = k32.OpenProcess(0x10 | 0x400, False, pid)
assert h, f"Cannot open PID {pid}"

base = 0x7FF6AFC20000
root_rva = 0x45CCFE0
buf = (ctypes.c_char * 8)()
br = ctypes.c_size_t()

# Read InGameState
k32.ReadProcessMemory(h, ctypes.c_void_p(base + root_rva), buf, 8, ctypes.byref(br))
ingame = struct.unpack('<Q', bytes(buf))[0]

# Read PlayerEntity
k32.ReadProcessMemory(h, ctypes.c_void_p(ingame + 0xBE0), buf, 8, ctypes.byref(br))
player = struct.unpack('<Q', bytes(buf))[0]

print(f"InGameState: 0x{ingame:X}")
print(f"PlayerEntity: 0x{player:X}")

# Dump 0x600 bytes of PlayerEntity
pbuf = (ctypes.c_char * 0x600)()
k32.ReadProcessMemory(h, ctypes.c_void_p(player), pbuf, 0x600, ctypes.byref(br))
praw = bytes(pbuf)

print("\n--- PlayerEntity Pointer Scan (offsets with pointer-like values) ---")
for off in range(0, 0x600, 8):
    val = struct.unpack_from('<Q', praw, off)[0]
    if 0x10000 <= val <= 0x7FFFFFFFFFFF:
        # Dereference to see if it points to a vtable or text or heap
        tbuf = (ctypes.c_char * 32)()
        if k32.ReadProcessMemory(h, ctypes.c_void_p(val), tbuf, 32, ctypes.byref(br)):
            vt = struct.unpack_from('<Q', bytes(tbuf), 0)[0]
            print(f"  +0x{off:03X}: 0x{val:X} -> [0x{vt:X}]")

k32.CloseHandle(h)
