Analyze a BC room-map export locally without logging in, connecting to MongoDB,
loading .env, or changing the bot runtime.
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.
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.
| 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.
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.
(0, 0) at the top-left. X grows rightward,
Y downward. Bounding boxes are inclusive.Blank wall paths are not entrances; metal wall paths are gates.Rxx identifies an interior component; Ex an exterior component. IDs are
deterministic for a given layout but are not durable room identities between
map revisions.cells arrays, not bounding rectangles, for irregular areas.
Surface patches have separate exact cell lists and include tiles covered by
windows or other boundaries.CellData destinations and shared-tile behavior are not interpreted or added
as graph links.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.
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:
roomKeyReviewed to true only after confirming the destination room.decision to include or exclude. A pending
row blocks the entire import, so omitted candidates require an explicit
exclusion.regionType, and enabled state as needed.lockedTile matches the source fixture
style with WallPath type, unlockedTile uses the corresponding catalog
open variant, and unlockDurationMs defaults to 2500. Already-open
source doors keep that style as their locked default; review deliberately.
Metal gates use passable WallPath/Metal because MetalOpen is render-only
and cannot be stored as a catalog object. Unknown counterparts remain
unresolved rather than guessed.insideRegionId only to one of its listed adjacent
regions, or leave it null when no occupancy region is intended.keypadTiles and autoOpenTiles are optional arrays of { "X": 0, "Y": 0 }
coordinates (integers 0-39); new drafts initialize both to empty arrays.
Included door records preserve both arrays during import. Older drafts
without these fields remain accepted.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.
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.
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.
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.