#!/usr/bin/env python3 """Frozen local rescue faction fixture; no live server or installed asset writes.""" from pathlib import Path import hashlib,json,shutil,subprocess,sys ROOT=Path(__file__).resolve().parents[3] sys.path.insert(0,str(ROOT/'tools')) from source_manifest import addon_manifest from headless_game import assert_no_game,assert_prefix_idle name=sys.argv[1] scope=sys.argv[2] if len(sys.argv)>2 else 'full' if scope not in {'full','flight','flight-short','preparation'}: raise ValueError('Unknown fixture scope') if not name.isalnum(): raise ValueError('Use an alphanumeric run suffix') source=Path('/tmp/erri-rescue-factions-source-'+name) profile=Path('/tmp/erri-rescue-factions-run-'+name) compat=Path('/tmp/erri-headless-compat') assert_no_game();assert_prefix_idle(compat) source.mkdir();profile.mkdir() manifest=addon_manifest(ROOT) for rel in manifest: target=source/rel;target.parent.mkdir(parents=True,exist_ok=True);shutil.copy2(ROOT/rel,target) shutil.copytree(ROOT/'tools',source/'tools',ignore=shutil.ignore_patterns('__pycache__')) (source/'docs').mkdir();shutil.copy2(ROOT/'docs/external-addons.json',source/'docs/external-addons.json') # Explicit test-only map input: preserve the real production survey while # moving the historical smoke fixture's hillside marker to verified flat pads. site_file=source/'addons/core/Configs/ERR/Tests/LegacySites.conf' site_text=site_file.read_text() assert site_text.count('Position 7000 0 7500')==1 site_file.write_text(site_text.replace('Position 7000 0 7500','Position 4776.55 0 11528.9')) fixture=Path(__file__).with_name('native-fixture.c') shutil.copy2(fixture,source/'addons/core/Scripts/Game/ERR/00_Core/ERR_ZRescueFactionFixture.c') # The opt-in fixture is independent of the historical generic Core smoke. p=source/'addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c' p.write_text(p.read_text().replace('array independentFixtures = {','array independentFixtures = {"rescue-faction", ')) p=source/'tools/headless_workbench.py' p.write_text(p.read_text().replace("choices=['coordinated-ai',", "choices=['rescue-faction', 'coordinated-ai',").replace("a.smoke not in {'coordinated-ai',", "a.smoke not in {'rescue-faction', 'coordinated-ai',").replace("if a.convoy_cover: command +=", "command += ['-errRescueFixtureScope', "+repr(scope)+"]\nif a.convoy_cover: command +=")) (profile/'profile').mkdir() (profile/'profile/EscapistsFactions.json').write_text(json.dumps({'escapists':'us','enemy':'ussr','independent':'fia'})+'\n') (profile/'fixture-inputs.json').write_text(json.dumps({'scope':scope,'arranged_pickup_definition':[4776.55,0,11528.9],'fixture_sha256':hashlib.sha256(fixture.read_bytes()).hexdigest(),'production_sources':manifest,'source':str(source),'profile':str(profile)},indent=2)+'\n') installed=Path.home()/'.local/share/Steam/steamapps/compatdata/1874880/pfx/drive_c/users/steamuser/Documents/My Games/ArmaReforger/addons' command=[sys.executable,str(source/'tools/headless_workbench.py'),'--compat',str(compat),'--profile',str(profile),'--external-addons',str(installed),'--project','core','--smoke','rescue-faction','--rounds','1','--timeout','600'] with (profile/'runner-output.log').open('w') as output: result=subprocess.run(command,stdout=output,stderr=subprocess.STDOUT) print(json.dumps({'exit':result.returncode,'source':str(source),'profile':str(profile)})) print('\n'.join((profile/'runner-output.log').read_text().splitlines()[-45:])) raise SystemExit(result.returncode)