Implements import_map.py script that converts YAML zone definitions to TOML format used by the engine. YAML format supports all zone features including terrain, portals, spawns, ambient messages, and boundaries.
171 lines
4.9 KiB
Python
Executable file
171 lines
4.9 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""Import YAML zone definitions and convert to TOML format.
|
|
|
|
Usage:
|
|
python scripts/import_map.py path/to/zone.yaml
|
|
python scripts/import_map.py path/to/zone.yaml --output content/zones/
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
|
|
def import_map(yaml_path: Path, output_dir: Path) -> Path:
|
|
"""Import a YAML zone definition and convert to TOML.
|
|
|
|
Args:
|
|
yaml_path: Path to YAML file
|
|
output_dir: Directory where TOML file should be written
|
|
|
|
Returns:
|
|
Path to created TOML file
|
|
|
|
Raises:
|
|
KeyError: If required fields are missing
|
|
"""
|
|
# Load YAML
|
|
with open(yaml_path) as f:
|
|
data = yaml.safe_load(f)
|
|
|
|
# Required fields
|
|
name = data["name"]
|
|
width = data["width"]
|
|
height = data["height"]
|
|
|
|
# Optional fields with defaults
|
|
description = data.get("description", "")
|
|
toroidal = data.get("toroidal", True)
|
|
safe = data.get("safe", False)
|
|
|
|
# Handle spawn coordinates
|
|
spawn = data.get("spawn", [0, 0])
|
|
spawn_x = spawn[0]
|
|
spawn_y = spawn[1]
|
|
|
|
# Build TOML lines
|
|
lines = []
|
|
|
|
# Basic fields
|
|
escaped_name = name.replace('"', '\\"')
|
|
lines.append(f'name = "{escaped_name}"')
|
|
if description:
|
|
escaped_description = description.replace('"', '\\"')
|
|
lines.append(f'description = "{escaped_description}"')
|
|
lines.append(f"width = {width}")
|
|
lines.append(f"height = {height}")
|
|
lines.append(f"toroidal = {str(toroidal).lower()}")
|
|
lines.append(f"spawn_x = {spawn_x}")
|
|
lines.append(f"spawn_y = {spawn_y}")
|
|
if safe:
|
|
lines.append("safe = true")
|
|
lines.append("")
|
|
|
|
# Terrain section
|
|
terrain_data = data.get("terrain", {})
|
|
rows = terrain_data.get("rows", [])
|
|
|
|
lines.append("[terrain]")
|
|
lines.append("rows = [")
|
|
for row in rows:
|
|
lines.append(f' "{row}",')
|
|
lines.append("]")
|
|
lines.append("")
|
|
|
|
# Impassable tiles
|
|
lines.append("[terrain.impassable]")
|
|
impassable = terrain_data.get("impassable", [])
|
|
if impassable:
|
|
tiles_str = ", ".join(f'"{tile}"' for tile in impassable)
|
|
lines.append(f"tiles = [{tiles_str}]")
|
|
else:
|
|
lines.append('tiles = ["^", "~"]') # default from zones.py
|
|
lines.append("")
|
|
|
|
# Ambient messages
|
|
ambient_data = data.get("ambient", {})
|
|
if ambient_data:
|
|
messages = ambient_data.get("messages", [])
|
|
interval = ambient_data.get("interval", 120)
|
|
|
|
lines.append("[ambient]")
|
|
lines.append(f"interval = {interval}")
|
|
lines.append("messages = [")
|
|
for msg in messages:
|
|
# Escape quotes in messages
|
|
escaped_msg = msg.replace('"', '\\"')
|
|
lines.append(f' "{escaped_msg}",')
|
|
lines.append("]")
|
|
lines.append("")
|
|
|
|
# Portals
|
|
portals = data.get("portals", [])
|
|
for portal in portals:
|
|
lines.append("[[portals]]")
|
|
lines.append(f"x = {portal['x']}")
|
|
lines.append(f"y = {portal['y']}")
|
|
escaped_target = portal["target"].replace('"', '\\"')
|
|
lines.append(f'target = "{escaped_target}"')
|
|
escaped_label = portal["label"].replace('"', '\\"')
|
|
lines.append(f'label = "{escaped_label}"')
|
|
if "aliases" in portal:
|
|
aliases_str = ", ".join(f'"{alias}"' for alias in portal["aliases"])
|
|
lines.append(f"aliases = [{aliases_str}]")
|
|
lines.append("")
|
|
|
|
# Spawn rules
|
|
spawns = data.get("spawns", [])
|
|
for spawn in spawns:
|
|
lines.append("[[spawns]]")
|
|
lines.append(f'mob = "{spawn["mob"]}"')
|
|
lines.append(f"max_count = {spawn.get('max_count', 1)}")
|
|
lines.append(f"respawn_seconds = {spawn.get('respawn_seconds', 300)}")
|
|
if "home_region" in spawn:
|
|
hr = spawn["home_region"]
|
|
lines.append(
|
|
f"home_region = {{ x = [{hr['x'][0]}, {hr['x'][1]}], "
|
|
f"y = [{hr['y'][0]}, {hr['y'][1]}] }}"
|
|
)
|
|
lines.append("")
|
|
|
|
# Write TOML file
|
|
toml_content = "\n".join(lines)
|
|
output_path = output_dir / f"{name}.toml"
|
|
output_path.write_text(toml_content)
|
|
|
|
return output_path
|
|
|
|
|
|
def main() -> None:
|
|
"""CLI entry point."""
|
|
parser = argparse.ArgumentParser(
|
|
description="Import YAML zone definition and convert to TOML"
|
|
)
|
|
parser.add_argument("yaml_file", type=Path, help="Path to YAML zone file")
|
|
parser.add_argument(
|
|
"--output",
|
|
type=Path,
|
|
default=Path("content/zones"),
|
|
help="Output directory (default: content/zones)",
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
yaml_path = args.yaml_file
|
|
output_dir = args.output
|
|
|
|
if not yaml_path.exists():
|
|
print(f"Error: {yaml_path} does not exist")
|
|
return
|
|
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
output_file = import_map(yaml_path, output_dir)
|
|
print(f"Imported {yaml_path} -> {output_file}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|