- Added a "Reload Current Map" button to the left panel for refreshing the selected map after catalog edits. - Updated catalog CSV handling to support non-authoritative `categorization` and `qualities` columns. - Implemented automatic addition of newly observed shapes to the game catalog CSV during cache builds. - Modified catalog entry handling to ensure proper boolean overrides for `roof` and `semitransparency`. - Introduced `ensureShapeCatalogCoverage` function to maintain catalog integrity based on observed shapes. - Enhanced the serialization of catalog entries to include new fields and proper formatting. - Updated UI to reflect changes in reload state and button functionality.
3.9 KiB
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
STATICandSTATIC_REGRETautomatically. - 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
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
- the left panel includes a
Reload Current Mapbutton that forces a fresh rebuild/load of the currently selected map after catalog edits - catalog CSV rows support
roofandsemitransparencyboolean overrides; the catalog is authoritative for those properties, so blank meansfalseand only explicittrueturns them on - cache builds automatically add any newly observed shapes into the matching game catalog CSV without overwriting existing rows, then rewrite the file sorted by
shape_code - catalog CSV rows also support non-authoritative
categorizationandqualitiescolumns; cache builds auto-fill them when blank from the existing derived categorization and observed per-shape quality values
Cache Warming
Build atlas and scene cache artifacts outside the request path:
cd map_renderer
npm run build-cache
Optional focused warmup:
cd map_renderer
npm run build-cache -- remorse 1
The app expects asset folders under the app root:
map_renderer/STATICmap_renderer/STATIC_REGRET
Docker Run
The dev image stays light and expects Crusader assets to be mounted at runtime.
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:
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.
cd map_renderer
docker compose up --build
HTTP Surface
GET /api/mapsreturns the detected catalog.POST /api/buildsstarts or reuses a build.GET /api/builds/:idreturns 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.csvreturns the source catalog CSV for that game.
No raw Crusader asset files are exposed over HTTP.