4.1 KiB
Manastorm stage asset bridge
import-existing-stage.mjs promotes a real converted dungeon asset package
into the Manastorm staging layout. It accepts either a previously green dungeon
pack or paired Blender-conversion and Recast reports; it does not synthesize or
substitute geometry.
Each import is an explicit
dungeon-pipeline/manastorm/imports/<stage-slug>.json manifest containing:
- either the green source validation report and package manifest, or the conversion and navigation reports for a newly converted package;
- reviewed visual, collision, and navigation GLB paths and checksums;
- original conversion evidence, such as the wow.export OBJ and Blender report;
- reviewed source anchor positions with
client,observed, orauthoredprovenance.
assets.visual and assets.collision accept either the original single
descriptor object or an array of descriptors. assets.navigation remains one
descriptor. Compound descriptors retain a stable id, decoded
triangleCount, source transform, and provenance object in
stage-source.json, optimized-manifest.json, the import report, and the
shipping stage pack. All collision chunks retain the 100,000-triangle
per-chunk limit.
The importer validates every chunk and every provenance file before it changes the active staging generation. It copies the complete set into a temporary generation, then swaps the staging directory and anchor review together with rollback. A bad checksum, missing chunk, incomplete Recast input list, or copy failure leaves the previous generation intact.
For a dungeon that already has green wow.export, Blender conversion, and Recast reports, scaffold that manifest and a five-anchor provisional review set with:
node scripts/manastorm-assets/scaffold-converted-import.mjs <stage-slug> <dungeon-slug>
The scaffold chooses start, middle, and end vertices from the largest connected navigation component, records placement-resolution statistics, and preserves collision-cap and visual-review warnings. The resulting gameplay semantics are provisional until encounter data and a playtest review confirm them.
For ADT-hybrid or other converted environments whose reviewed runtime fixture does not yet list the collision assets, bake navigation directly from every collision chunk recorded by the Blender conversion report:
npm run dungeon:navmesh:conversion -- <dungeon-slug>
This command hashes and loads the full collision set from
dungeon-pipeline/work/<dungeon-slug>/staging/environment/conversion-report.json,
writes the navigation GLB and Recast report, and records the exact ordered
input paths and checksums. The scaffold/import steps reject a Recast report
whose input set differs from the reviewed collision descriptors.
The equivalent Node API is:
import { bakeConversionNavigation } from "../dungeon-pipeline/recast-bake.mjs";
await bakeConversionNavigation("<dungeon-slug>");
The importer rejects checksum drift, unvalidated source packages, unreadable or
non-finite GLBs, collision chunks over 100,000 triangles, and anchors more than
2 meters from the actual navigation surface. Accepted anchors are projected
onto navigation triangles with three-mesh-bvh, retaining both their source
position and measured projection distance.
For any configured import:
npm run manastorm:maps:import -- <slug>
node scripts/manastorm-pipeline/cli.mjs optimize <slug>
node scripts/manastorm-pipeline/cli.mjs pack <slug>
npm run manastorm:maps:validate
npm run manastorm:maps:khronos
optimize and pack consume the staged asset manifests, so the same commands
work for single-root, multi-root, and ADT-hybrid packages. Packing is the step
that updates the shipping directory and generated registry; do not run it
while another worker owns registry serialization.
The collection validator remains blocked until every catalog map has a package.
The Khronos gate recursively validates every shipping GLB, fails on errors or
warnings, and rejects an empty target so a zero-file run cannot pass silently.
Inspect the requested map's entry in
dungeon-pipeline/manastorm/validation-report.json; a packaged map is green
when its blockers array is empty.