Files
AIGame/Tools/process_enemy_studio_batch.py

62 lines
3.8 KiB
Python

"""Four remaining enemy Studio trials; clouds run serially, Unity mutations stay serial."""
import argparse
import hashlib
import json
import subprocess
import sys
from pathlib import Path
ROOT=Path(__file__).resolve().parents[1]
WORKBENCH=Path('D:/UD/AI/XModel/LLM3DGraphics/.venv/Scripts/python.exe')
def main():
ap=argparse.ArgumentParser()
ap.add_argument('--stage',choices=('cloud','finish','play','verify'),required=True)
ap.add_argument('--actors',nargs='+')
ap.add_argument('--play-check',action='store_true')
a=ap.parse_args()
config=json.loads((ROOT/'Config/Art/StudioTrials/Enemies.json').read_text(encoding='utf-8'))
rows=[r for r in config['actors'] if not a.actors or r['actor'] in a.actors]
if a.actors and set(a.actors)-{r['actor'] for r in rows}:raise ValueError('Unknown enemy')
if a.stage=='play':
from enemy_character_pipeline import unity,script,wait_editor
if a.actors:raise ValueError('The combined Play check requires all four actors')
unity('set_autotick',enable=True)
if unity('editor_status')['playMode']!='stopped':raise RuntimeError('Preserve the current Play session; run this after it stops')
unity('editor_play')
try:
wait_editor('playing');script('VerifyEnemyStudioBatch','VerifyEnemyStudioBatch.PlayAll',[])
finally:unity('editor_stop');wait_editor('stopped')
for row in rows:
folder=ROOT/'Tools/output/studio_trial'/row['actor'];path=folder/'trial.json';receipt=json.loads(path.read_text(encoding='utf-8'))
if json.loads((folder/'unity_verification.json').read_text(encoding='utf-8'))['status']!='pass':raise ValueError('Edit QA missing')
for relative,digest in receipt['originals'].items():
if hashlib.sha256((ROOT/relative).read_bytes()).hexdigest()!=digest:raise ValueError(relative+' changed')
receipt['status']='validated';path.write_text(json.dumps(receipt,indent=2),encoding='utf-8')
return
for row in rows:
actor=row['actor']
if hashlib.sha256((ROOT/row['source']).read_bytes()).hexdigest()!=row['sourceSha256']:raise ValueError(actor+' source changed')
if a.stage=='cloud':
cmd=[str(WORKBENCH),'Tools/studio_lowpoly_trial.py','--actor',actor,'--kind','Enemy','--source',row['source'],'--rig',row['rig'],'--prefab',row['prefab'],'--tris',str(config['targetTriangles']),'--size',str(config['textureSize'])]
elif a.stage=='finish':
cmd=[sys.executable,'Tools/studio_lowpoly_finish.py','--actor',actor,'--height',str(row['height']),'--recipe',row['recipe']]
if a.play_check:cmd.append('--play-check')
else:
folder=ROOT/'Tools/output/studio_trial'/actor
receipt=json.loads((folder/'trial.json').read_text(encoding='utf-8'))
if receipt['status']!='validated':raise ValueError(actor+' has not passed actual Play')
for path,digest in receipt['originals'].items():
if hashlib.sha256((ROOT/path).read_bytes()).hexdigest()!=digest:raise ValueError(path+' changed')
for name in ('unity_verification.json','play_verification.json'):
if json.loads((folder/name).read_text(encoding='utf-8'))['status']!='pass':raise ValueError(actor+' failed '+name)
print('PASS '+actor+' validated; original protected hashes unchanged',flush=True)
continue
print('BEGIN '+actor+' '+a.stage,flush=True)
child=subprocess.Popen(cmd,cwd=ROOT,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True,encoding='utf-8',errors='replace')
for line in child.stdout:print(actor+': '+line.rstrip(),flush=True)
if child.wait():raise RuntimeError(actor+' '+a.stage+' failed; completed task records are retained for resume')
print('COMPLETE '+actor+' '+a.stage,flush=True)
if __name__=='__main__':main()