test(scripts): enable the hook on the deployed launcher without a rebuild
Bridges openfut-launcher c542415 onto the already-built launcher on .105 by writing WINEDLLOVERRIDES=version=n,b into game_profile.env, which that build does apply. Forward-compatible: the fixed launcher defers to a profile that already pins version=, so this value simply wins. Records the prior value -- including its absence, as the literal <absent> -- to a sidecar before mutating, so revert restores the real previous state instead of assuming the key was missing. Refuses to edit while the launcher runs, since it holds its config in memory and would write the stale value back.
This commit is contained in:
Executable
+138
@@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Ensure the deployed launcher starts FIFA with the hook's WINEDLLOVERRIDES.
|
||||
|
||||
The hook ships as a `version.dll` proxy in the game directory, and Proton prefers a
|
||||
local DLL over its own builtin ONLY when WINEDLLOVERRIDES names it. Launcher builds
|
||||
before openfut-launcher c542415 apply `game_profile.env` but never that override, so
|
||||
the hook silently never loads -- and with no hook there is no port rewrite, the
|
||||
openfut.cfg the launcher just wrote is inert, and the client reaches EA's real Blaze
|
||||
ports (production, via /etc/hosts) while looking like a healthy configured launch.
|
||||
|
||||
This writes the override into `game_profile.env`, which the deployed launcher DOES
|
||||
apply, so it works without rebuilding. It is forward-compatible with the fixed
|
||||
launcher: hook_dll_overrides() defers to a profile that already pins `version=`, so
|
||||
the value set here simply wins and nothing conflicts.
|
||||
|
||||
python3 scripts/client-hook-override.py show
|
||||
python3 scripts/client-hook-override.py apply
|
||||
python3 scripts/client-hook-override.py revert
|
||||
|
||||
Safety: the prior value (including its absence) is recorded to a sidecar before the
|
||||
first mutation, so `revert` restores the real previous state rather than guessing;
|
||||
every operation re-reads and prints the result; and it refuses to edit while the
|
||||
launcher is running, because the launcher holds its config in memory and would write
|
||||
the stale value straight back over ours.
|
||||
"""
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
CLIENT = "alex@10.10.0.105"
|
||||
CFG = "/home/alex/.config/openfut-launcher/config.json"
|
||||
SIDECAR = "/home/alex/.config/openfut-launcher/config.json.openfut-prev-dlloverrides"
|
||||
KEY = "WINEDLLOVERRIDES"
|
||||
HOOK = "version=n,b"
|
||||
ABSENT = "<absent>"
|
||||
|
||||
|
||||
def ssh(script):
|
||||
r = subprocess.run(["ssh", "-o", "BatchMode=yes", CLIENT, script],
|
||||
capture_output=True, text=True, timeout=60)
|
||||
if r.returncode != 0:
|
||||
raise SystemExit(f"ssh failed ({r.returncode}): {r.stderr.strip()}")
|
||||
return r.stdout
|
||||
|
||||
|
||||
def launcher_running():
|
||||
"""comm is truncated by the kernel to 15 chars ("openfut-launche")."""
|
||||
out = ssh("for d in /proc/[0-9]*; do c=$(cat $d/comm 2>/dev/null); "
|
||||
"case \"$c\" in openfut-launche*) echo ${d#/proc/};; esac; done || true")
|
||||
return bool(out.strip())
|
||||
|
||||
|
||||
def fifa_running():
|
||||
out = ssh("for d in /proc/[0-9]*; do "
|
||||
"[ \"$(cat $d/comm 2>/dev/null)\" = FIFA17.exe ] && echo ${d#/proc/}; "
|
||||
"done || true")
|
||||
return bool(out.strip())
|
||||
|
||||
|
||||
def load():
|
||||
return json.loads(ssh(f'cat "{CFG}"'))
|
||||
|
||||
|
||||
def env_of(d):
|
||||
return d.setdefault("game_profile", {}).setdefault("env", {})
|
||||
|
||||
|
||||
def save(d):
|
||||
body = json.dumps(d, indent=2, sort_keys=True)
|
||||
ssh(f'cat > "{CFG}" <<\'EOF\'\n{body}\nEOF')
|
||||
|
||||
|
||||
def show():
|
||||
d = load()
|
||||
cur = env_of(d).get(KEY, ABSENT)
|
||||
print(f"--- {CFG}")
|
||||
print(f" game_profile.env[{KEY}] = {cur}")
|
||||
print(f" hook active on launch = {'YES' if 'version=' in cur else 'NO'}")
|
||||
side = ssh(f'cat "{SIDECAR}" 2>/dev/null || true').strip()
|
||||
print(f" recorded previous value = {side or '(none recorded yet)'}")
|
||||
print(f" launcher running = {'YES' if launcher_running() else 'no'}")
|
||||
return cur
|
||||
|
||||
|
||||
def guard():
|
||||
if fifa_running():
|
||||
raise SystemExit("REFUSING: a FIFA client is running; exit it first.")
|
||||
if launcher_running():
|
||||
raise SystemExit(
|
||||
"REFUSING: openfut-launcher is running. It holds its config in memory and\n"
|
||||
"would write the old value back over ours. Quit the launcher first.")
|
||||
|
||||
|
||||
def apply_override():
|
||||
guard()
|
||||
d = load()
|
||||
env = env_of(d)
|
||||
prior = env.get(KEY, ABSENT)
|
||||
if not ssh(f'cat "{SIDECAR}" 2>/dev/null || true').strip():
|
||||
ssh(f'cat > "{SIDECAR}" <<\'EOF\'\n{prior}\nEOF')
|
||||
print(f"recorded previous value to {SIDECAR}: {prior}")
|
||||
# Preserve an unrelated override rather than clobbering it, and never double up.
|
||||
if prior != ABSENT and "version=" in prior:
|
||||
print(f"already pins version= ({prior}); leaving it alone")
|
||||
return show()
|
||||
env[KEY] = HOOK if prior == ABSENT else f"{prior};{HOOK}"
|
||||
save(d)
|
||||
after = env_of(load()).get(KEY, ABSENT)
|
||||
if "version=" not in after:
|
||||
raise SystemExit(f"VERIFY FAILED: {KEY} is {after!r}")
|
||||
return show()
|
||||
|
||||
|
||||
def revert():
|
||||
guard()
|
||||
side = ssh(f'cat "{SIDECAR}" 2>/dev/null || true').strip()
|
||||
if not side:
|
||||
raise SystemExit(f"no recorded previous value at {SIDECAR}; refusing to guess")
|
||||
d = load()
|
||||
env = env_of(d)
|
||||
if side == ABSENT:
|
||||
env.pop(KEY, None)
|
||||
else:
|
||||
env[KEY] = side
|
||||
save(d)
|
||||
return show()
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2 or sys.argv[1] not in ("show", "apply", "revert"):
|
||||
print(__doc__)
|
||||
return 2
|
||||
{"show": show, "apply": apply_override, "revert": revert}[sys.argv[1]]()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user