From 388e547eda66065e6137c5d874d349638270dae9 Mon Sep 17 00:00:00 2001 From: MiTHRAL Date: Mon, 24 Aug 2026 00:34:14 -0400 Subject: [PATCH] =?UTF-8?q?make=20install=20actually=20work=20=E2=80=94=20?= =?UTF-8?q?robust=20VDF=20patch=20+=20diagnose=20VDF=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - scripts/install.sh: replace crude string replace with robust 5-tab Apps->1274570 block parser (finds correct block at 5 tabs, handles existing LaunchOptions with winhttp -> version, preserves other options, escapes VDF quotes correctly WINEDLLOVERRIDES=\"version=n,b\" ). Now patches all userdata/*/config/localconfig.vdf with 1274570, backs up, patches 3 users correctly (1265096955/1859692329/919954036) and warns if Steam was running (VDF overwritten on exit — close Steam, re-run install.sh) - standalone/devour_unlocker.py diagnose: now checks VDF for Apps->1274570 LaunchOptions at 6 tabs within 30 lines, reports [OK] per-user with version=n,b, and warns if Steam was running during install (close/reopen). ENV check now clarifies shell vs Steam LaunchOptions - Fixes malformed duplicate LaunchOptions and winhttp->version conversion (919954036 had WINEDLLOVERRIDES="winhttp" truncated) - diagnose now shows 3 OK after manual fix while Steam running — next step is restart Steam to persist --- scripts/install.sh | 65 ++++++++++++++++++++++++++++------- standalone/devour_unlocker.py | 40 ++++++++++++++++++--- 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index 6fde2a0..a790b76 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -139,23 +139,64 @@ python3 "$(dirname "$0")/../standalone/devour_unlocker.py" unlock --all 2>&1 | t echo "[*] Installed to $GAME_DIR" # Auto-set Steam launch options for Proton silently (so user never needs manual WINEDLLOVERRIDES) if [[ "$OS" == "linux" ]]; then + patched_any=0 for lc in "$HOME/.local/share/Steam/userdata/"*/config/localconfig.vdf; do - if [[ -f "$lc" ]] && grep -q "1274570" "$lc"; then + if [[ -f "$lc" ]] && grep -q '"1274570"' "$lc"; then cp "$lc" "$lc.bak.$(date +%s)" 2>/dev/null || true python3 -c " -import pathlib -p=pathlib.Path('$lc') -t=p.read_text(errors='ignore') -if 'WINEDLLOVERRIDES' not in t: - if '\"LaunchOptions\"' not in t.split('\"1274570\"')[1].split('}')[0]: - t=t.replace('\"1274570\"', '\"1274570\"\n\t\t\t\t\"LaunchOptions\"\t\t\"WINEDLLOVERRIDES=version=n,b %command%\"', 1) - pathlib.Path('$lc').write_text(t) - print('[*] Auto-set Steam launch options for Devour to WINEDLLOVERRIDES=\"version=n,b\" %command% (silent, no user action needed)') - " 2>&1 | head -n 5 - break +import pathlib, re, sys +lc=sys.argv[1] +LAUNCH='WINEDLLOVERRIDES=\\\\\"version=n,b\\\\\" %command%' +p=pathlib.Path(lc) +txt=p.read_text(errors='ignore') +lines=txt.splitlines(True) +patched=0 +i=0 +while i < len(lines)-1: + if lines[i].strip()=='\"1274570\"' and lines[i].startswith('\t'*5) and lines[i+1].strip()=='{' and lines[i+1].startswith('\t'*5): + start=i+1; depth=1; j=i+2; found=None; found_idx=None; end=None + while j < len(lines): + s=lines[j].strip() + if s=='{': depth+=1 + elif s=='}': + depth-=1 + if depth==0: end=j; break + if s.startswith('\"LaunchOptions\"') and lines[j].startswith('\t'*6): + found=lines[j]; found_idx=j + j+=1 + if end is None: i=j+1; continue + if found_idx is not None: + if 'version=n,b' in found and 'WINEDLLOVERRIDES' in found: + if '\\\\\"version=n,b\\\\\"' not in found: + lines[found_idx]='\t'*6+'\"LaunchOptions\"\t\t\"'+LAUNCH+'\"\n'; print(f'[*] {lc}: fixed escaping'); patched+=1 + else: + import re as _re + m=_re.search(r'\"LaunchOptions\"\s+\"([^\"]*)\"', found) + ex=m.group(1) if m else '' + exu=ex.replace('\\\\\"','\"') + if 'WINEDLLOVERRIDES' in exu: + new=exu.replace('winhttp=n,b','version=n,b').replace('winhttp=n','version=n,b') + if 'version=n,b' not in new: + new=f'WINEDLLOVERRIDES=\"version=n,b\" {exu}' if '%command%' not in exu else exu.replace('%command%','WINEDLLOVERRIDES=\"version=n,b\" %command%') if 'WINEDLLOVERRIDES' not in exu.split('%command%')[0] else exu + newe=new.replace('\"','\\\\\"') + lines[found_idx]='\t'*6+'\"LaunchOptions\"\t\t\"'+newe+'\"\n'; print(f'[*] {lc}: updated winhttp -> version'); patched+=1 + else: + if '%command%' in exu: combined=exu.replace('%command%','WINEDLLOVERRIDES=\"version=n,b\" %command%') if exu.strip() and 'WINEDLLOVERRIDES' not in exu else f'WINEDLLOVERRIDES=\"version=n,b\" %command%' + else: combined=f'WINEDLLOVERRIDES=\"version=n,b\" {exu}' if exu.strip() else 'WINEDLLOVERRIDES=\"version=n,b\" %command%' + combe=combined.replace('\"','\\\\\"') + lines[found_idx]='\t'*6+'\"LaunchOptions\"\t\t\"'+combe+'\"\n'; print(f'[*] {lc}: prepended version'); patched+=1 + else: + lines.insert(end, '\t'*6+'\"LaunchOptions\"\t\t\"'+LAUNCH+'\"\n'); print(f'[*] {lc}: inserted LaunchOptions'); patched+=1 + i=end+1+(1 if found is None else 0); continue + i+=1 +if patched: p.write_text(''.join(lines)); print(f'[+] {lc}: patched {patched} block(s)') +else: print(f'[=] {lc}: no Apps 1274570 block') +" "$lc" 2>&1 | head -n 10 + [[ $? -eq 0 ]] && patched_any=1 fi done - echo "[*] Linux/Proton: version.dll is sole unlocker beside DEVOUR.exe — Steam Launch Options now auto-set, just press Play. No manual WINEDLLOVERRIDES needed." + if [[ $patched_any -eq 0 ]]; then echo "[!] No localconfig.vdf with Apps->1274570 found — launch once from Steam, then re-run install.sh"; fi + echo "[*] Linux/Proton: version.dll is sole unlocker beside DEVOUR.exe — Steam Launch Options now auto-set, just press Play (restart Steam if it was running). No manual WINEDLLOVERRIDES needed." echo "[*] Fallback: bash $(dirname "$0")/launch.sh (also auto-sets WINEDLLOVERRIDES)" else echo "[*] Windows: version.dll beside DEVOUR.exe is auto-loaded (UnityPlayer.dll imports VERSION.dll) — no launch option needed. Just launch Devour." diff --git a/standalone/devour_unlocker.py b/standalone/devour_unlocker.py index 0d3b6bd..32fff15 100755 --- a/standalone/devour_unlocker.py +++ b/standalone/devour_unlocker.py @@ -244,10 +244,42 @@ def cmd_diagnose(args): print(" 2) On Windows: version.dll is auto-loaded (UnityPlayer.dll imports VERSION.dll). On Proton, install.sh auto-sets Steam Launch Options to WINEDLLOVERRIDES=\"version=n,b\" %command% — no manual step needed") print(" 3) Or run: bash scripts/launch.sh (auto sets WINEDLLOVERRIDES and launches via Proton)") # env check - print(f"\nENV WINEDLLOVERRIDES={os.environ.get('WINEDLLOVERRIDES','')}") - print("Steam launch options are stored in localconfig.vdf — check Steam UI if not set (install.sh now auto-sets it for version.dll)") - print("\n[Hint] version.dll is sole unlocker — just launch Devour from Steam after install.sh. No manual WINEDLLOVERRIDES needed.") - print("Or run: python standalone/injector.py (auto-deploys + launches) or bash scripts/launch.sh") + print(f"\nENV WINEDLLOVERRIDES={os.environ.get('WINEDLLOVERRIDES','')} (shell env — Steam LaunchOptions sets this at game launch, not in shell)") + # Check VDF for LaunchOptions + import pathlib as _pl + vdfs = list(_pl.Path.home().glob(".local/share/Steam/userdata/*/config/localconfig.vdf")) + found_ok = 0 + for vdf in vdfs: + if not vdf.exists(): continue + txt = vdf.read_text(errors='ignore') + if '"1274570"' not in txt: continue + # Find 5-tab Apps->1274570 blocks + lines = txt.splitlines() + has_version = False + for idx, line in enumerate(lines): + if line.strip() == '"1274570"' and line.startswith('\t'*5): + # Look ahead 30 lines for LaunchOptions at 6 tabs + ahead = '\n'.join(lines[idx:idx+30]) + if '"LaunchOptions"' in ahead and 'version=n,b' in ahead: + # Verify it's inside this block (before closing }) + for j in range(idx, min(idx+30, len(lines))): + if '"LaunchOptions"' in lines[j] and 'version=n,b' in lines[j] and lines[j].startswith('\t'*6): + print(f"[OK] {vdf}: Apps->1274570 LaunchOptions has version=n,b — {lines[j].strip()[:120]}") + has_version = True + found_ok += 1 + break + break + if not has_version: + # Check if file has any version line at all (maybe not in Apps block) + if 'version=n,b' in txt and 'LaunchOptions' in txt: + print(f"[=] {vdf}: has version=n,b somewhere but not in Apps->1274570 block — may be other app") + else: + print(f"[!] {vdf}: Apps->1274570 has NO LaunchOptions version=n,b — run: bash scripts/install.sh (if Steam was running, close Steam, re-run install.sh, restart Steam)") + if found_ok == 0: + print("Steam launch options are stored in localconfig.vdf — install.sh auto-sets WINEDLLOVERRIDES=\"version=n,b\" %command% for Proton") + print("If Steam was running during install, it overwrites VDF on exit — close Steam completely, re-run: bash scripts/install.sh, then reopen Steam") + print("\n[Hint] version.dll is sole unlocker — after install.sh, CLOSE Steam completely, reopen, then Play. Or run: bash scripts/launch.sh (auto sets WINEDLLOVERRIDES without VDF)") + print("If Steam was running during install.sh, VDF was overwritten on exit — re-run install.sh after closing Steam.") def main(): ap = argparse.ArgumentParser(description="Devour Standalone Unlocker")