"""Copy project-owned interchange sources and pin the portable JSON dependency.""" from pathlib import Path import hashlib, json, re, shutil, urllib.request, subprocess, tarfile ROOT = Path(__file__).resolve().parents[2] UNITY = Path('D:/vibeCoding/unityRouge') def write(path, text): path.parent.mkdir(parents=True, exist_ok=True) path.write_text(text, encoding='utf-8', newline='\n') def main(): originals = ROOT/'SourceAssets/ThirdParty/nlohmann/json/3.12.0' originals.mkdir(parents=True, exist_ok=True) if not all((originals/name).exists() for name in ('json.hpp','LICENSE.MIT')): archive=originals/'json.tar.xz' url='https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz' if not archive.exists(): subprocess.run(['curl.exe','--fail','--location','--retry','1','--connect-timeout','5','--max-time','45','--output',str(archive),url],check=True) assert hashlib.sha256(archive.read_bytes()).hexdigest()=='42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa' with tarfile.open(archive) as package: for name,tail in [('json.hpp','single_include/nlohmann/json.hpp'),('LICENSE.MIT','LICENSE.MIT')]: matches=[m for m in package.getmembers() if m.isfile() and (m.name.endswith('/'+tail) or m.name==tail)] member=min(matches,key=lambda m:len(m.name)) (originals/name).write_bytes(package.extractfile(member).read()) digest = hashlib.sha256((originals/'json.hpp').read_bytes()).hexdigest() assert digest == 'aaf127c04cb31c406e5b04a63f1ae89369fccde6d8fa7cdda1ed4f32dfc5de63' for name in ['json.hpp','LICENSE.MIT']: target=ROOT/'gameFramework/third_party/nlohmann'/name target.parent.mkdir(parents=True, exist_ok=True); shutil.copy2(originals/name,target) entries=[] for category, folder in [('equipment','Equipment'),('chassis','Mechs')]: for path in sorted((UNITY/'Assets/Game/Data'/folder).glob('*.asset')): data={} for line in path.read_text(encoding='utf-8-sig').splitlines(): m=re.match(r'^ (\w+): (.+)$',line) if not m: continue key,value=m.groups() if key in ('id','slot','mass','power','damage','magazineSize','reloadSeconds','fireRate','speedFactor','guided','speed','boostSpeed','boostDuration','lift','armor','massCapacity','powerCapacity'): try:value=float(value) if '.' in value else int(value) except ValueError:pass data[key]=value if 'id' in data: entries.append((category,data)) catalog={'equipment':[d for c,d in entries if c=='equipment'], 'chassis':[d for c,d in entries if c=='chassis']} assert len(catalog['equipment'])==9 and len(catalog['chassis'])==3 write(ROOT/'SourceAssets/Data/Definitions.json',json.dumps(catalog,ensure_ascii=False,indent=2)+'\n') write(ROOT/'gameFramework/src/DefaultCatalog.inc','R"GFDEFS('+json.dumps(catalog,ensure_ascii=False,separators=(',',':'))+')GFDEFS"\n') records=[] selections=[('SourceAssets/Blender','SourceAssets/Blender'),('Assets/Game/Art/Models','SourceAssets/Exports/Unity'),('Assets/Game/UI/Icons/Equipment','SourceAssets/UI/Icons/Equipment'),('Assets/Game/UI/Illustrations','SourceAssets/UI/Illustrations'),('Assets/Game/Localization/Tables','SourceAssets/Localization/Tables'),('SourceAssets/ThirdParty/Adobe/NotoSansSC','SourceAssets/ThirdParty/Adobe/NotoSansSC'),('Docs/Production/Licenses/Adobe/NotoSansSC','Docs/Production/Licenses/Adobe/NotoSansSC')] for source,target in selections: for path in (UNITY/source).rglob('*'): if not path.is_file() or path.suffix not in ('.blend','.fbx','.svg','.json','.ttf','.txt'): continue dest=ROOT/target/path.relative_to(UNITY/source) dest.parent.mkdir(parents=True,exist_ok=True);shutil.copy2(path,dest) records.append({'source':str(path.relative_to(UNITY)).replace('\\','/'),'destination':str(dest.relative_to(ROOT)).replace('\\','/'),'sha256':hashlib.sha256(dest.read_bytes()).hexdigest()}) records.append({'author':'Niels Lohmann','version':'3.12.0','license':'MIT','source':'https://github.com/nlohmann/json/releases/tag/v3.12.0','destination':str(originals.relative_to(ROOT)).replace('\\','/'),'sha256':digest}) write(ROOT/'Docs/Production/AssetSources.json',json.dumps({'date':'2026-11-13','unityBaseline':'463d898','sources':records},ensure_ascii=False,indent=2)+'\n') print(f'Prepared {len(records)} source records, 9 equipment definitions, 3 chassis; JSON dependency hash verified') if __name__=='__main__': main()