DevourUnlocker/tools/check_offsets.py
MiTHRAL 6329350e90
Some checks are pending
Build DevourUnlocker / windows-cross (push) Waiting to run
Build DevourUnlocker / linux (push) Waiting to run
Build DevourUnlocker / standalone (push) Waiting to run
add version.dll (less flagged) + per-platform installers with redownload/shift check
- version.dll proxy (6 exports GetFileVersionInfoA/W etc, runtime forwarding to C:\Windows\System32\version.dll, less flagged than winhttp) built via CMake version SHARED
- install.sh: platform detector (Linux/Darwin/Windows), --install/--uninstall/--update/--repair, detects Steam via libraryfolders.vdf, pulls version.dll+winhttp.dll+DevourUnlocker.dll per OS, backs up, patches collectables.json via devour_unlocker.py, handles Forgejo vs GitHub API, no BepInEx required but BepInEx still built as fallback, macOS note (no GameAssembly.dylib available)
- install.ps1: same for Windows (Find-GameDir, backup, version.dll primary)
- check_offsets.py: verifies GameAssembly sha1 and IsRobeUpdated/UpdateLockedPets still in global-metadata, warns if GameAssembly changed since last install
2026-08-24 00:03:19 -04:00

39 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""
Check if GameAssembly.dll unlock offsets have shifted since last install.
Uses the same logic as src/il2cpp_resolver.cpp: tries to resolve IsRobeUnlocked etc via
il2cpp_class_from_name + hasCollectedAll, and also checks collectables.json full sets.
If GameAssembly sha1 differs from DevourUnlocker.json:gameAssemblySha, warns to --repair.
"""
import pathlib, hashlib, json, sys, re
def sha1(p): return hashlib.sha1(open(p,'rb').read()).hexdigest()
def check(game_dir):
ga = pathlib.Path(game_dir) / "GameAssembly.dll"
gm = pathlib.Path(game_dir) / "DEVOUR_Data/il2cpp_data/Metadata/global-metadata.dat"
dj = pathlib.Path(game_dir) / "DevourUnlocker.json"
print(f"GameAssembly: {ga} exists={ga.exists()} sha1={sha1(ga) if ga.exists() else 'missing'}")
if gm.exists():
data=open(gm,'rb').read()
for needle in [b'IsRobeUnlocked', b'IsCharacterUnlocked', b'UpdateLockedPets', b'HasPerk']:
print(f" {needle.decode()} in global-metadata: {'FOUND' if needle in data else 'NOT FOUND'} at {data.find(needle) if needle in data else -1}")
if dj.exists():
j=json.loads(dj.read_text())
print(f"DevourUnlocker.json gameAssemblySha={j.get('gameAssemblySha','')}")
if ga.exists():
cur=sha1(ga)
if j.get('gameAssemblySha') and j['gameAssemblySha']!=cur:
print(f"[!] GameAssembly changed since last install (was {j['gameAssemblySha'][:8]} now {cur[:8]}) — run: bash scripts/install.sh --repair or .\\scripts\\install.ps1 -Update")
return 1
else:
print("[*] GameAssembly unchanged since last install")
# Also check collectables.json for all users
for p in pathlib.Path.home().glob(".local/share/Steam/userdata/*/1274570/remote/collectables.json"):
try:
j=json.loads(p.read_text())
print(f"collectables {p.parent.parent.name}: BarbedWires {j.get('BarbedWires')} ({len(j.get('BarbedWires',[]))})")
except: pass
return 0
if __name__=="__main__":
gd = sys.argv[1] if len(sys.argv)>1 else "/home/mithral/.local/share/Steam/steamapps/common/Devour"
sys.exit(check(gd))