92 lines
No EOL
3 KiB
Python
Executable file
92 lines
No EOL
3 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""SCICRAFT — story generator.
|
|
|
|
Reads STORY/*.md, merges every ```lang JSON block (in filename order) into
|
|
en_us.json, writes it to BOTH packs, and validates that every lang key
|
|
referenced from the KubeJS scripts and advancement JSONs resolves.
|
|
|
|
Usage:
|
|
python tools/gen_story.py
|
|
|
|
Edit the story by editing STORY/*.md, then run this script. Never hand-edit
|
|
en_us.json — it is a generated artifact.
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
STORY_DIR = ROOT / "STORY"
|
|
LANGS = [
|
|
ROOT / "server_pack" / "kubejs" / "assets" / "scicraft" / "lang" / "en_us.json",
|
|
ROOT / "client_pack" / "kubejs" / "assets" / "scicraft" / "lang" / "en_us.json",
|
|
]
|
|
KUBEJS_DIRS = [ROOT / "server_pack" / "kubejs"]
|
|
ADVANCEMENT_DIR = ROOT / "server_pack" / "kubejs" / "data" / "scicraft" / "advancements"
|
|
|
|
LANG_BLOCK = re.compile(r"```lang\s*\n(.*?)```", re.S)
|
|
|
|
|
|
def load_lang_files():
|
|
merged = {}
|
|
order = []
|
|
for path in sorted(STORY_DIR.glob("*.md")):
|
|
text = path.read_text(encoding="utf-8")
|
|
for i, match in enumerate(LANG_BLOCK.finditer(text)):
|
|
try:
|
|
data = json.loads(match.group(1))
|
|
except json.JSONDecodeError as e:
|
|
sys.exit(f"BAD JSON in {path.name} block #{i + 1}: {e}")
|
|
for key, value in data.items():
|
|
if key in merged:
|
|
print(f"WARN: duplicate key {key!r} ({path.name} overrides)")
|
|
merged[key] = value
|
|
order.append(key)
|
|
return merged, order
|
|
|
|
|
|
def write_lang(merged, order):
|
|
payload = {k: merged[k] for k in order}
|
|
for target in LANGS:
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text(
|
|
json.dumps(payload, ensure_ascii=False, indent="\t") + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
print(f"wrote {target.relative_to(ROOT)} ({len(payload)} keys)")
|
|
|
|
|
|
def validate(merged):
|
|
missing = set()
|
|
|
|
def check_key(key, source):
|
|
if key not in merged:
|
|
missing.add((key, source))
|
|
|
|
for root_dir in KUBEJS_DIRS:
|
|
for script in root_dir.rglob("*.js"):
|
|
for key in re.findall(r"Text\.translate\(\s*['\"]([^'\"]+)['\"]\s*(?:\+|\))", script.read_text(encoding="utf-8")):
|
|
# Keys followed by ` + msg` are dynamic templates — skip.
|
|
if key.endswith("."):
|
|
continue
|
|
check_key(key, str(script.relative_to(ROOT)))
|
|
|
|
if ADVANCEMENT_DIR.exists():
|
|
for jf in ADVANCEMENT_DIR.rglob("*.json"):
|
|
for key in re.findall(r'"translate"\s*:\s*"([^"]+)"', jf.read_text(encoding="utf-8")):
|
|
check_key(key, str(jf.relative_to(ROOT)))
|
|
|
|
if missing:
|
|
print("\nMISSING LANG KEYS:")
|
|
for key, source in sorted(missing):
|
|
print(f" {key} (used in {source})")
|
|
sys.exit(1)
|
|
print("all referenced lang keys resolve")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
merged, order = load_lang_files()
|
|
write_lang(merged, order)
|
|
validate(merged) |