53 lines
1.8 KiB
Python
53 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from engine.map import Map
|
|
from engine.tile import TILE_LAYERS, Tile, TileLayerInstance
|
|
|
|
|
|
def _layer_instances(fields: dict) -> dict[str, TileLayerInstance | None]:
|
|
return {layer: (TileLayerInstance(def_id) if def_id else None) for layer, def_id in fields.items() if layer in TILE_LAYERS}
|
|
|
|
|
|
class MapLoader:
|
|
"""Builds Map graphs (including embedded sub-maps) from resources/defs/maps/*.json."""
|
|
|
|
def __init__(self, maps_dir: Path):
|
|
self.maps_dir = maps_dir
|
|
self._cache: dict[str, Map] = {}
|
|
|
|
def load(self, filename: str) -> Map:
|
|
data = json.loads((self.maps_dir / filename).read_text())
|
|
map_id = data["map_id"]
|
|
if map_id in self._cache:
|
|
return self._cache[map_id]
|
|
|
|
m = Map(map_id, data["width"], data["height"], data["depth"], source_def=filename)
|
|
self._cache[map_id] = m
|
|
|
|
default_tile = data.get("default_tile", {})
|
|
for z in range(m.depth):
|
|
for y in range(m.height):
|
|
for x in range(m.width):
|
|
m.set_tile(x, y, z, Tile(**_layer_instances(default_tile)))
|
|
|
|
for override in data.get("tiles", []):
|
|
x, y, z = override["x"], override["y"], override["z"]
|
|
fields = {k: v for k, v in override.items() if k not in ("x", "y", "z")}
|
|
tile = m.get_tile(x, y, z)
|
|
for layer, instance in _layer_instances(fields).items():
|
|
tile.set_layer(layer, instance)
|
|
|
|
for embedding in data.get("embeddings", []):
|
|
child = self.load(embedding["map_file"])
|
|
m.embed(
|
|
child,
|
|
tuple(embedding["anchor"]),
|
|
embedding.get("rotation", 0),
|
|
embedding.get("max_rotation_speed", 90.0),
|
|
)
|
|
|
|
return m
|