veratown-prototype

Offline BC Map Analysis

Analyze a BC room-map export locally without logging in, connecting to MongoDB, loading .env, or changing the bot runtime.

Integrated administration interface

The admin-map workspace embeds the same analyzer natively (no iframe): upload or analyze the stored/unsaved layout, inspect clickable cells and findings, explore the first-person walkthrough and download labeled, exact-candidate and isometric SVGs. It also exports exact candidate manifests/import drafts and supports GUI include/exclude review, room confirmation and reopening reviewed drafts. The shared planMapImport validator checks source provenance and exact geometry; each included record is then handed to its normal reviewed, version-checked editor. There is no automatic or bulk database write and no live BC authority. The older manifest-mapping CLI remains available below; the GUI uses the richer import-draft contract rather than inventing a second region importer. Standalone/offline workflows remain supported.

Inside the admin workspace, Walkthrough and Map analysis are separate views, and candidate review/import controls are separate and collapsed by default. When the analyzed geometry matches the current managed map, the walkthrough receives a minimal projection of saved door coordinates, configured locked/unlocked styles, enabled state, triggers and inside-region geometry. Configured door preview modes are visual simulations only; they do not observe live door state, movement or access. Access-code values are never passed to the analyzer, and managed overlays are hidden for a different analyzed map. The standalone analyzer remains database-free and has no managed-door definitions.

The graphical candidate grid can merge exact regions, retaining gaps and disconnected cells, or replace only the region/inside-region geometry of an existing record. Door candidates can replace only an existing door’s position. Other settings remain intact; the normal version-checked review/save path is still mandatory. Candidate selection does not implicitly include/approve an import record.

Quick start

Save one exported LZ-string map per nonempty line in a UTF-8 text file:

npm run analyze:bc-map -- --input /path/to/map.txt

This prints the analysis and proposed output paths without writing files. Review the result, then write the report and images:

npm run analyze:bc-map -- \
  --input /path/to/map.txt \
  --output /path/to/new-analysis-directory \
  --apply

The output directory must not already exist. There is no overwrite mode. The default destination is dist/map-analysis, which is excluded from Git. Keep room exports and generated reports outside tracked source directories.

For a file containing multiple exports, explicitly select a 1-based nonempty line index:

npm run analyze:bc-map -- --input /path/to/maps.txt --index 2 --apply

The tool never guesses which version to analyze. --help prints the options. Input is limited to a regular UTF-8 file of at most 64 KiB; the selected export must decode to a 40 x 40 base tile/object map. Unknown catalog IDs fail explicitly rather than becoming empty tiles. Decompression stops at 262,144 characters instead of materializing an oversized result. Catalog data is pinned to the revision recorded in the output; changing this tool does not update the BC pin.

After a deliberate catalog repin, regenerate candidate manifests rather than editing their catalog revision: the region importer checks catalog provenance alongside the map fingerprint.

Outputs

File Contents
report.md Region inventory, door/gate/window coordinates, surface patches, furniture and review findings
analysis.json Versioned structured output, catalog revision, decoded cells, exact region/surface membership, bounds and adjacency
map.svg Labeled top-down map with region IDs, windows, doors and suspected sealed shells
isometric.svg Roofless isometric impression with raised walls, windows, doors and symbolic furnishings
region-candidates.json Exact canonical row-span candidates, per-candidate tile counts, bounds, components, catalog revision and map fingerprint
region-candidates.svg Exact tile overlay for candidate review; no bounding-box membership is implied

Both SVG images open directly in a browser. They contain no external assets, network requests or scripts. They are illustrations, not original BC asset renders. The isometric image leaves EmptySpace / Passable objects implicit rather than drawing furniture blocks; underlying floor tiles and walls remain visible. Real objects and impassable empty-space markers retain their symbolic geometry. Window panes and frames follow their wall line in labeled, isometric and walkthrough views. Orientation uses adjacent wall/half-wall tiles; ambiguous corners or isolated windows use catalog rotation, defaulting to horizontal.

Map tools in the admin dashboard

The former standalone map-web service is retired. The dashboard sidebar has a Map tools group, available to every authenticated user including viewers:

Each view analyzes the stored creation map in memory, or an uploaded export (limited to 64 KiB). Nothing is saved, logged or sent to BC. The dashboard CSP only allows its own assets and API.

For additional PNG images, install ImageMagick separately and make its magick command available on PATH, then add --png:

npm run analyze:bc-map -- \
  --input /path/to/map.txt \
  --output /path/to/another-new-directory \
  --apply --png

This additionally writes map.png and isometric.png. No npm dependency is installed by the tool. A missing renderer fails before writing outputs. A render failure after writing reports is reported as an error; inspect the partial output and choose a new directory for a retry.

Geometry and interpretation

The legacy Base64/LZ-string portion of a combined ...@... export is analyzed. The effects suffix and optional cell metadata are not interpreted; their presence does not change the geometric result. This tool is not a pathfinder, permission simulator or live-state observation. The analysis command itself never connects to MongoDB.

See the map and doors guide for the runtime configuration that remains separate from this analysis.

Operator-reviewed location and door import

To create a single editable dataset containing every analyzed region and door/gate fixture, generate a draft from the source export:

npm run create:map-import-draft -- \
  --input /path/to/map.txt \
  --output /path/to/map-import-draft.json \
  --apply

The command is offline and refuses to overwrite an existing file. The generated JSON includes the source catalog revision and map fingerprint, exact geometry for every region, and each door/gate tile with its adjacent region IDs. It defaults every row to decision: "pending" and every record to disabled. The suggested main room key, region names/keys, and door keys are editable proposals, not semantic conclusions.

Review the full file before import:

Preview the reviewed dataset against the same source map and target database:

npm run import:map-draft -- \
  --draft /path/to/reviewed-map-import-draft.json \
  --source-map /path/to/map.txt

The importer requires an exact catalog revision and map fingerprint match, validates every approved document against the runtime schemas, rejects duplicate keys and existing-key conflicts, and writes only new location and door definitions. Apply also inserts the two missing room-wide admin/whitelist access groups with the public default code knock, as runtime startup does; existing group edits and all memberships are preserved. The draft GUI does not edit access codes or memberships. See door access management. Dry-run is the default; database writes require --apply:

RUNTIME_TARGET=test npm run import:map-draft -- \
  --draft /path/to/reviewed-map-import-draft.json \
  --source-map /path/to/map.txt \
  --apply

The target is pinned to veratown_prototype_test or veratown_prototype by RUNTIME_TARGET; arbitrary database overrides are rejected. Test in the isolated test database first. Inserts are non-updating, but a connection failure during apply can leave earlier inserts in place; inspect the reported progress and current records before retrying. Use a reviewed backup and coordinate production rollout with all bot instances.

Standalone browser review GUI

Generate a self-contained review webpage:

npm run build:map-review -- --output /path/to/map-review.html --apply

Without --apply, this only previews the destination. Existing files are never overwritten. The default output is dist/map-review.html; choose a location outside dist/ to keep it across production builds.

Open the generated HTML file directly in a browser (file:// works). There is no server, build runtime, CDN, remote font, or external JavaScript requirement. The file embeds the current draft JSON schema and pinned BC object catalog. All file reading, map rendering, editing, validation and JSON generation happen in the browser. A restrictive content security policy blocks network connections. Nothing is uploaded or saved to browser storage.

  1. Open a draft JSON with the file picker. Use the exact-cell map or searchable, filterable candidate list to select a region or door/gate tile.
  2. Review names and stable keys. Dropdowns constrain decisions, enabled state, location types, region categories, adjacent inside regions and unambiguous catalog tile style/type pairs. Names and keys remain bounded text inputs; unlock duration is a nonnegative integer in milliseconds.
  3. Choose include or exclude individually for every candidate. Door inclusion also requires valid locked/unlocked tiles and a duration. Selecting a tile writes its style and type together. No code, keypad, membership, or entrance grouping is inferred. When older drafts have null door settings, the GUI supplies the same source defaults and 2500 ms duration; existing non-null operator settings are kept.
  4. Confirm the destination room key. Editing that key clears its confirmation. Read-only source fields, geometry, classifications and analysis notes are preserved. The page does not let an operator reshape, merge, or split candidates.
  5. Use Save work in progress at any time to download incomplete JSON. Reopen that file to resume. Unsaved edits are held only in the current tab; closing/reloading prompts when the browser allows it.
  6. Download import-ready JSON is enabled only after browser validation passes. It downloads the same reviewed draft format consumed by npm run import:map-draft, not a database dump.

For each door, use Map click mode to choose Toggle keypad tiles or Toggle auto-open tiles, then click any cell in the 40 x 40 grid. Each click adds or removes that coordinate without changing the selected door. This works on region cells, doors and dark gaps alike. Green outlines mark keypad tiles; purple outlines mark auto-open tiles. Coordinate buttons below the editor also remove individual selections. Switch back to Inspect candidates to select a different door. These are configuration trigger coordinates, not a guarantee that the cells are walkable or that players have access.

The Hidden door dropdown defaults to disabled for visible doors. Enabling it sets lockedTile: "Blank", lockedTileType: "WallDecoration", unlockedTile: "SteelDoorOpen", and unlockedTileType: "WallPath" and locks the tile dropdowns while hidden. Disabling it restores the previous visible tile settings in the current session (or source defaults after reopening). Hidden state is represented by those tile fields, not a new runtime flag. Both trigger arrays and hidden tile settings are saved in progress and reviewed downloads. None of these controls edits the live BC map.

Use the CLI dry-run with the original map export before applying. The GUI cannot independently verify that the supplied draft came from that map, inspect existing database keys, or certify live BC state. A catalog-revision mismatch blocks ready export; rebuild the reviewer from the matching pinned revision. Browser checks are an editing aid, not a replacement for the CLI’s authoritative source-map, geometry and database validations.

The static template and browser code are under tools/map-review/; the generator is scripts/build-map-review.ts. The normal test suite includes standalone generation checks and a browser download/import round-trip when Playwright Chromium is installed; otherwise the browser test reports an explicit skip.

Reviewed region import

The generated candidate manifest does not assign durable identities. Review region-candidates.svg and the exact region forms in the JSON, then add the intended room scope and stable target mapping. A mapping may combine multiple candidate IDs into one region, including disconnected components:

{
    "roomKey": "main",
    "mappings": [
        {
            "candidateIds": ["R06", "R08"],
            "targetType": "location",
            "targetKey": "park"
        }
    ]
}

Use a reviewed source export and preview before applying:

npm run import:map-regions -- \
  --manifest /path/to/reviewed-region-candidates.json \
  --source-map /path/to/map-export.txt

--index <1-based> selects from a multi-export source file. The importer recomputes candidates and requires an exact catalog-revision and map-content fingerprint match; that fingerprint verifies configuration provenance, not the current live BC room. It validates the target room, uniqueness, geometry and resulting map-document size, then reports exact tile counts, bounds summaries and disconnected-component counts. No writes occur unless --apply is specified:

npm run import:map-regions -- \
  --manifest /path/to/reviewed-region-candidates.json \
  --source-map /path/to/map-export.txt \
  --apply

The importer uses RUNTIME_TARGET to select only veratown_prototype or veratown_prototype_test; it never accepts an arbitrary database name. It updates only each explicitly mapped location region or door insideRegion and its normal updatedAt field. It does not infer permissions, keypad codes, door durations, enabled state, or which side of a door is inside. Back up and review target documents before production apply; mixed-version deployments must not receive tile-region documents.