Refactor map renderer and server API

- Updated index.html to enhance UI with new elements for hidden shapes and catalog CSVs.
- Changed download button to a button element for better accessibility.
- Modified server.js to improve API endpoints:
  - Renamed overlays endpoint to scene for clarity.
  - Updated tile rendering endpoints to use atlas instead of tile coordinates.
  - Added new endpoint for downloading shape catalog CSV files.
  - Removed unused options in build creation.
This commit is contained in:
Marco 2026-03-27 16:28:45 +01:00
commit f93cfc31c8
17 changed files with 2228 additions and 1199 deletions

View file

@ -1,13 +1,13 @@
# Crusader Map Renderer
Node web app that renders Crusader maps on the server and streams only finished PNG tiles to the browser.
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 render state on demand after the user selects a map.
- Serve large maps as draggable and zoomable image tiles.
- 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
@ -25,8 +25,27 @@ 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 before building
- when editor-only elements are enabled, the base map excludes those records and the original editor shapes render as interactive overlay sprites with hover metadata
- 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:
@ -35,22 +54,32 @@ The app expects asset folders under the app root:
## Docker Run
The Docker image excludes the Crusader assets on purpose. Mount them at runtime so they stay outside the image and are never served directly to clients.
The `dev` image stays light and expects Crusader assets to be mounted at runtime.
```powershell
cd map_renderer
docker build -t crusader-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
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 mounts `STATIC` and `STATIC_REGRET` from the host filesystem into the container as read-only volumes. They are excluded from the image build by `.dockerignore`, so the assets are never copied into the image.
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
@ -62,9 +91,10 @@ docker compose up --build
- `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 tile settings.
- `GET /api/maps/:game/:mapId/overlays?buildId=...` returns interactive overlay records for editor-only content.
- `GET /api/maps/:game/:mapId/overlays/:overlayId.webp?buildId=...` returns the rendered sprite for one overlay item.
- `GET /api/maps/:game/:mapId/tiles/:tileX/:tileY.png?buildId=...` returns rendered PNG tiles.
- `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.