TRX/tools/update_gameflow
2025-01-17 18:35:39 +01:00

98 lines
2.7 KiB
Python
Executable file

#!/usr/bin/env python3
import json
import re
from pathlib import Path
from shared.paths import PROJECT_PATHS, SHARED_INCLUDE_DIR
def get_objects_map(paths: list[Path]) -> dict[str, str]:
result: dict[str, str] = {}
for path in paths:
for line in path.read_text().splitlines():
if match := re.match(
r'^OBJ_NAME_DEFINE\((\w+),\s*"([^"]+)",\s*"([^"]+)"\)$',
line.strip(),
):
result[match.group(2)] = match.group(3)
return result
def get_strings_map(paths: list[Path]) -> dict[str, str]:
result: dict[str, str] = {}
for path in paths:
for line in path.read_text().splitlines():
if match := re.match(
r'^\w+DEFINE\((\w+),\s*"([^"]+)"\)$', line.strip()
):
result[match.group(1)] = match.group(2)
return result
def postprocess_game_strings(
content: str,
object_names_map: dict[str, str],
game_strings_map: dict[str, str],
) -> str:
max_key_length = (
max(len(json.dumps(key)) for key in object_names_map.keys()) + 2
)
indent = " " * 8
content = re.sub(
r'^( "objects": {)[\S\s]*?^( })',
' "objects": {\n'
+ "\n".join(
f"{indent}{f'{json.dumps(key)}: '.ljust(max_key_length)}{json.dumps({'name': value})},"
for key, value in object_names_map.items()
)
+ "\n }",
content,
flags=re.M | re.DOTALL,
)
content = re.sub(
r'^( "game_strings": {)[\S\s]*?^( })',
' "game_strings": {\n'
+ "\n".join(
f" {json.dumps(key)}: {json.dumps(value)},"
for key, value in sorted(
game_strings_map.items(), key=lambda kv: kv[0]
)
)
+ "\n }",
content,
flags=re.M | re.DOTALL,
)
return content
def process(game: int) -> None:
GAME_STRING_DEF_PATHS = [
PROJECT_PATHS[game].src_dir / "game/game_string.def",
SHARED_INCLUDE_DIR / "game/game_string.def",
]
OBJECT_NAMES_DEF_PATH = (
SHARED_INCLUDE_DIR / f"game/objects/names_tr{game}.def"
)
object_names_map = get_objects_map([OBJECT_NAMES_DEF_PATH])
game_strings_map = get_strings_map(GAME_STRING_DEF_PATHS)
assert object_names_map
assert game_strings_map
for path in PROJECT_PATHS[game].shipped_data_dir.rglob("*strings*.json*"):
old_content = path.read_text()
new_content = postprocess_game_strings(
old_content, object_names_map, game_strings_map
)
if new_content != old_content:
path.write_text(new_content)
def main() -> None:
process(1)
process(2)
if __name__ == "__main__":
main()