Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
53 lines
4.5 KiB
Python
53 lines
4.5 KiB
Python
from pathlib import Path
|
|
import sys,os,json,subprocess,time,shutil,signal,hashlib
|
|
ROOT=Path('/home/jakub/devel/escapistsrereintroduced');sys.path.insert(0,str(ROOT/'tools'))
|
|
from external_addons import policy,prepare_profile
|
|
runtime=Path('/tmp/erri-takeover-dedicated-runtime');source=Path('/tmp/erri-takeover-ds-source4');run=Path('/tmp/erri-takeover-ds4');run.mkdir()
|
|
shutil.copytree('/tmp/erri-takeover-feature-source4',source)
|
|
(source/'Scripts/Game/ERR/00_Core/ERR_TerrainValidationProbe.c').write_text('''modded class ArmaReforgerScripted
|
|
{
|
|
protected override void OnWorldPostProcess(World world)
|
|
{
|
|
SCR_MissionHeader header = SCR_MissionHeader.Cast(GetMissionHeader());
|
|
if (header) PrintFormat("ERR TERRAIN DEDICATED PROBE: dedicated=%1 enabled=%2 airports=%3 saves=%4", RplSession.Mode() == RplMode.Dedicated, header.m_bERR_EnableEscape, header.m_sERR_Airfields, header.m_eSaveTypes);
|
|
super.OnWorldPostProcess(world);
|
|
}
|
|
}
|
|
''')
|
|
steam=Path.home()/'.local/share/Steam';game=steam/'steamapps/common/Arma Reforger';addons=run/'addons';addons.mkdir()
|
|
prepare_profile(addons,steam/'steamapps/compatdata/1874880/pfx/drive_c/users/steamuser/Documents/My Games/ArmaReforger/addons',policy(ROOT),run/'external-cache.json')
|
|
(addons/'ERR_Core').symlink_to('/tmp/source',target_is_directory=True)
|
|
installed_root=steam/'steamapps/compatdata/1874880/pfx/drive_c/users/steamuser/Documents/My Games/ArmaReforger/addons'
|
|
(addons/'Nogova').symlink_to(installed_root/'NogovaReforger_70C981A53E02B64F',target_is_directory=True)
|
|
for name in ('meta','ServerData.json'):shutil.copy2(installed_root/'EscapistsReintroduced_2528466DE220D91C'/name,source/name)
|
|
if not (runtime/'addons').exists():(runtime/'addons').symlink_to(game/'addons',target_is_directory=True)
|
|
for name in ('profile','home','tmp'):(run/name).mkdir()
|
|
config={'bindAddress':'127.0.0.1','bindPort':22991,'game':{'name':'Private terrain takeover test','password':'private-local-probe','scenarioId':'{469880DFE1B48F95}Missions/Nogova_TerrainTest.conf','mods':[{'modId':'2528466DE220D91C','name':'Co10 Escape Reintroduced'},{'modId':'70C981A53E02B64F','name':'Nogova Reforger'}],'maxPlayers':8,'visible':False,'supportedPlatforms':['PLATFORM_PC'],'gameProperties':{'battlEye':False,'missionHeader':{'m_bERR_EnableEscape':True,'m_sERR_Airfields':'1525 5075','m_eSaveTypes':0}}}}
|
|
(run/'server.json').write_text(json.dumps(config,indent=2))
|
|
exe=['/tmp/runtime/ArmaReforgerServer','-config','/tmp/work/server.json','-profile','/tmp/work','-addonsDir','/tmp/work/addons','-noBackend','-bindIP','127.0.0.1','-bindPort','22991','-maxFPS','30','-logconsole','-noSound','-noSplash','-noThrow','-disableCrashReporter']
|
|
from dedicated_native import PROBE
|
|
(run/'network_probe.py').write_text(PROBE)
|
|
cmd=['bwrap','--unshare-net','--unshare-pid','--unshare-ipc','--unshare-uts','--die-with-parent','--cap-drop','ALL','--clearenv','--ro-bind','/','/','--tmpfs','/tmp','--proc','/proc','--dev','/dev','--ro-bind',str(runtime),'/tmp/runtime','--bind',str(source),'/tmp/source','--bind',str(run),'/tmp/work','--setenv','HOME','/tmp/work/home','--setenv','TMPDIR','/tmp/work/tmp','--setenv','PATH','/usr/bin:/bin','--setenv','LANG','C.UTF-8','--chdir','/tmp/runtime','/usr/bin/python3','/tmp/work/network_probe.py',os.readlink('/proc/self/ns/net'),*exe]
|
|
(run/'command.json').write_text(json.dumps(cmd,indent=2))
|
|
(run/'source-before.json').write_text(json.dumps({str(p.relative_to(source)):hashlib.sha256(p.read_bytes()).hexdigest() for p in source.rglob('*') if p.is_file() and p.name!='resourceDatabase.rdb'},indent=2))
|
|
child=None;started=time.time();reason='deadline'
|
|
with (run/'stdout.log').open('w') as log:
|
|
try:
|
|
child=subprocess.Popen(cmd,stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
|
|
while time.time()-started<180:
|
|
if child.poll() is not None:reason='process-exit';break
|
|
logs=sorted((run/'logs').glob('logs_*/console.log'))
|
|
if logs:
|
|
s=logs[-1].read_text(errors='replace')
|
|
if 'Reintroduced [mission]: phase 0 -> 1' in s:reason='mission-started';break
|
|
if 'terrain takeover failed' in s or "Can't compile" in s or 'Unable to initialize the game' in s:reason='startup-failed';break
|
|
time.sleep(1)
|
|
finally:
|
|
if child and child.poll() is None:
|
|
os.killpg(child.pid,signal.SIGTERM)
|
|
try:child.wait(timeout=10)
|
|
except subprocess.TimeoutExpired:os.killpg(child.pid,signal.SIGKILL);child.wait(timeout=5)
|
|
result={'reason':reason,'exit_code':child.returncode if child else None,'supervisor_reaped':child is not None and child.poll() is not None,'seconds':round(time.time()-started,2)}
|
|
(run/'result.json').write_text(json.dumps(result,indent=2));print(result)
|
|
print(run)
|