68 lines
2.9 KiB
Python
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')
|