tick and entity generation carry forward (which is why later sections show higher numbers).
The three paths, thinnest restore first:
- Scene (
/scene/save,/scene/load) — restores transform + physics body only. - Scenario (
POST/GET /scenario) — restores transform + health + team; reassigns ids. - Level (
/level/save,/level/load) — saves a rich file, but the save and load formats don’t match, so a saved level reloads zero entities.
Scene round-trip — what survives
Reset (a fresh server holds one component-less bootstrap entity), spawn a rich entity (position, health, team, role, gold, a dynamic physics body), step once so the transform propagates, and read it back.health is reported as [current, max]:
[5, 0.997, -2]), scale, and physics body round-tripped. Everything else is gone —
no health, team, gold, level, role, or velocity. The save file contains those fields, but
scene/load only reads transform.position, transform.scale, and physics_body back. The
generation bumped (here 1→2) because load wipes and re-spawns.
Scenario round-trip — richer, but still partial
A scenario is one document for a complete setup (templates, entities, rules, assertions, camera, game config).GET /scenario exports the current world; POST /scenario wipes and rebuilds from a document.
Reset, spawn a unit, step, and export it:
health and team survive (scene/load drops both), but
role and gold are still lost, and ids are reassigned:
position, scale, health, and team from each entity’s
components — that’s the full set it knows how to round-trip. role, gold, color, mesh, and the
combat/AI fields are read as null even when the components are present, so they’re dropped on
re-apply. Entities are inlined with no id, so applying assigns fresh ids.
Level save/load — a saved level reloads zero entities
POST /level/save writes a level file, and POST /level/load reads one. But they speak different
shapes, so a level you saved cannot be reloaded. Reset, spawn a unit, step, then save and reload it:
level/save writes the same rich per-entity record as /observe (with health as a [current, max]
array). But level/load parses each entity as a spawn request, where health is a single number. The
array shape fails to deserialize, and the loader silently falls back to an empty entity list — so
entities_created is 0, with no error.
The loader itself works fine; it’s the save format that’s incompatible. A hand-authored level (with
scalar health) loads correctly:
Behavior and gotchas
The things you only find out by running it:- Restore depth differs by path. Scene keeps transform + physics body; scenario keeps
transform + health + team; level save→load keeps nothing (format mismatch). No path keeps
role,gold,color,velocity, or ability/AI state. None is byte-exact. - Step after a load to see positions. Load writes the local transform; the world-space transform
/observereports propagates on the next tick. Read immediately after a load and a dynamic body still shows[0,0,0]until you/step. scene/loadandPOST /scenariowipe the world first;level/loadappends. Loading a scene or applying a scenario despawns everything, then rebuilds.level/loadadds to whatever is already there.- A saved level file does not reload (
entities_created:0, silently). Use a scenario for a save→reload round-trip, or hand-author level files in the spawn-request shape (scalarhealth). - Paths are sandboxed and relative. Absolute paths and
..are rejected; files resolve against the server’s working directory.
Endpoints
For exact, byte-comparable reproducibility, use the structured state and digest on
Datasets — scene/scenario/level files are for authoring and layout.
Status
- Shipped — scene save/load, scenario apply/export (including into forks), level save/load with format auto-detect and a procedural MOBA map. All headless.
- Partial — every save/load path is a subset round-trip. Scene keeps transform + physics body;
scenario keeps transform + health + team; a saved level file currently reloads zero entities (the
save format is the
/observerecord, which the loader doesn’t accept).
Scene & scenario endpoints
Scenario, level, and scene endpoints with request and response schemas.