Gate radio intel behind configurable site discovery; record Workshop 0.0.119
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Frozen local Workbench radio intel 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_prefix_idle
|
||||
from external_addons import parse_project
|
||||
name=sys.argv[1]
|
||||
absent="--with-drones" not in sys.argv[2:]
|
||||
if not name.isalnum(): raise ValueError('Use an alphanumeric run suffix')
|
||||
source=Path('/tmp/erri-radio-intel-source-'+name)
|
||||
profile=Path('/tmp/erri-radio-intel-run-'+name)
|
||||
compat=ROOT/'.local/playtest-compat-20260920'
|
||||
assert_prefix_idle(compat)
|
||||
source.mkdir();profile.mkdir()
|
||||
for rel in addon_manifest(ROOT):
|
||||
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')
|
||||
fixture=Path(__file__).with_name('native-fixture.c')
|
||||
shutil.copy2(fixture,source/'addons/core/Scripts/Game/ERR/00_Core/ERR_ZRadioIntelFixture.c')
|
||||
# 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<string> independentFixtures = {','array<string> independentFixtures = {"radio-intel", '))
|
||||
p=source/'tools/headless_workbench.py'
|
||||
p.write_text(p.read_text().replace("choices=['coordinated-ai',", "choices=['radio-intel', 'coordinated-ai',").replace("a.smoke not in {'coordinated-ai',", "a.smoke not in {'radio-intel', 'coordinated-ai',"))
|
||||
# The optional drone addon is added only for the compatibility variant to this isolated source's
|
||||
# exact dependency policy only. Runtime files are hashed and checked by the
|
||||
# normal runner, and all original dependency checks remain enabled.
|
||||
installed=Path.home()/'.local/share/Steam/steamapps/compatdata/1874880/pfx/drive_c/users/steamuser/Documents/My Games/ArmaReforger/addons'
|
||||
optional={'65AD60E204191D37':('Realistic Combat Drones','RealisticCombatDrones_65AD60E204191D37')}
|
||||
if absent: optional={}
|
||||
policy_file=source/'docs/external-addons.json';policy=json.loads(policy_file.read_text());allowed={}
|
||||
for guid,(title,folder) in optional.items():
|
||||
project=installed/folder/'addon.gproj';actual,deps=parse_project(project.read_text());assert actual==guid
|
||||
allowed[guid]=deps
|
||||
policy['addons'][guid]={'title':title,'version':'2.3.7; installed 2026-10-21','dependencies':sorted(deps),'project_sha256':hashlib.sha256(project.read_bytes()).hexdigest()}
|
||||
policy['direct_ai_dependencies'].append(guid)
|
||||
policy_file.write_text(json.dumps(policy,indent=2)+'\n')
|
||||
p=source/'tools/external_addons.py'
|
||||
s=p.read_text();i=s.index('\ndef require(')
|
||||
s=s[:i]+'\nALLOWED.update('+repr(allowed)+')\nDIRECT += '+repr(tuple(optional))+'\n'+s[i:];p.write_text(s)
|
||||
if not absent:
|
||||
p=source/'addons/core/addon.gproj';s=p.read_text().replace(' Dependencies {',' Dependencies {\n "65AD60E204191D37"');p.write_text(s)
|
||||
# Add three real prepared non-radio sites: together with the legacy medical
|
||||
# stash and outpost they make the default five-site boundary reachable.
|
||||
p=source/'addons/core/Configs/ERR/Tests/LegacySites.conf'
|
||||
s=p.read_text(); pos=s.rfind(' }')
|
||||
extra=''
|
||||
for index in range(3):
|
||||
extra += '\n ERR_SiteDefinition { Id "fixture-site-%d" Label "Progression site %d" Kind 4 Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" Position %d 0 7400 Guarded 0 DiscoverRadius 25 }\n' % (index,index,6000+index*60)
|
||||
s=s[:pos]+extra+s[pos:];p.write_text(s)
|
||||
(profile/'profile').mkdir()
|
||||
(profile/'profile/EscapistsFactions.json').write_text(json.dumps({'escapists':'ussr','enemy':'us','independent':'fia'})+'\n')
|
||||
(profiles:=profile/'fixture-inputs.json').write_text(json.dumps({'fixture_sha256':hashlib.sha256(fixture.read_bytes()).hexdigest(),'production_sources':addon_manifest(ROOT),'source':str(source),'profile':str(profile)},indent=2)+'\n')
|
||||
command=[sys.executable,str(source/'tools/headless_workbench.py'),'--compat',str(compat),'--profile',str(profile),'--external-addons',str(installed),'--project','core','--smoke','radio-intel','--rounds','1','--timeout','180']
|
||||
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)
|
||||
Reference in New Issue
Block a user