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

59 lines
2.6 KiB
Python

"""Project FFGO's labelled Bonfire reference tables without copying a run.
The target identity is a compatibility gate for the existing server catalog,
not a claim that these rows were captured from that Client assembly.
"""
import argparse
import hashlib
import json
from pathlib import Path
def main():
p = argparse.ArgumentParser(description=__doc__)
p.add_argument('--excel', type=Path, required=True)
p.add_argument('--custom', type=Path, required=True)
p.add_argument('--catalog', type=Path, required=True)
p.add_argument('--source-binary-sha256', required=True)
p.add_argument('--output', type=Path, required=True)
a = p.parse_args()
if len(bytes.fromhex(a.source_binary_sha256)) != 32:
raise ValueError('Expected SHA256 identity')
excel_raw, custom_raw = a.excel.read_bytes(), a.custom.read_bytes()
excel, custom = json.loads(excel_raw), json.loads(custom_raw)
catalog = json.loads(a.catalog.read_bytes())
def rows(name, fields):
result = []
for row in excel[name]:
copy = dict(row)
for field in fields:
if field in copy:
copy[field] = int(copy[field])
result.append(copy)
return result
configs = {k:v for k,v in custom['config_files'].items()
if v.get('Engine') == 'TeaBreakOption'}
result = {
'format_version': 1,
'target_client_version': catalog['client_version'],
'target_assembly_sha256': catalog['provenance']['game_assembly_sha256'],
'source_binary_sha256': a.source_binary_sha256,
'source_kind': 'reference-implementation',
'source': 'FFGO embedded GridFight Excel rows plus FFGO declarative TeaBreakOption recipes; not original Client scripts or a native Client capture.',
'compatibility_scope': 'Event IDs must also be present on the active Client node; no reference route or saved run is imported. Only explicitly supported effects execute.',
'source_excel_sha256': hashlib.sha256(excel_raw).hexdigest(),
'source_custom_sha256': hashlib.sha256(custom_raw).hexdigest(),
'tables': {
'events': rows('grid_fight_bonfire_event', ['ID','PetPalID','DialogID']),
'options': rows('grid_fight_bonfire_event_option', ['EventID','OptionID','DialogID']),
'heal': rows('grid_fight_bonfire_heal', ['ChapterID','HealNum']),
},
'configs': configs,
}
a.output.write_text(json.dumps(result, ensure_ascii=False, indent=2)+'\n', encoding='utf8')
print(json.dumps({k:len(v) for k,v in result['tables'].items()} | {'recipes':len(configs)}))
if __name__ == '__main__':
main()