#!/usr/bin/env python3 """Stage the exact AVA2 biology items/icons for the current 156-byte proto format. No whole AVA2 locale/protocol is imported. Outputs are a reproducible, small client patch pack. """ import argparse,json,shutil,subprocess from pathlib import Path HERE=Path(__file__).resolve().parent NAMES={70028:'研究奖励重选券',300004:'榉木树枝',300005:'图吉木板',300006:'红鬼树枝',300007:'首领笔记',300008:'嫉妒宝石',300009:'智慧宝石',300010:'凤凰羽毛',300011:'红色单片镜',300012:'古老配方',30229:'智慧灵魂石',30230:'凤凰灵魂石',30231:'红镜灵魂石',30232:'古方灵魂石',30250:'研究冷却药剂',71035:'研究员精华'} def prepare(proto,ava,locale,output,tool,packer): catalog=json.loads((HERE/'catalog.json').read_text());wanted={v for r in catalog for v in (r['material'],r['stone'],r['enhancer'],r['skip']) if v}|{70028} rows={} for line in proto.read_bytes().splitlines(): cols=line.split(b'\t') if cols[0].isdigit() and int(cols[0]) in wanted: rows[int(cols[0])]=cols assert rows.keys()==wanted output.mkdir(parents=True,exist_ok=True) server=[];numeric=[] listrows={} for line in (ava/'locale/locale/es/item_list.txt').read_bytes().splitlines(): c=line.split(); if c and c[0].isdigit() and int(c[0]) in wanted:listrows[int(c[0])]=c assert listrows.keys()==wanted assets=output/'assets';(assets/'icon/item').mkdir(parents=True,exist_ok=True) # Chinese names for existing IDs come from the already reviewed current locale. names={} for filename in ('item_names_zh.txt','item_names_zh_overlay.txt'): path=HERE.parents[2]/'data/zh_40250'/filename for line in path.read_text().splitlines(): c=line.split('\t',1) if len(c)==2 and c[0].isdigit():names[int(c[0])]=c[1] for v,c in sorted(rows.items()): original_name=c[1].decode('cp949','replace') name=NAMES.get(v,names.get(v,original_name)) c[1]=name.encode('gbk');server.append(b'\t'.join(c)) types={b'ITEM_NONE':0,b'ITEM_MATERIAL':5,b'ITEM_QUEST':18} flags={b'NONE':0,b'ITEM_STACKABLE':4,b'LOG':8192} antis={b'NONE':0,b'ANTI_DROP':128,b'ANTI_SELL':256,b'ANTI_GIVE':8192,b'ANTI_MYSHOP':65536} parse=lambda s,m:sum(m[x.strip()] for x in s.split(b'|')) assert all(c[i] in (b'0',b'',b'LIMIT_NONE',b'APPLY_NONE',b'NONE') for i in (12,14,15,16,17,18,19,20,21,22,23)) numeric.append('%d\t%d\t0\t%d\t%d\t%d\t%d\t%d\t%s\t%s' % (v,types[c[2]],int(c[4]),parse(c[5],antis),parse(c[6],flags),int(c[9]),int(c[10]),'\t'.join(str(int(c[i] or b'0')) for i in range(24,30)),name)) icon=listrows[v][2].decode('ascii');shutil.copy2(ava/'icon'/icon,assets/icon) (output/'items-server.tsv').write_bytes(b'\n'.join(server)+b'\n') (output/'items-client.tsv').write_bytes(('\n'.join(numeric)+'\n').encode('gbk')) target=assets/'locale/zh';target.mkdir(parents=True,exist_ok=True) subprocess.run([str(tool),str(locale/'item_proto'),str(output/'items-client.tsv'),str(target/'item_proto')],check=True) # Replace only the matching item_list/description rows; all other current entries stay byte-identical. for filename in ('item_list.txt','itemdesc.txt'): lines=(locale/filename).read_bytes().splitlines();result=[] for line in lines: key=line.split(b'\t',1)[0] if not key.isdigit() or int(key) not in wanted:result.append(line) for v in sorted(wanted): if filename=='item_list.txt':result.append(b'\t'.join(listrows[v])) else: name=NAMES.get(v,names.get(v,'研究材料')).encode('gbk') description=('重新选择一次已经领取的生物学家奖励。' if v==70028 else '提高本次研究成功率 50 个百分点。' if v==71035 else '跳过本次提交的等待时间;仅在冷却期间消耗。' if v==30250 else '用于生物学家研究。').encode('gbk') result.append(str(v).encode()+b'\t'+name+b'\t'+description) (target/filename).write_bytes(b'\n'.join(result)+b'\n') subprocess.run([str(packer),str(output/'biolog'),str(assets), ''],check=True) (output/'items.json').write_text(json.dumps({v:NAMES.get(v,names.get(v,'研究材料')) for v in sorted(wanted)},ensure_ascii=False,indent=2)+'\n') if __name__=='__main__': p=argparse.ArgumentParser();p.add_argument('proto',type=Path);p.add_argument('ava',type=Path);p.add_argument('locale',type=Path);p.add_argument('output',type=Path);p.add_argument('tool',type=Path);p.add_argument('packer',type=Path) a=p.parse_args();prepare(a.proto,a.ava,a.locale,a.output,a.tool.resolve(),a.packer.resolve())