@jgengine/editor 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +12 -0
- package/dist/AssetBrowser.d.ts +26 -1
- package/dist/AssetBrowser.js +54 -1
- package/dist/AssetDropZone.d.ts +9 -0
- package/dist/AssetDropZone.js +65 -0
- package/dist/CatalogsPanel.d.ts +4 -2
- package/dist/CatalogsPanel.js +162 -9
- package/dist/CityPreview.d.ts +11 -0
- package/dist/CityPreview.js +45 -0
- package/dist/CollectionsPanel.js +5 -5
- package/dist/DebugDraw.d.ts +3 -1
- package/dist/DebugDraw.js +37 -19
- package/dist/EditorApp.d.ts +9 -1
- package/dist/EditorApp.js +147 -35
- package/dist/EditorChrome.d.ts +25 -6
- package/dist/EditorChrome.js +310 -130
- package/dist/InspectorPanel.d.ts +17 -7
- package/dist/InspectorPanel.js +173 -27
- package/dist/LightingPanel.d.ts +11 -0
- package/dist/LightingPanel.js +99 -0
- package/dist/MaterialsWorkspacePanel.d.ts +12 -0
- package/dist/MaterialsWorkspacePanel.js +86 -0
- package/dist/ParentPickerMenu.d.ts +13 -0
- package/dist/ParentPickerMenu.js +33 -0
- package/dist/PerfProbe.js +33 -0
- package/dist/PrefabsPanel.js +5 -5
- package/dist/RuntimePlayBridge.d.ts +5 -3
- package/dist/RuntimePlayBridge.js +6 -13
- package/dist/ScatterPreview.d.ts +3 -1
- package/dist/ScatterPreview.js +10 -7
- package/dist/SchemaInspector.js +21 -8
- package/dist/ScriptingPanel.d.ts +15 -0
- package/dist/ScriptingPanel.js +46 -0
- package/dist/SelectionGizmo.js +114 -30
- package/dist/StandaloneEditor.d.ts +16 -9
- package/dist/StandaloneEditor.js +19 -20
- package/dist/TerrainPanel.d.ts +3 -2
- package/dist/TerrainPanel.js +16 -5
- package/dist/TerrainSculpt.js +98 -59
- package/dist/agent/AgentPanel.d.ts +5 -2
- package/dist/agent/AgentPanel.js +11 -6
- package/dist/agent/toolBridge.js +5 -0
- package/dist/assetImport.d.ts +36 -0
- package/dist/assetImport.js +66 -0
- package/dist/authoredComponentMeta.d.ts +25 -0
- package/dist/authoredComponentMeta.js +65 -0
- package/dist/gizmoPivot.d.ts +4 -0
- package/dist/gizmoPivot.js +34 -0
- package/dist/handlers/catalogs.d.ts +3 -0
- package/dist/handlers/catalogs.js +137 -0
- package/dist/handlers/collections.d.ts +3 -0
- package/dist/handlers/collections.js +57 -0
- package/dist/handlers/context.d.ts +36 -0
- package/dist/handlers/context.js +1 -0
- package/dist/handlers/document.d.ts +3 -0
- package/dist/handlers/document.js +350 -0
- package/dist/handlers/grids.d.ts +3 -0
- package/dist/handlers/grids.js +142 -0
- package/dist/handlers/hierarchy.d.ts +3 -0
- package/dist/handlers/hierarchy.js +55 -0
- package/dist/handlers/index.d.ts +8 -0
- package/dist/handlers/index.js +23 -0
- package/dist/handlers/minimap.d.ts +9 -0
- package/dist/handlers/minimap.js +32 -0
- package/dist/handlers/runtime.d.ts +3 -0
- package/dist/handlers/runtime.js +191 -0
- package/dist/handlers/terrain.d.ts +3 -0
- package/dist/handlers/terrain.js +204 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/listDocumentTriggers.d.ts +42 -0
- package/dist/listDocumentTriggers.js +49 -0
- package/dist/materialAssignments.d.ts +63 -0
- package/dist/materialAssignments.js +84 -0
- package/dist/mcp/fieldSpec.d.ts +32 -0
- package/dist/mcp/fieldSpec.js +173 -0
- package/dist/mcp/rpcRequest.d.ts +8 -5
- package/dist/mcp/rpcRequest.js +72 -93
- package/dist/mcp/tools.js +104 -912
- package/dist/networkSnapshot.d.ts +82 -0
- package/dist/networkSnapshot.js +73 -0
- package/dist/parentCandidates.d.ts +12 -0
- package/dist/parentCandidates.js +25 -0
- package/dist/session.d.ts +77 -4
- package/dist/session.js +36 -1017
- package/dist/shell/AnimationPanel.d.ts +17 -0
- package/dist/shell/AnimationPanel.js +134 -0
- package/dist/shell/AssetThumbnail.d.ts +12 -0
- package/dist/shell/AssetThumbnail.js +23 -0
- package/dist/shell/BottomDock.d.ts +25 -0
- package/dist/shell/BottomDock.js +40 -0
- package/dist/shell/CommandPalette.d.ts +12 -0
- package/dist/shell/CommandPalette.js +56 -0
- package/dist/shell/ConsolePanel.d.ts +8 -0
- package/dist/shell/ConsolePanel.js +45 -0
- package/dist/shell/ContentBrowser.d.ts +21 -0
- package/dist/shell/ContentBrowser.js +130 -0
- package/dist/shell/HierarchyPanel.d.ts +26 -0
- package/dist/shell/HierarchyPanel.js +387 -0
- package/dist/shell/NetworkWorkspacePanel.d.ts +11 -0
- package/dist/shell/NetworkWorkspacePanel.js +49 -0
- package/dist/shell/PlayModeBar.d.ts +12 -0
- package/dist/shell/PlayModeBar.js +27 -0
- package/dist/shell/ProfilerPanel.d.ts +10 -0
- package/dist/shell/ProfilerPanel.js +41 -0
- package/dist/shell/SceneToolbar.d.ts +43 -0
- package/dist/shell/SceneToolbar.js +122 -0
- package/dist/shell/StatusBar.d.ts +18 -0
- package/dist/shell/StatusBar.js +41 -0
- package/dist/shell/TopAppBar.d.ts +33 -0
- package/dist/shell/TopAppBar.js +64 -0
- package/dist/shell/ViewportOverlays.d.ts +23 -0
- package/dist/shell/ViewportOverlays.js +136 -0
- package/dist/shell/WorkspaceRail.d.ts +20 -0
- package/dist/shell/WorkspaceRail.js +31 -0
- package/dist/shell/cameraTelemetry.d.ts +27 -0
- package/dist/shell/cameraTelemetry.js +24 -0
- package/dist/shell/commandRegistry.d.ts +58 -0
- package/dist/shell/commandRegistry.js +133 -0
- package/dist/shell/consoleSink.d.ts +11 -0
- package/dist/shell/consoleSink.js +17 -0
- package/dist/shell/consoleStore.d.ts +27 -0
- package/dist/shell/consoleStore.js +43 -0
- package/dist/shell/fields.d.ts +39 -0
- package/dist/shell/fields.js +104 -0
- package/dist/shell/formatSavedRelative.d.ts +2 -0
- package/dist/shell/formatSavedRelative.js +14 -0
- package/dist/shell/glbThumbnailCache.d.ts +45 -0
- package/dist/shell/glbThumbnailCache.js +241 -0
- package/dist/shell/hierarchyA11y.d.ts +21 -0
- package/dist/shell/hierarchyA11y.js +35 -0
- package/dist/shell/icons.d.ts +13 -0
- package/dist/shell/icons.js +85 -0
- package/dist/shell/layoutStore.d.ts +68 -0
- package/dist/shell/layoutStore.js +156 -0
- package/dist/shell/pathFlythrough.d.ts +37 -0
- package/dist/shell/pathFlythrough.js +54 -0
- package/dist/shell/perfHistory.d.ts +70 -0
- package/dist/shell/perfHistory.js +130 -0
- package/dist/shell/renameObject.d.ts +3 -0
- package/dist/shell/renameObject.js +25 -0
- package/dist/shell/theme.d.ts +36 -0
- package/dist/shell/theme.js +37 -0
- package/dist/shell/ui.d.ts +84 -0
- package/dist/shell/ui.js +90 -0
- package/dist/shell/useGlbThumbnail.d.ts +8 -0
- package/dist/shell/useGlbThumbnail.js +19 -0
- package/dist/uiStore.d.ts +27 -0
- package/dist/uiStore.js +10 -0
- package/dist/viewportContextMenu.d.ts +4 -2
- package/dist/viewportContextMenu.js +5 -1
- package/package.json +4 -4
- package/skills/jgengine/SKILL.md +7 -4
- package/skills/jgengine/api.md +172 -79
- package/skills/jgengine/capabilities.md +104 -2
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-editor/SKILL.md +18 -3
- package/skills/jgengine-editor/api.md +397 -18
- package/skills/jgengine-editor/capabilities.md +46 -0
- package/skills/jgengine-editor/reference.md +87 -0
- package/skills/level-design/SKILL.md +54 -0
- package/skills/level-design/agents/openai.yaml +4 -0
- package/skills/level-design/references/application-playbook.md +192 -0
- package/skills/level-design/references/field-guide.md +337 -0
- package/skills/level-design/references/live-editor-loop.md +179 -0
- package/dist/OutlinerPanel.d.ts +0 -14
- package/dist/OutlinerPanel.js +0 -84
- package/skills/jgengine/reference-cartridge.md +0 -72
|
@@ -11,8 +11,19 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
11
11
|
- `EditorCatalogEntry` (interface) · `import { EditorCatalogEntry } from "@jgengine/core/editor"`
|
|
12
12
|
- `findEditorCatalog` (function) · `import { findEditorCatalog } from "@jgengine/core/editor"`
|
|
13
13
|
- `findEditorCatalogEntry` (function) · `import { findEditorCatalogEntry } from "@jgengine/core/editor"`
|
|
14
|
+
- `resolveCatalogDefinitions` (function) · `import { resolveCatalogDefinitions } from "@jgengine/core/editor"`
|
|
14
15
|
- `seedEditorCatalogs` (function) · `import { seedEditorCatalogs } from "@jgengine/core/editor"`
|
|
15
16
|
|
|
17
|
+
## editor-entities — Author entity stats/movement per catalog row instead of hardcoding TS.
|
|
18
|
+
|
|
19
|
+
- `entityDefinitionSchema` (const) · `import { entityDefinitionSchema } from "@jgengine/core/editor"`
|
|
20
|
+
- `entityEntryFromCatalog` (function) · `import { entityEntryFromCatalog } from "@jgengine/core/editor"`
|
|
21
|
+
|
|
22
|
+
## editor-environment — persist sky/fog/lighting knobs on the scene document
|
|
23
|
+
|
|
24
|
+
- `EditorEnvironment` (interface) · `import { EditorEnvironment } from "@jgengine/core/editor"`
|
|
25
|
+
- `skyFromDocument` (function) · `import { skyFromDocument } from "@jgengine/core/editor"`
|
|
26
|
+
|
|
16
27
|
## editor-grid-import — Configure an ASCII/glyph → grid-layer import.
|
|
17
28
|
|
|
18
29
|
- `AsciiGridImportOptions` (interface) · `import { AsciiGridImportOptions } from "@jgengine/core/editor"`
|
|
@@ -65,6 +76,12 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
65
76
|
- `runtimeEntityMetaWriteBackCommand` (function) · `import { runtimeEntityMetaWriteBackCommand } from "@jgengine/core/editor"`
|
|
66
77
|
- `summarizeRuntimeInspector` (function) · `import { summarizeRuntimeInspector } from "@jgengine/core/editor"`
|
|
67
78
|
|
|
79
|
+
## minimap-bake — persist a baked minimap PNG + bounds on the scene document
|
|
80
|
+
|
|
81
|
+
- `EditorMinimapBake` (interface) · `import { EditorMinimapBake } from "@jgengine/core/editor"`
|
|
82
|
+
- `bakeMinimapFromDocument` (function) · `import { bakeMinimapFromDocument } from "@jgengine/core/editor"`
|
|
83
|
+
- `documentBakeZones` (function) · `import { documentBakeZones } from "@jgengine/core/editor"`
|
|
84
|
+
|
|
68
85
|
## scene-ownership — audit a whole ownership manifest for boundary violations
|
|
69
86
|
|
|
70
87
|
- `auditManifest` (function) · `import { auditManifest } from "@jgengine/core/scene/sceneOwnership"`
|
|
@@ -72,3 +89,32 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
72
89
|
- `collectOwnershipDiagnostics` (function) · `import { collectOwnershipDiagnostics } from "@jgengine/core/scene/sceneOwnership"`
|
|
73
90
|
- `isSceneOwnershipManifest` (function) · `import { isSceneOwnershipManifest } from "@jgengine/core/scene/sceneOwnership"`
|
|
74
91
|
- `ownershipKey` (function) · `import { ownershipKey } from "@jgengine/core/scene/sceneOwnership"`
|
|
92
|
+
|
|
93
|
+
## world-convergence — derive environment coordinate content from the scene document
|
|
94
|
+
|
|
95
|
+
- `environmentContentFromDocument` (function) · `import { environmentContentFromDocument } from "@jgengine/core/editor"`
|
|
96
|
+
- `lakebedFromWaterVolumes` (function) · `import { lakebedFromWaterVolumes } from "@jgengine/core/editor/environment"`
|
|
97
|
+
- `terrainBoundsFromDocument` (function) · `import { terrainBoundsFromDocument } from "@jgengine/core/editor"`
|
|
98
|
+
|
|
99
|
+
## world-directives — apply a sparse overlay over materialized directive instances
|
|
100
|
+
|
|
101
|
+
- `applyDirectiveOverlay` (function) · `import { applyDirectiveOverlay } from "@jgengine/core/editor"`
|
|
102
|
+
- `materializeDirective` (function) · `import { materializeDirective } from "@jgengine/core/editor"`
|
|
103
|
+
- `materializeDirectives` (function) · `import { materializeDirectives } from "@jgengine/core/editor"`
|
|
104
|
+
- `materializePopulationDirective` (function) · `import { materializePopulationDirective } from "@jgengine/core/editor"`
|
|
105
|
+
- `materializeScatterDirective` (function) · `import { materializeScatterDirective } from "@jgengine/core/editor"`
|
|
106
|
+
- `resolveDirectiveFootprint` (function) · `import { resolveDirectiveFootprint } from "@jgengine/core/editor"`
|
|
107
|
+
|
|
108
|
+
## world-shards — decode an untrusted world manifest with per-field diagnostics
|
|
109
|
+
|
|
110
|
+
- `decodeWorldManifest` (function) · `import { decodeWorldManifest } from "@jgengine/core/editor"`
|
|
111
|
+
- `loadWorldDocument` (function) · `import { loadWorldDocument } from "@jgengine/core/editor"`
|
|
112
|
+
- `selectWorldShards` (function) · `import { selectWorldShards } from "@jgengine/core/editor"`
|
|
113
|
+
- `shardMatchesQuery` (function) · `import { shardMatchesQuery } from "@jgengine/core/editor"`
|
|
114
|
+
- `singleShardWorldManifest` (function) · `import { singleShardWorldManifest } from "@jgengine/core/editor"`
|
|
115
|
+
- `splitEditorDocumentIntoShards` (function) · `import { splitEditorDocumentIntoShards } from "@jgengine/core/editor"`
|
|
116
|
+
|
|
117
|
+
## world-streaming — schedule shard load/unload by camera proximity
|
|
118
|
+
|
|
119
|
+
- `createWorldStreamer` (function) · `import { createWorldStreamer } from "@jgengine/core/editor"`
|
|
120
|
+
- `shardDistance` (function) · `import { shardDistance } from "@jgengine/core/editor"`
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
# Editor RPC/CLI and agent panel
|
|
2
|
+
|
|
3
|
+
## Headless CLI persistence
|
|
4
|
+
|
|
5
|
+
`bun packages/editor/src/mcp/cli.ts --game <id> --rpc '<json>' … --save` runs the RPC batch on one
|
|
6
|
+
in-memory session and, when every RPC succeeds, writes the session document to
|
|
7
|
+
`Games/<id>/src/editor.scene.json` (dev-save format: 2-space JSON + trailing newline, identical to
|
|
8
|
+
the GUI's Ctrl+S through `devSavePlugin`). Without `--save`, `--rpc` mutations are discarded on
|
|
9
|
+
exit — use it for read-only inspection only, or capture `export_document` yourself.
|
|
10
|
+
|
|
1
11
|
# Editor agent panel (embedded)
|
|
2
12
|
|
|
3
13
|
Toolbar **Agent** opens a dockable chat panel in `EditorChrome`. Tool calls use the same editor RPC verbs as the MCP/CLI bridge and the GUI — one session undo stack, interleaved with human edits.
|
|
@@ -30,6 +40,15 @@ Content-Type: application/json
|
|
|
30
40
|
|
|
31
41
|
Each `toolCalls[].name` is an editor RPC method (`set_transform`, `select`, …). The panel runs them via `routeToolCall` → `EditorHostApi.handle`.
|
|
32
42
|
|
|
43
|
+
## Bridge reliability
|
|
44
|
+
|
|
45
|
+
The bridge is trustworthy so agents author instead of hardcoding — every path is honest about failure:
|
|
46
|
+
|
|
47
|
+
- **Rejected mutations return `ok:false` with a reason.** A locked/cyclic `set_transform`, a `set_parent` that would form a cycle, a collection/prefab verb targeting a missing id, and a batch verb that matches nothing all fail loudly — never a phantom `{ok:true}`.
|
|
48
|
+
- **One decode/migrate boundary.** `decodeEditorDocument` (`@jgengine/core/editor`) validates every field with a path-specific diagnostic (`$.markers[2].position`) and migrates forward; `import_document` and a `push_document_patch` **snapshot** both clear it, so a malformed or old document fails or migrates loudly rather than corrupting a live session.
|
|
49
|
+
- **Document-global id uniqueness.** Placeable ids (markers/volumes/paths/notes) are one namespace: adds re-id on collision, and a single imported document that reuses an id is rejected with its path — a duplicate-id import is impossible. Combine paths (`mergeEditorDocuments`, duplicate, overlay) re-id instead.
|
|
50
|
+
- **Schema-validated input.** `decodeEditorBridgeRequest` type-checks each field a method understands against the per-method schema before it reaches `handle` — a fuzzed value (string where a number belongs, scalar where an object belongs) is rejected at the `--rpc`/HTTP/stdio/agent-tool boundary, never cast in blind. Missing/unknown fields are left to `handle`'s guards so the boundary stays forward-compatible.
|
|
51
|
+
|
|
33
52
|
## Pure API (`@jgengine/editor`)
|
|
34
53
|
|
|
35
54
|
```ts
|
|
@@ -63,6 +82,53 @@ routeToolCall(api, { id: "1", name: "set_transform", arguments: { id: "boss", x:
|
|
|
63
82
|
|
|
64
83
|
Commands: `/help`, `/status`, `/summary`, `/selection`, `/frame`, `/undo`, `/redo`, `/clear`, `/select <id…>`, `/goto <id>`, `move <id> <x> <y> <z>`.
|
|
65
84
|
|
|
85
|
+
## Data catalogs & entity definitions
|
|
86
|
+
|
|
87
|
+
The **Data** tab (`CatalogsPanel`) edits gameplay tuning rows that persist on the scene document
|
|
88
|
+
(`EditorDocument.catalogs`). Two kinds of catalog feed the tab, merged by
|
|
89
|
+
`resolveCatalogDefinitions(document, gameDefinitions)`: **game-exported** catalogs whose schema lives
|
|
90
|
+
in code (a game's `editorCatalogs` export, `EditorCatalogDefinition[]`: `{ id, label, schema:
|
|
91
|
+
ParamSchema, entries }`, wired via a `defineGame`-sibling module export passed as the `catalogs` prop —
|
|
92
|
+
the scaffold's `main.tsx` passes `catalogs={editorCatalogs}`), and **editor-authored** catalogs created
|
|
93
|
+
entirely in the editor. A game def always wins on id collision; a document catalog is surfaced only when
|
|
94
|
+
it carries its own `schema`.
|
|
95
|
+
|
|
96
|
+
Beyond tuning existing rows the tab **authors catalogs and schemas**:
|
|
97
|
+
- **Create a catalog** — the `+ New catalog` form takes an id (+ optional label) and dispatches
|
|
98
|
+
`addCatalog` with an empty `schema: { fields: [] }`. The document now *carries the schema*
|
|
99
|
+
(`EditorCatalogData.schema`/`label`), so an editor-only catalog round-trips through save/reload and
|
|
100
|
+
drives the default `content.ts` path with no game code.
|
|
101
|
+
- **Author schema fields** — for document-authored catalogs (`data.schema !== undefined`; game-exported
|
|
102
|
+
catalogs stay read-only since their schema is in code) the field editor adds/renames/removes fields
|
|
103
|
+
(key, type over `ParamField["type"]`, default, min/max). Every field mutation rebuilds the whole
|
|
104
|
+
`fields` array and dispatches one `setCatalogSchema`, whose reducer **re-parses every row's `meta`
|
|
105
|
+
against the new schema** via `parseParams`: removed keys drop, added keys default in, range/number
|
|
106
|
+
values clamp. One undoable step.
|
|
107
|
+
- **Author rows** — `+ Row` adds a schema-defaulted entry; each row has a remove (`×`).
|
|
108
|
+
|
|
109
|
+
Agents/CLI drive the same edits: `add_catalog` / `remove_catalog` / `set_catalog_schema` for the
|
|
110
|
+
catalog + schema, and `add_catalog_entry` / `remove_catalog_entry` / `set_catalog_entry` for rows
|
|
111
|
+
(alongside `list_catalogs`, `get_catalog_entry`). A catalog added via `add_catalog` is RPC-addressable
|
|
112
|
+
immediately (the host recomputes merged defs per request). New-row meta is seeded from the catalog
|
|
113
|
+
`ParamSchema` defaults and validated before it lands. Values and document-carried schemas save into
|
|
114
|
+
`editor.scene.json` → `catalogs`.
|
|
115
|
+
|
|
116
|
+
**Entity definitions** are a data catalog: the well-known `ENTITY_CATALOG_ID` (`"entities"`) catalog,
|
|
117
|
+
whose rows carry role/health/speed/scale per `entityDefinitionSchema`. `entityEntryFromCatalog(document,
|
|
118
|
+
catalogId, definitions?)` (`@jgengine/core/editor`) turns a row into the runtime
|
|
119
|
+
`GameContextEntityEntry` the default `content.ts#entityById` returns — so a `mob`/`boss` marker whose
|
|
120
|
+
`catalogId` names an entities row spawns with the stats/speed tuned in the editor, no game TS. It
|
|
121
|
+
prefers a document-carried `entities` schema over `entityDefinitionSchema` when the document authored
|
|
122
|
+
one, so a re-authored entity field set drives the parse.
|
|
123
|
+
`authoredEntitySpawns(document)` (`@jgengine/core/world/authoredEntities`) yields the spawn plan
|
|
124
|
+
(`{ markerId, catalogId, position, rotationY }`) the scaffold `loop.ts` feeds to
|
|
125
|
+
`ctx.scene.entity.spawn`. Author entities in the editor (place a marker → Data tab → tune the row →
|
|
126
|
+
save); never hardcode entity stats where the document should own them.
|
|
127
|
+
|
|
128
|
+
## Asset import
|
|
129
|
+
|
|
130
|
+
Dropping a `.glb`/`.gltf` into the editor persists it durably, but where depends on the project shape (`editorHostPlugin`, `@jgengine/node`). A **standalone folder workspace** copies the bytes into the scanned asset folder and re-lists them under a scan-stable id (`importEditorAsset`); the id comes from the file's workspace-relative path, so a placement referencing it resolves after reload. A **promoted game** (one with a typed `src/game/assets.ts` catalog — `isPromotedProject`) instead copies the bytes into `public/<basePath>/imported/` and rewrites `assets.ts` to add a durable `extras` entry to its `buildCatalog({ extras })` call (`importPromotedAsset` → `upsertCatalogExtra`), so the **shipped** game serves and resolves the asset through its own typed catalog rather than a dev-only route. The id matches what a folder rescan would produce, the rewrite is idempotent (re-import of the same id collapses to a single entry), and an unparseable or multi-`buildCatalog` source throws so the host falls back to the folder-scan import rather than corrupt the file.
|
|
131
|
+
|
|
66
132
|
## Grid / tile layers
|
|
67
133
|
|
|
68
134
|
Grid-addressed content (rooms, tactics maps, farms, nav/rule layers) lives on the scene document as
|
|
@@ -88,3 +154,24 @@ author the grid and read it at runtime.
|
|
|
88
154
|
`importCsvGrid`/`exportCsvGrid` (value id per cell). ASCII/CSV are import paths **into** the grid
|
|
89
155
|
document, never the canonical representation — `migrateGridLayer` normalizes and version-migrates
|
|
90
156
|
any layer from disk or an adapter.
|
|
157
|
+
|
|
158
|
+
## Minimap bake (#1036)
|
|
159
|
+
|
|
160
|
+
`bake_minimap` rasterizes the authored terrain into a top-down PNG stored on the document as
|
|
161
|
+
`EditorDocument.minimap: EditorMinimapBake` (`{ background: "data:image/png;…", bounds }`). The pure,
|
|
162
|
+
deterministic core rasterizer is `bakeMinimapFromDocument` (`@jgengine/core/editor/index`); the RPC
|
|
163
|
+
handler composes the live viewport's base ground field with `document.terrain` and dispatches the
|
|
164
|
+
undoable `setMinimapBake` command. Runtime feeds the stored `background`/`bounds` straight into the
|
|
165
|
+
`Minimap`/`WorldMap` props — **no re-rasterization at runtime** (see `jgengine-ui`).
|
|
166
|
+
|
|
167
|
+
- **Live-viewport only.** The bake needs the mounted editor world's composed height/normal sampler
|
|
168
|
+
(`EditorHostApi.getTerrainSampler`, registered by `EditorWorldOverlay` while the viewport is
|
|
169
|
+
mounted). It is **not** a headless CLI/MCP verb: with no viewport the sampler is null and
|
|
170
|
+
`bake_minimap` returns `{ ok:false, error:"bake_minimap needs the live editor viewport" }`. To bake
|
|
171
|
+
a committed scene offline, run a deterministic node script that rebuilds the base field with
|
|
172
|
+
`groundFieldFor(world)` and calls `bakeMinimapFromDocument` (see
|
|
173
|
+
`scripts/bake-claudecraft-minimap.ts`).
|
|
174
|
+
- GUI: the Terrain panel's **Bake minimap** button calls `bake_minimap` and surfaces any `ok:false`
|
|
175
|
+
error inline.
|
|
176
|
+
- RPC/CLI verb: `bake_minimap` (optional `padding`, `resolution`, `waterLevel`). The bake path uses
|
|
177
|
+
no `Date`/`Math.random`, so the same scene + sampler always bakes byte-identical output.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: level-design
|
|
3
|
+
description: Design, audit, author, implement, and validate readable levels, worlds, encounters, navigation, and pacing.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Level design
|
|
7
|
+
|
|
8
|
+
## Ownership
|
|
9
|
+
|
|
10
|
+
Own the spatial realization of game design: player metrics, topology, routes, landmarks, gates, encounter geometry, challenge sequencing, exploration, pacing, recovery, and spatial storytelling. Use `game-design` for the player promise and loops, `jgengine-editor` to author space, and `jgengine-world` to consume it.
|
|
11
|
+
|
|
12
|
+
All authorable world content belongs in `editor.scene.json`, changed through the editor GUI or RPC/CLI. Never hand-edit the document or keep geometry, paths, spawns, zones, objectives, terrain, foliage, encounters, or coordinate arrays in code. File an editor `[FEATURE]` issue before any fallback.
|
|
13
|
+
|
|
14
|
+
Read [references/application-playbook.md](references/application-playbook.md) only when the task explicitly calls for spatial design depth — a level/world design brief, an audit or redesign, or "make this fun/better" work; it is not a mandatory step of creating a game. Read [references/live-editor-loop.md](references/live-editor-loop.md) whenever live captures, an editor-agent handoff, or iterative scene improvement is involved. Read [references/field-guide.md](references/field-guide.md) for metric families, topology, pacing, genre lenses, accessibility, and research.
|
|
15
|
+
|
|
16
|
+
## Choose the mode
|
|
17
|
+
|
|
18
|
+
### Greenfield
|
|
19
|
+
|
|
20
|
+
Measure the real controller, camera, interaction, combat, AI, and network constraints in an authored metric gym. Produce a topology graph, critical/optional route model, beat sheet, learning sequence, encounter cards, authoring plan, and falsifiable completion scenario before art production.
|
|
21
|
+
|
|
22
|
+
### Existing game
|
|
23
|
+
|
|
24
|
+
Start with a spatial-truth audit. Inventory every source of coordinates and semantics; report any gameplay placement outside `editor.scene.json` as a blocking ownership defect. Reconstruct the critical path and representative optional path from scene data and live play. Measure travel, decision, encounter, retry, and recovery time. Inspect first-look orientation, reverse navigation, affordances, spawn safety, combat positions, pacing contrast, and visual hierarchy.
|
|
25
|
+
|
|
26
|
+
“Improve with level design” is an authoring and implementation request. Do not stop at a map critique: select the highest-leverage route/zone/encounter slice, author the change through editor operations, connect runtime semantics, and prove it in play.
|
|
27
|
+
|
|
28
|
+
For a live editor handoff, send evidence and an executable authoring contract—not an aesthetic request. Require the editor agent to inspect authority, document revision, ids, layers, assets, runtime state, and tool support before mutation; apply one coherent hypothesis through undoable operations; then return the exact revision/change log for replay and comparison. Stop when the live editor is not connected to the runtime's authoritative scene or the required operation is unsupported.
|
|
29
|
+
|
|
30
|
+
## Required output contract
|
|
31
|
+
|
|
32
|
+
Make every level-design pass yield:
|
|
33
|
+
|
|
34
|
+
1. **Spatial truth audit:** scene counts and semantic kinds plus every code-owned coordinate table, generated placement, or duplicated position that must migrate.
|
|
35
|
+
2. **Metric sheet:** measured movement, camera, interaction, weapon/AI, readability, density, performance, multiplayer, and retry constraints with units.
|
|
36
|
+
3. **Topology and journey:** nodes/edges, critical and optional routes, gates, returns, landmarks, expected traversal times, and first-minute/mission/campaign beats.
|
|
37
|
+
4. **Zone/encounter diagnosis:** purpose, entry knowledge/state, choices, geometry, actors, escalation, resources, exits, failure/reset, reward, and downstream change.
|
|
38
|
+
5. **Bottleneck ranking:** observed symptom, player consequence, root cause, evidence, reach, confidence, effort, dependencies, and ownership.
|
|
39
|
+
6. **Editor change set:** exact semantic ids/kinds and operations to add/move/remove for paths, markers, zones, spawns, objectives, checkpoints, props, and terrain—without putting coordinates in code.
|
|
40
|
+
7. **Acceptance evidence:** document assertions, route/encounter tests, fresh-player play scenario, pacing/wayfinding thresholds, inspected screenshots, and before/after comparison.
|
|
41
|
+
|
|
42
|
+
## Execution rules
|
|
43
|
+
|
|
44
|
+
- Graph before geometry; graybox before art; gameplay and wayfinding before decoration.
|
|
45
|
+
- Present decision-relevant information before commitment. Make alternate routes differ in risk, cost, verbs, information, reward, or experience.
|
|
46
|
+
- Sequence teaching through cue, safe use, feedback, independent test, combination, transformation, and mastery as the audience requires.
|
|
47
|
+
- Align composition, landmark, value/color, motion, audio, affordance, path shape, and optional UI guidance. No marker can repair contradictory space.
|
|
48
|
+
- Design pacing across separate threat, motor, cognitive, navigation, emotional, resource, and social axes. Constant pressure or empty traversal is not pacing.
|
|
49
|
+
- Make every encounter support intended verbs, counterplay, retreat, fair spawns, recovery, and bounded performance.
|
|
50
|
+
- Populate only after the graybox survives play. Preserve silhouettes, safe footing, goals, threats, interactables, teams, and traversal boundaries through art passes.
|
|
51
|
+
|
|
52
|
+
## Completion
|
|
53
|
+
|
|
54
|
+
An audit or prettier screenshot is not completion for a build/improve request. Finish when the scene document owns spatial truth; a fresh target player can orient, choose, act, recover, and complete the scenario without coaching; the route has intentional decisions and pacing; encounter exploits and alternate states are tested; and `jgengine-verify` records document, gameplay, and inspected visual evidence.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Level Design"
|
|
3
|
+
short_description: "Design readable, paced, playable spaces"
|
|
4
|
+
default_prompt: "Use $level-design to observe this world live, brief and drive the editor agent through an authoritative scene change, then replay the same journey and prove the result."
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Applying level design
|
|
2
|
+
|
|
3
|
+
Use this playbook to turn spatial intent or an existing world into editor-authored, playable change. Its purpose is to force concrete topology, authoring operations, and evidence rather than aesthetic commentary.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
1. Greenfield procedure
|
|
8
|
+
2. Existing-world audit
|
|
9
|
+
3. Spatial truth and metrics
|
|
10
|
+
4. Journey, topology, and beats
|
|
11
|
+
5. Zone and encounter diagnosis
|
|
12
|
+
6. Ranking interventions
|
|
13
|
+
7. Editor change set
|
|
14
|
+
8. Implementation and proof
|
|
15
|
+
9. Failure modes
|
|
16
|
+
|
|
17
|
+
## 1. Greenfield procedure
|
|
18
|
+
|
|
19
|
+
Before production art:
|
|
20
|
+
|
|
21
|
+
1. Import the game-design contract: promise, verbs, repeated decision, loops, target player, and completion proof.
|
|
22
|
+
2. Author a metric gym and measure the actual controller, camera, interaction, combat, AI, and network behavior.
|
|
23
|
+
3. Draw the topology graph with starts, goals, critical/optional routes, gates, returns, checkpoints, encounters, safe spaces, and rewards.
|
|
24
|
+
4. Write a beat sheet across threat, motor, cognitive, navigation, emotional, resource, and social intensity.
|
|
25
|
+
5. Map where each mechanic is cued, tried safely, tested, combined, transformed, and mastered.
|
|
26
|
+
6. Specify encounter cards and the semantic scene ids they require.
|
|
27
|
+
7. Graybox one route/zone slice in `editor.scene.json` through GUI or RPC/CLI.
|
|
28
|
+
8. Playtest orientation, decisions, traversal, encounter flow, failure, and retry before population and art.
|
|
29
|
+
|
|
30
|
+
## 2. Existing-world audit
|
|
31
|
+
|
|
32
|
+
### Inventory spatial truth
|
|
33
|
+
|
|
34
|
+
Inspect the editor document and source tree. Report separately:
|
|
35
|
+
|
|
36
|
+
- authored paths and point counts
|
|
37
|
+
- authored markers grouped by semantic kind and catalog id
|
|
38
|
+
- authored zones/volumes, terrain, foliage, annotations, prefabs, and collections
|
|
39
|
+
- gameplay spawns, objectives, NPCs, vendors, loot, checkpoints, gates, and encounters
|
|
40
|
+
- coordinate arrays, centers, offsets, radii, procedural placement, and duplicated positions in code
|
|
41
|
+
- runtime queries that consume stable scene ids/kinds
|
|
42
|
+
|
|
43
|
+
If gameplay placement exists in code but not the document, mark the spatial-truth audit failed before discussing polish. The repair is an editor-authored migration with stable semantics, not another adapter around coordinate tables.
|
|
44
|
+
|
|
45
|
+
### Observe live play
|
|
46
|
+
|
|
47
|
+
Capture and inspect:
|
|
48
|
+
|
|
49
|
+
- spawn/first frame and the first ten seconds
|
|
50
|
+
- first decision and first objective
|
|
51
|
+
- one critical-path transition
|
|
52
|
+
- one representative encounter and retry
|
|
53
|
+
- one optional route/POI
|
|
54
|
+
- reverse travel or return after state change
|
|
55
|
+
- a dense/peak gameplay frame
|
|
56
|
+
|
|
57
|
+
Record what dominates the frame, what the player can infer, where they look, where they move, what they miss, and whether UI/world cues agree. Pixel metrics only reject technical blanks; human inspection judges composition and gameplay readability.
|
|
58
|
+
|
|
59
|
+
## 3. Spatial truth and metrics
|
|
60
|
+
|
|
61
|
+
### Metric sheet
|
|
62
|
+
|
|
63
|
+
| Family | Measured values | Source/build | Design consequence | Extreme/accessibility case |
|
|
64
|
+
| --- | --- | --- | --- | --- |
|
|
65
|
+
| movement | speed, acceleration, stop, turn, jump, slope, radius | | | |
|
|
66
|
+
| camera | perspective, FOV, offset, obstruction, sensitivity | | | |
|
|
67
|
+
| interaction | range, use time, target clarity | | | |
|
|
68
|
+
| combat/AI | weapon bands, projectile time, sensing, attack, group size | | | |
|
|
69
|
+
| navigation | path width, sightline, branch/rejoin, landmark range | | | |
|
|
70
|
+
| pacing | time to action, encounter, rest, reward, retry | | | |
|
|
71
|
+
| multiplayer | spawn, regroup, revive, latency, count | | | |
|
|
72
|
+
| performance | actor/object density, nav, draw, simulation | | | |
|
|
73
|
+
|
|
74
|
+
Derive dimensions from the measured game. Never paste corridor, cover, jump, or arena numbers from another title.
|
|
75
|
+
|
|
76
|
+
### Travel-time audit
|
|
77
|
+
|
|
78
|
+
Measure each route at the actual movement speed, including turns, hazards, encounters, and interaction delay. For every interval, classify the intended value: decision, mastery, anticipation, story, resource planning, combat, exploration, recovery, or deliberate atmosphere. Empty time with no purpose is a pacing defect even when the scenery is attractive.
|
|
79
|
+
|
|
80
|
+
## 4. Journey, topology, and beats
|
|
81
|
+
|
|
82
|
+
### Topology table
|
|
83
|
+
|
|
84
|
+
| Node/edge | Purpose | Entry information | Choice/tradeoff | Gate/return | Expected time | Downstream change |
|
|
85
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
86
|
+
|
|
87
|
+
Validate reachability for relevant quest/world states and the reverse direction. Branches must differ in risk, cost, verb, information, reward, story, or experience.
|
|
88
|
+
|
|
89
|
+
### Beat sheet
|
|
90
|
+
|
|
91
|
+
| Time/distance | Beat | Threat | Motor | Cognitive | Navigation | Emotion/resource | Evidence/failure signal |
|
|
92
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
93
|
+
|
|
94
|
+
Look for long flats, constant peaks, unseen goals, repeated rhythms, rewards without anticipation, combat without aftermath, and failure without fast useful retry.
|
|
95
|
+
|
|
96
|
+
### First-minute contract
|
|
97
|
+
|
|
98
|
+
The first minute must deliberately answer:
|
|
99
|
+
|
|
100
|
+
- Where am I and what fantasy am I inhabiting?
|
|
101
|
+
- What can I do now?
|
|
102
|
+
- What should I notice first?
|
|
103
|
+
- What is my immediate goal and why?
|
|
104
|
+
- Where is the first safe experiment?
|
|
105
|
+
- What consequence teaches the rule?
|
|
106
|
+
- What next decision promises depth?
|
|
107
|
+
|
|
108
|
+
Do not answer all seven with text. Use space, action, feedback, and only the necessary UI.
|
|
109
|
+
|
|
110
|
+
## 5. Zone and encounter diagnosis
|
|
111
|
+
|
|
112
|
+
### Zone card
|
|
113
|
+
|
|
114
|
+
- role in the game/session loop
|
|
115
|
+
- visual/spatial identity and landmark hierarchy
|
|
116
|
+
- entry/exit states and critical/optional routes
|
|
117
|
+
- mechanics introduced, tested, combined, and mastered
|
|
118
|
+
- decision types and exploration rewards
|
|
119
|
+
- pacing arc, safe spaces, checkpoints, and return value
|
|
120
|
+
- content budget and performance peak
|
|
121
|
+
- spatial story and world-state change
|
|
122
|
+
|
|
123
|
+
Zones that differ only by palette, enemy level, or kill quota do not provide meaningful progression.
|
|
124
|
+
|
|
125
|
+
### Encounter card
|
|
126
|
+
|
|
127
|
+
- purpose and target player behavior
|
|
128
|
+
- entry sightline, knowledge, position, resources, and condition
|
|
129
|
+
- initial decision and viable approaches
|
|
130
|
+
- geometry for every intended verb and counterplay
|
|
131
|
+
- actors/hazards, escalation, reinforcement, peak, and resolution
|
|
132
|
+
- cover/refuge, retreat, flank, exits, and exploit risks
|
|
133
|
+
- reward, failure/reset, retry time, and downstream state change
|
|
134
|
+
- semantic scene ids and performance budget
|
|
135
|
+
|
|
136
|
+
## 6. Ranking interventions
|
|
137
|
+
|
|
138
|
+
Rank candidate changes with evidence:
|
|
139
|
+
|
|
140
|
+
| Candidate | Player behavior changed | Reach | Evidence/confidence | Effort/risk | Dependencies | Editor/runtime owner |
|
|
141
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
142
|
+
|
|
143
|
+
Use three horizons:
|
|
144
|
+
|
|
145
|
+
- **Minimum correction:** migrate invalid spatial ownership or repair a blocking orientation/flow failure.
|
|
146
|
+
- **Strong target:** make one representative route/zone/encounter deliver the intended promise end to end.
|
|
147
|
+
- **Multiplier:** propagate the proven spatial grammar, semantic kinds, encounter kit, and tests across the world.
|
|
148
|
+
|
|
149
|
+
Prioritize upstream seams and reusable authoring kinds. Do not spend the first pass scattering props across a structurally unchanged map.
|
|
150
|
+
|
|
151
|
+
## 7. Editor change set
|
|
152
|
+
|
|
153
|
+
Specify operations semantically, not as code coordinates:
|
|
154
|
+
|
|
155
|
+
| Operation | Stable id/kind | Purpose/meta | Runtime consumer | Acceptance |
|
|
156
|
+
| --- | --- | --- | --- | --- |
|
|
157
|
+
| add/move/remove path | | from/to, route role | | |
|
|
158
|
+
| add/move/remove marker | | spawn/objective/NPC/checkpoint/landmark | | |
|
|
159
|
+
| add/move/remove zone | | encounter/settlement/safe/gate/resource | | |
|
|
160
|
+
| terrain/foliage/material pass | | traversal/readability/identity | | |
|
|
161
|
+
| prop/asset pass | | cover/affordance/story/landmark | | |
|
|
162
|
+
|
|
163
|
+
Execute through `jgengine-editor`. Gameplay code queries ids, kinds, layers, and metadata; it does not receive copied positions. File an editor feature issue if a required semantic kind or operation does not exist.
|
|
164
|
+
|
|
165
|
+
## 8. Implementation and proof
|
|
166
|
+
|
|
167
|
+
When the user asks to build or improve:
|
|
168
|
+
|
|
169
|
+
1. Establish before evidence and the acceptance scenario.
|
|
170
|
+
2. Author the chosen graybox and semantics through the editor.
|
|
171
|
+
3. Connect shared runtime/gameplay primitives to the authored ids.
|
|
172
|
+
4. Migrate superseded coordinate tables without changing unrelated content.
|
|
173
|
+
5. Add document assertions for required paths, zones, markers, and ids.
|
|
174
|
+
6. Add deterministic route, encounter, reset, and state-transition tests.
|
|
175
|
+
7. Run a fresh-player or representative play scenario.
|
|
176
|
+
8. Capture and inspect the same views before/after.
|
|
177
|
+
9. Evaluate timing, choice, comprehension, exploit, accessibility, and performance falsifiers.
|
|
178
|
+
|
|
179
|
+
Evidence should answer the design claim. Scene counts prove ownership, headless tests prove state, a driven playtest proves progress, and inspected screenshots prove visible composition. No one rung proves all four.
|
|
180
|
+
|
|
181
|
+
## 9. Failure modes
|
|
182
|
+
|
|
183
|
+
- praising asset count while gameplay semantics remain in code
|
|
184
|
+
- drawing a map without measuring the real controller/camera
|
|
185
|
+
- calling multiple corridors meaningful choice
|
|
186
|
+
- filling empty travel with collectibles instead of decisions or pacing
|
|
187
|
+
- changing color/lighting while topology and encounter flow remain unchanged
|
|
188
|
+
- using objective markers to compensate for contradictory geometry
|
|
189
|
+
- designing only the critical path or only the plan view
|
|
190
|
+
- making every zone the same objective with new enemies and palette
|
|
191
|
+
- reporting an audit after the user asked for improvement
|
|
192
|
+
- claiming success from scene counts, tests, telemetry, or screenshots alone
|