Files
EscapistsReintroduced/tools/import_settings.py
T

60 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Import supported legacy settings without modifying either source or an existing destination."""
import argparse,json,os,tempfile,sys
from pathlib import Path
SCHEMA={
'reportIntervalSeconds':(10,5,60),
'supportSquadLimit':(4,0,8),
'responseRadiusMetres':(2000,500,5000),
'aiIntelChancePercent':(60,0,100),
'intelRevealChancePercent':(15,0,100),
'radioDefenceSeconds':(180,30,1800),
'startTimeMinutes':(840,0,1439),
'timeMultiplier':(1,1,24),
'startDateCode':(0,0,1501231),
'weatherProfile':(0,0,3),
}
AI_KEYS=('reportIntervalSeconds','supportSquadLimit','responseRadiusMetres')
INTEL_KEYS=('aiIntelChancePercent','intelRevealChancePercent')
def merge(ai=None,intel=None):
result={key:spec[0] for key,spec in SCHEMA.items()};deferred=[]
for label,data,keys in [('ai',ai,AI_KEYS),('intel',intel,INTEL_KEYS)]:
if data is None:continue
if not isinstance(data,dict):raise ValueError(label+' settings must be a JSON object')
if 'configVersion' in data and (type(data['configVersion']) not in (int,float) or data['configVersion']!=1):
raise ValueError(label+' configVersion must be 1')
for key in keys:
if key not in data:continue
value=data[key];_,lo,hi=SCHEMA[key]
if type(value) not in (int,float) or not lo<=value<=hi or int(value)!=value:
raise ValueError(f'{key} must be an integer in [{lo},{hi}]')
result[key]=int(value)
deferred.extend(label+':'+key for key in data if key not in keys and key!='configVersion')
return result,deferred
def write_new(path,text):
path=Path(path)
with tempfile.NamedTemporaryFile(mode='w',dir=path.parent,prefix='.rereintroduced-',delete=False) as f:
tmp=Path(f.name)
try:
f.write(text);f.flush();os.fsync(f.fileno())
# Atomic installation that cannot overwrite an existing file, even in a race.
os.link(tmp,path)
finally:tmp.unlink(missing_ok=True)
def main():
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('--ai',type=Path,help='Read-only escapists-ai.json source')
p.add_argument('--intel',type=Path,help='Read-only escapists-intel.json source')
p.add_argument('--out',type=Path,help='New rereintroduced.json; omit to preview on stdout')
a=p.parse_args()
if not a.ai and not a.intel:p.error('Supply --ai and/or --intel')
try:
result,deferred=merge(json.loads(a.ai.read_text()) if a.ai else None,json.loads(a.intel.read_text()) if a.intel else None)
text=json.dumps(result,indent=2,allow_nan=False)+'\n'
if a.out:write_new(a.out,text)
else:print(text,end='')
if deferred:print('Settings awaiting controller migration (source files retained): '+', '.join(deferred),file=sys.stderr)
except (ValueError,OSError) as e:p.error(str(e))
if __name__=='__main__':main()