tts_yaml_unpacker/tts_yaml_unpacker.py

108 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
import json
import yaml
import os
import sys
from pathvalidate import sanitize_filename
class IncludeTag:
yaml_tag = '!include'
def __init__(self, target):
self.target = target
@classmethod
def to_yaml(cls, dumper, node):
return dumper.represent_scalar(cls.yaml_tag, node.target)
@classmethod
def from_yaml(cls, loader, node):
base_dir = os.path.dirname(loader.stream.name)
target = os.path.join(base_dir, node.value)
with open(target) as f:
if target.endswith('.yaml'):
return yaml.load(f, Loader=yaml.Loader)
else:
return f.read()
yaml.add_constructor('!include', IncludeTag.from_yaml)
yaml.add_representer(IncludeTag, IncludeTag.to_yaml)
def uniqueName(obj):
if 'SaveName' in obj:
return obj['SaveName']
return f"{obj['Name']} {obj['Nickname']} {obj['GUID']}"
def shouldRecurse(obj, subobject_prop):
return subobject_prop in obj \
and obj.get('Name') not in ('Deck', 'DeckCustom') \
and len(obj[subobject_prop]) > 1
def recursivelyUnpackObject(parent_dir, obj,
subobject_prop='ContainedObjects', base_name=None):
def convertObjectsToIncludes(objects):
for subObj in objects:
filename = recursivelyUnpackObject(file_base_path, subObj)
yield IncludeTag(os.path.join(obj_base_name, filename))
obj_base_name = base_name or sanitize_filename(uniqueName(obj))
file_base_path = os.path.join(parent_dir, obj_base_name)
if shouldRecurse(obj, subobject_prop):
os.makedirs(file_base_path, exist_ok=True)
obj[subobject_prop] = list(
convertObjectsToIncludes(obj[subobject_prop]))
if 'LuaScript' in obj and len(obj['LuaScript']) > 0:
with open(file_base_path + '.ttslua', 'w') as f:
f.write(obj['LuaScript'])
obj['LuaScript'] = IncludeTag(obj_base_name + '.ttslua')
with open(file_base_path + '.yaml', 'w') as f:
yaml.dump(obj, f)
return obj_base_name + '.yaml'
def unpackJson(json_file, output_name):
with open(json_file) as f:
data = json.load(f)
recursivelyUnpackObject(
'', data, subobject_prop='ObjectStates', base_name=output_name)
def packYaml(yaml_file, output_json_file):
with open(yaml_file) as f:
data = yaml.load(f, Loader=yaml.Loader)
with open(output_json_file, 'w') as f:
json.dump(data, f, indent=2)
def usage():
print(f"Usage: {sys.argv[0]} <unpack|pack> <input> <output>")
def main():
if len(sys.argv) != 4:
usage()
elif sys.argv[1] == 'unpack':
unpackJson(sys.argv[2], sys.argv[3])
elif sys.argv[1] == 'pack':
packYaml(sys.argv[2], sys.argv[3])
else:
usage()
if __name__ == '__main__':
main()