Files
GaCy-GO/tools/build_mission_config_audit.py
2026-10-28 18:54:43 +07:00

68 lines
2.9 KiB
Python

"""Prepare a bounded, inactive Client audit from the actual outgoing ID catalog."""
import argparse
import hashlib
import json
from pathlib import Path
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--catalog', type=Path, required=True)
parser.add_argument('--output', type=Path, required=True)
args = parser.parse_args()
raw = args.catalog.read_bytes()
ids = sorted(set(json.loads(raw)['subMissionIds']))
if not ids or any(not isinstance(i, int) or not 0 < i < 2**32 for i in ids):
raise SystemExit('Invalid outgoing mission catalog')
ranges = []
for i in ids:
if ranges and ranges[-1][1] + 1 == i:
ranges[-1][1] = i
else:
ranges.append([i, i])
source = '''-- Temporary: read-only lookup of outgoing sub-missions, at most four per frame.
do
if not _G.__gacMissionAudit1 then
local s={range=1,done=false,checked=0,valid=0,missing={},frame=-1}
_G.__gacMissionAudit1=s
local ranges=__RANGES__
local log=function(v)CS.UnityEngine.Debug.Log('[GAC_MISSION_AUDIT] '..tostring(v))end
log('BEGIN expected=__COUNT__ catalog_sha256=__HASH__')
s.tick=function()
if s.done then return end
local frame=CS.UnityEngine.Time.frameCount
if s.frame==frame then return end
s.frame=frame
local good,err=pcall(function()
local manager=CS.RPG.Client.GlobalVars.s_GamePhaseManager
local flags=CS.System.Enum.ToObject(typeof(CS.System.Reflection.BindingFlags),60)
local phase=manager and typeof(CS.RPG.Client.GamePhaseManager):GetField('_CurrentPhase',flags):GetValue(manager)
if phase and typeof(CS.RPG.Client.BattleGamePhase):IsInstanceOfType(phase)then return end
local m=CS.RPG.Client.GlobalVars.s_ModuleManager.MissionModule
local start=CS.UnityEngine.Time.realtimeSinceStartup
for n=1,4 do
local r=ranges[s.range]
if not r then
s.done=true
log('END checked='..s.checked..' valid='..s.valid..' missing='..table.concat(s.missing,','))
return
end
local id=s.next or r[1]
local cfg=m:GetSubMissionInfoConfig(id)
if cfg then s.valid=s.valid+1 else s.missing[#s.missing+1]=tostring(id)end
s.checked=s.checked+1
if id==r[2]then s.range=s.range+1;s.next=nil else s.next=id+1 end
if s.checked%1000==0 then log('PROGRESS checked='..s.checked..' valid='..s.valid)end
if CS.UnityEngine.Time.realtimeSinceStartup-start>0.002 then break end
end
end)
if not good then s.done=true;log('ERROR checked='..s.checked..' '..tostring(err))end
end
local ok,e=pcall(function()CS.UnityEngine.Application.onBeforeRender('+',s.tick)end)
if not ok then s.done=true;log('ERROR '..tostring(e))end
end
end
'''
source = source.replace('__RANGES__', '{' + ','.join('{%d,%d}' % tuple(r) for r in ranges) + '}')
source = source.replace('__COUNT__', str(len(ids))).replace('__HASH__', hashlib.sha256(raw).hexdigest())
args.output.write_text(source, encoding='utf-8')
print(f'Prepared {len(ids)} IDs in {len(ranges)} ranges; {len(source)} bytes')