# Crusader Map Renderer Node web app that decodes Crusader maps into cached sprite atlases plus scene JSON, then renders the scene directly in the browser. ## Goals - Keep Crusader source assets server-side. - Detect maps from `STATIC` and `STATIC_REGRET` automatically. - Build map scene caches on demand after the user selects a map. - Serve cached atlas images and scene JSON so the browser reconstructs the view client-side. - Run locally with Node or inside Docker. ## Local Run ```powershell cd map_renderer npm install npm start ``` Open `http://localhost:3000`. Viewer behavior: - drag with the mouse or one finger to pan - use the scroll wheel to zoom directly at the pointer - pinch to zoom on touch devices - toggle roofs and editor-only elements independently without rebuilding; the client filters one full cached scene payload - inspect mode lets you pin a shape tooltip, hide a single instance, and restore hidden instances from the left panel - PNG export is generated in the browser from the cached scene instead of being rasterized server-side - hidden instances can be exported as JSON and each catalog CSV can be downloaded from the viewer - catalog CSV rows support `roof` and `semitransparency` boolean overrides; leave them blank to use decoded defaults, or set `true`/`false` per shape ## Cache Warming Build atlas and scene cache artifacts outside the request path: ```powershell cd map_renderer npm run build-cache ``` Optional focused warmup: ```powershell cd map_renderer npm run build-cache -- remorse 1 ``` The app expects asset folders under the app root: - `map_renderer/STATIC` - `map_renderer/STATIC_REGRET` ## Docker Run The `dev` image stays light and expects Crusader assets to be mounted at runtime. ```powershell cd map_renderer docker build --target dev -t crusader-map-renderer:dev . docker run --rm -p 3000:3000 ` -v ${PWD}/STATIC:/app/STATIC:ro ` -v ${PWD}/STATIC_REGRET:/app/STATIC_REGRET:ro ` crusader-map-renderer:dev ``` If only one game is available, mount only that folder. Production image with prebuilt cache artifacts and no raw `STATIC` assets in the final layer: ```powershell cd map_renderer docker build --target production -t crusader-map-renderer:prod . docker run --rm -p 3000:3000 crusader-map-renderer:prod ``` The production target copies `STATIC` and `STATIC_REGRET` only into the intermediate precache stage, runs `npm run build-cache`, then ships just `src`, `Catalogs`, `node_modules`, and `.cache` in the final image. ## Docker Compose The compose file targets the lightweight `dev` image and mounts `STATIC` and `STATIC_REGRET` from the host filesystem as read-only volumes. ```powershell cd map_renderer docker compose up --build ``` ## HTTP Surface - `GET /api/maps` returns the detected catalog. - `POST /api/builds` starts or reuses a build. - `GET /api/builds/:id` returns build status. - `GET /api/maps/:game/:mapId/metadata?buildId=...` returns map bounds and scene metadata. - `GET /api/maps/:game/:mapId/scene?buildId=...` returns the cached atlas-backed scene payload. - `GET /api/maps/:game/:mapId/atlases/:atlasId.png?buildId=...` returns a cached packed sprite atlas. - `GET /api/maps/:game/:mapId/inspect?buildId=...` returns the same per-instance shape metadata used for inspection. - `GET /api/catalogs/:game.csv` returns the source catalog CSV for that game. No raw Crusader asset files are exposed over HTTP.