@jgengine/editor 0.18.0 → 0.19.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 +265 -2
- package/dist/ClipPreviewLayer.js +18 -2
- package/dist/EditorChrome.js +7 -0
- package/dist/LightingPanel.js +13 -1
- package/dist/handlers/document.js +2 -0
- package/dist/handlers/index.js +2 -0
- package/dist/handlers/navmesh.d.ts +5 -0
- package/dist/handlers/navmesh.js +21 -0
- package/dist/handlers/streets.js +15 -2
- package/dist/mcp/fieldSpec.js +3 -2
- package/dist/mcp/tools.js +3 -2
- package/dist/modelAnimationAuthoring.d.ts +23 -0
- package/dist/modelAnimationAuthoring.js +58 -1
- package/dist/session.d.ts +11 -0
- package/dist/session.js +2 -0
- package/dist/shell/AnimationGraphPanel.d.ts +16 -0
- package/dist/shell/AnimationGraphPanel.js +172 -0
- package/dist/shell/AnimationPanel.d.ts +3 -1
- package/dist/shell/AnimationPanel.js +9 -7
- package/dist/shell/WorkspaceRail.js +1 -1
- package/dist/shell/animGraphPreview.d.ts +56 -0
- package/dist/shell/animGraphPreview.js +92 -0
- package/dist/shell/clipPreview.d.ts +8 -0
- package/package.json +5 -4
- package/skills/ce-handoff/SKILL.md +2 -2
- package/skills/jgengine/SKILL.md +9 -5
- package/skills/jgengine/api.md +205 -101
- package/skills/jgengine/capabilities.md +56 -0
- package/skills/jgengine/recipes/minimal-game.md +3 -0
- package/skills/jgengine-editor/SKILL.md +3 -1
- package/skills/jgengine-editor/api.md +28 -0
- package/skills/jgengine-editor/reference.md +13 -3
- package/skills/level-design/SKILL.md +1 -1
|
@@ -12,10 +12,30 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
12
12
|
|
|
13
13
|
- `collectAuthoredTriggers` (function) · `import { collectAuthoredTriggers } from "@jgengine/shell/gameKit"`
|
|
14
14
|
|
|
15
|
+
## chase-view-cycle — cycle a vehicle camera between chase, hood and cockpit views at runtime
|
|
16
|
+
|
|
17
|
+
- `nextChaseView` (function) · `import { nextChaseView } from "@jgengine/core/runtime/cameraDirector"`
|
|
18
|
+
|
|
19
|
+
## client-side — input prediction with replay reconciliation
|
|
20
|
+
|
|
21
|
+
- `createPredictionBuffer` (function) · `import { createPredictionBuffer } from "@jgengine/core/runtime/prediction"`
|
|
22
|
+
|
|
15
23
|
## collider-autofit — hitboxes and physical bodies fit each kind's rendered model bounds automatically — no hand-tuned sizes
|
|
16
24
|
|
|
17
25
|
- `GameContextModels` (interface) · `import { GameContextModels } from "@jgengine/core/runtime/gameContext"`
|
|
18
26
|
|
|
27
|
+
## command-number — validate finite, bounded numbers and integers at command boundaries
|
|
28
|
+
|
|
29
|
+
- `readInputNumber` (function) · `import { readInputNumber } from "@jgengine/core/runtime/commandInput"`
|
|
30
|
+
|
|
31
|
+
## command-parse — parse untrusted command input once so every command stage sees typed, bounded values
|
|
32
|
+
|
|
33
|
+
- `defineCommand` (function) · `import { defineCommand } from "@jgengine/core/runtime/commandRunner"`
|
|
34
|
+
|
|
35
|
+
## command-quantity — validate bounded whole-item counts at command boundaries
|
|
36
|
+
|
|
37
|
+
- `readQuantity` (function) · `import { readQuantity } from "@jgengine/core/runtime/commandInput"`
|
|
38
|
+
|
|
19
39
|
## default-walk-codes — stock WASD + jump key codes for the shell walk controller
|
|
20
40
|
|
|
21
41
|
- `DEFAULT_WALK_CODES` (const) · `import { DEFAULT_WALK_CODES } from "@jgengine/shell/gameKit"`
|
|
@@ -32,6 +52,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
32
52
|
|
|
33
53
|
- `EditorCatalogDefinition` (interface) · `import { EditorCatalogDefinition } from "@jgengine/shell/gameKit"`
|
|
34
54
|
|
|
55
|
+
## fire-input — bind a key or mouse button to a named action that runs the same-named command with the aim; repeatMs auto-fires while held
|
|
56
|
+
|
|
57
|
+
- `ActionCodesMap` (type) · `import { ActionCodesMap } from "@jgengine/core/authoring"`
|
|
58
|
+
|
|
35
59
|
## game-system — declare a composable capability with its own schedule and lifecycle
|
|
36
60
|
|
|
37
61
|
- `SystemDefinition` (interface) · `import { SystemDefinition } from "@jgengine/shell/gameKit"`
|
|
@@ -84,6 +108,14 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
84
108
|
|
|
85
109
|
- `StatBar` (function) · `import { StatBar } from "@jgengine/shell/gameKit"`
|
|
86
110
|
|
|
111
|
+
## input-recorder — tick-indexed input log for replay, rollback, and regression tests
|
|
112
|
+
|
|
113
|
+
- `createInputRecorder` (function) · `import { createInputRecorder } from "@jgengine/core/runtime/inputRecorder"`
|
|
114
|
+
|
|
115
|
+
## local-players — Couch co-op seats: devices hot-join into slots, each with its own user id and input snapshot.
|
|
116
|
+
|
|
117
|
+
- `createLocalPlayers` (function) · `import { createLocalPlayers } from "@jgengine/core/runtime/localPlayers"`
|
|
118
|
+
|
|
87
119
|
## loot-table — validate a loot table definition for use with the registry
|
|
88
120
|
|
|
89
121
|
- `lootTable` (function) · `import { lootTable } from "@jgengine/core/authoring"`
|
|
@@ -116,6 +148,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
116
148
|
|
|
117
149
|
- `toRuntimeObjectRow` (function) · `import { toRuntimeObjectRow } from "@jgengine/core/runtime/objectRows"`
|
|
118
150
|
|
|
151
|
+
## pose-interpolation — render entity poses between fixed simulation steps without stutter
|
|
152
|
+
|
|
153
|
+
- `createPoseHistory` (function) · `import { createPoseHistory } from "@jgengine/core/runtime/poseInterpolation"`
|
|
154
|
+
|
|
119
155
|
## render-fallback-diagnostics — Enable/disable the dev-only placeholder-fallback probe.
|
|
120
156
|
|
|
121
157
|
- `armFallbackSeams` (function) · `import { armFallbackSeams } from "@jgengine/core/devtools/fallbackSeams"`
|
|
@@ -126,6 +162,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
126
162
|
- `resetTextureErrors` (function) · `import { resetTextureErrors } from "@jgengine/core/devtools/textureErrors"`
|
|
127
163
|
- `textureErrorsSnapshot` (function) · `import { textureErrorsSnapshot } from "@jgengine/core/devtools/textureErrors"`
|
|
128
164
|
|
|
165
|
+
## runtime — snapshot interpolation
|
|
166
|
+
|
|
167
|
+
- `createSnapshotBuffer` (function) · `import { createSnapshotBuffer } from "@jgengine/core/runtime/snapshotBuffer"`
|
|
168
|
+
|
|
129
169
|
## runtime-save — save/load the whole game world through a pluggable backend, autosave or save points
|
|
130
170
|
|
|
131
171
|
- `createRuntimeSave` (function) · `import { createRuntimeSave } from "@jgengine/core/runtime/runtimeSave"`
|
|
@@ -142,6 +182,14 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
142
182
|
|
|
143
183
|
- `seededRng` (function) · `import { seededRng } from "@jgengine/shell/gameKit"`
|
|
144
184
|
|
|
185
|
+
## sim-loop — fixed-step or variable simulation stepping with tick count, catch-up cap, and interpolation alpha
|
|
186
|
+
|
|
187
|
+
- `createSimLoop` (function) · `import { createSimLoop } from "@jgengine/core/runtime/simLoop"`
|
|
188
|
+
|
|
189
|
+
## sim-snapshot — capture and restore whole-simulation state for replay, rollback, and regression tests
|
|
190
|
+
|
|
191
|
+
- `createSimSnapshotRegistry` (function) · `import { createSimSnapshotRegistry } from "@jgengine/core/runtime/simSnapshot"`
|
|
192
|
+
|
|
145
193
|
## typed-keyed-store — a cast-free typed handle onto a per-owner keyed family of reactive game-store slots, replayable and host-authoritative
|
|
146
194
|
|
|
147
195
|
- `defineKeyedStore` (function) · `import { defineKeyedStore } from "@jgengine/shell/gameKit"`
|
|
@@ -150,6 +198,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
150
198
|
|
|
151
199
|
- `defineStore` (function) · `import { defineStore } from "@jgengine/shell/gameKit"`
|
|
152
200
|
|
|
201
|
+
## warn-once — emit a dev-only warning a single time per call site
|
|
202
|
+
|
|
203
|
+
- `warnOnce` (function) · `import { warnOnce } from "@jgengine/core/devtools/warnOnce"`
|
|
204
|
+
|
|
153
205
|
## world-chunk-key — map world positions to persisted chunk keys at a declared cell size
|
|
154
206
|
|
|
155
207
|
- `chunkKeyOf` (function) · `import { chunkKeyOf } from "@jgengine/core/runtime/worldChunks"`
|
|
@@ -165,3 +217,7 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
165
217
|
## world-environment — compose editor/preset-derived outdoor dressing — terrain, weather, water, structures — into a legacy environment feature
|
|
166
218
|
|
|
167
219
|
- `environment` (function) · `import { environment } from "@jgengine/shell/gameKit"`
|
|
220
|
+
|
|
221
|
+
## world-item-pickup — pick up dropped items: ctx.scene.worldItem nearestInRadius → pickup into the player's inventory
|
|
222
|
+
|
|
223
|
+
- `SceneWorldItemContext` (interface) · `import { SceneWorldItemContext } from "@jgengine/core/runtime/gameContext"`
|
|
@@ -45,6 +45,9 @@ spatial place. When the game *is* a place, declare only substrate + laws with `w
|
|
|
45
45
|
`@jgengine/core/world/place` (e.g. `{ id, ground: { mode: "flat", size: { x: Infinity, z: Infinity } }, physics: { gravity: -24 } }`,
|
|
46
46
|
or `mode: "board"` for 2D). Never seed, sky, or vegetation in `world` — the engine renders its
|
|
47
47
|
default sky until you author one in the editor, and foliage is editor scatter over the ground.
|
|
48
|
+
A created 3D game instead ships hills as a terrain sculpt in `editor.scene.json` and a `world.ts`
|
|
49
|
+
that consumes it with `environment({ sculpt })` via `environmentContentFromDocument`; the file
|
|
50
|
+
holds only the ground palette. Reshape the hills in the editor, not in code.
|
|
48
51
|
|
|
49
52
|
|
|
50
53
|
```ts
|
|
@@ -17,7 +17,7 @@ Every editor-visible object has an explicit provenance — `authored`, `generate
|
|
|
17
17
|
|
|
18
18
|
## Headless fast path
|
|
19
19
|
|
|
20
|
-
Inspect, mutate, and persist a game's scene in single commands — no GUI session and no reference reading needed for basic authoring:
|
|
20
|
+
Inspect, mutate, and persist a game's scene in single commands — no GUI session and no reference reading needed for basic authoring (monorepo):
|
|
21
21
|
|
|
22
22
|
```sh
|
|
23
23
|
bun packages/editor/src/mcp/cli.ts --game <id> --tools # verb inventory with descriptions
|
|
@@ -28,6 +28,8 @@ bun packages/editor/src/mcp/cli.ts --game <id> \
|
|
|
28
28
|
|
|
29
29
|
Repeat `--rpc` to batch several mutations on one session; `--save` then writes the document back to `Games/<id>/src/editor.scene.json` in the same format as the GUI's Ctrl+S, and a failed RPC aborts the batch before anything is saved.
|
|
30
30
|
|
|
31
|
+
That CLI exists only in the monorepo (`npx jgengine editor-mcp` says so). In a created project the same verbs run on the live page through the agent bridge: `bun run drive -- --rpc '{"method":"editor_summon"}' --rpc '<verb json>' --rpc '{"method":"save_scene"}'`. `editor_summon` resolves once the editor has mounted, so the verbs after it in the same batch reach it.
|
|
32
|
+
|
|
31
33
|
## Canonical workflow
|
|
32
34
|
|
|
33
35
|
1. Inspect the current scene and available editor capabilities.
|
|
@@ -61,9 +61,11 @@
|
|
|
61
61
|
- `EntityCatalogDocumentLike` (interface): interface EntityCatalogDocumentLike — Minimal document shape {@link entityEntryFromCatalog} reads — any `EditorDocument` satisfies it.
|
|
62
62
|
- `EnvironmentContent` (interface): interface EnvironmentContent — The coordinate/placement content of a world, derived from its scene document.
|
|
63
63
|
- `EnvironmentContentOptions` (interface): interface EnvironmentContentOptions extends ClearanceOptions — World-authoring convergence (#1018, epic #1006 Phase 4): derive the **coordinate/placement** content of an `environment()` world from the scene document, so a game with an authored document needs no coordinate arrays in `world.ts` — the remaining `world.ts` surface is engine tuning (noise, materials, sky preset, physics). Terrain footprint follows the authored objects, ground clearings come from authored spawns/POIs (`clearanceZonesFrom`), and the sculpt snapshot is the document's own terrain overlay. Pure and serializable; consumers pass the result straight to `environment({ terrain: terrain({ bounds }), clearings, sculpt })`.
|
|
64
|
+
- `EnvironmentSource` (type): type EnvironmentSource = | { kind: "gradient"; sky: string; ground: string; sun?: string; intensity?: number } /** Equirectangular HDR or EXR environment map loaded from `url`. */ | { kind: "hdri"; url: string; rotation?: number; intensity?: number } /** Six faces of a cube environment map, in three… — A declarative source for image-based scene lighting.
|
|
64
65
|
- `HudPanelTypeDef` (interface): interface HudPanelTypeDef — Declared panel type: growable axes, size limits, optional ParamSchema for the editor.
|
|
65
66
|
- `HudResizeAxes` (type): type HudResizeAxes = "none" | "x" | "y" | "both" — Which axes a panel type may grow when resized in canvas mode. Resize is semantic — content reflows (longer track, more rows) — never a CSS scale of the whole panel.
|
|
66
67
|
- `MaterializedInstance` (interface): interface MaterializedInstance — The deterministic materializer for scene {@link EditorDirective}s — the bake side of the bake/patch seam in #985. A directive is one authored line ("scatter rocks across the north ridge"); this expands it into many placements with **stable per-instance ids** (`<directiveId># <index>`) so a sparse overlay can hand-tweak or delete individual instances by id without every re-materialize orphaning those edits. Fully deterministic: same directive + seed + region ⇒ the same field, every time (safe for verify/CI). Built on the existing `scatter` primitive.
|
|
68
|
+
- `PointLightingConfig` (interface): interface PointLightingConfig — A bounded dynamic point light in world space.
|
|
67
69
|
- `RuntimeEntityState` (interface): interface RuntimeEntityState — One live entity row the runtime may stream to the editor (play-mode inspector feed).
|
|
68
70
|
- `RuntimeInspectorGetResult` (interface): interface RuntimeInspectorGetResult — One resolved runtime field returned by `runtime_get`.
|
|
69
71
|
- `RuntimeInspectorSetPlan` (interface): interface RuntimeInspectorSetPlan — Desired mutation from `runtime_set` before the host applies it.
|
|
@@ -130,6 +132,7 @@
|
|
|
130
132
|
- `importCsvGrid` (function): function importCsvGrid(text: string, options: CsvGridImportOptions): EditorGridLayer — Parses a CSV grid — one row per line, one value id per comma-separated field — into a grid layer. Blank fields become the empty value. Unlike ASCII this carries multi-character value ids directly, so it suits grids whose cell values are names rather than single glyphs.
|
|
131
133
|
- `inGridBounds` (function): function inGridBounds(layer: EditorGridLayer, col: number, row: number): boolean — True when `col,row` falls inside the layer's declared bounds.
|
|
132
134
|
- `installDocumentLiveSync` (function): function installDocumentLiveSync(sync: DocumentLiveSync): () => void — Publishes a live-sync bus globally so AuthoredScene / games can subscribe without prop drilling.
|
|
135
|
+
- `lightingFromDocument` (function): function lightingFromDocument(doc: EditorDocument): LightingConfig | undefined — Converts authored `light` markers into the runtime lighting contract.
|
|
133
136
|
- `loadWorldDocument` (function): function loadWorldDocument(manifest: WorldManifest, resolve: WorldShardResolver, query?: WorldQuery): EditorDocument — Loads the live neighborhood document for a query: reads each selected shard through `resolve`, applies its overlay (if any) on top, then merges them into one {@link EditorDocument} downstream consumers (`placeAuthoredObjects`, `collectAuthoredTriggers`, scatter, …) read unchanged. The monolith becomes an internal detail of the loader; a one-shard world yields exactly that shard.
|
|
134
137
|
- `materializeDirective` (function): function materializeDirective(doc: EditorDocument, directive: EditorDirective): MaterializedInstance[] — Materializes one directive against a document, resolving its footprint first. Returns an empty list when the region does not resolve.
|
|
135
138
|
- `materializeDirectives` (function): function materializeDirectives(doc: EditorDocument, overlays?: readonly EditorDirectiveOverlay[]): MaterializedInstance[] — Materializes every directive on a document into one flat instance list, applying each directive's overlay (matched by `over` === directive id) as it goes. The bulk-content counterpart to `resolveAuthoredObjects` / `resolveScatter`: games and headless tests read the same list.
|
|
@@ -197,6 +200,7 @@
|
|
|
197
200
|
- `EnvironmentContentOptions` (interface): interface EnvironmentContentOptions extends ClearanceOptions — World-authoring convergence (#1018, epic #1006 Phase 4): derive the **coordinate/placement** content of an `environment()` world from the scene document, so a game with an authored document needs no coordinate arrays in `world.ts` — the remaining `world.ts` surface is engine tuning (noise, materials, sky preset, physics). Terrain footprint follows the authored objects, ground clearings come from authored spawns/POIs (`clearanceZonesFrom`), and the sculpt snapshot is the document's own terrain overlay. Pure and serializable; consumers pass the result straight to `environment({ terrain: terrain({ bounds }), clearings, sculpt })`.
|
|
198
201
|
- `environmentContentFromDocument` (function): function environmentContentFromDocument(doc: EditorDocument, options: EnvironmentContentOptions = {}): EnvironmentContent — Derives the coordinate/placement content of an `environment()` world from its scene document: terrain footprint (via {@link terrainBoundsFromDocument}), ground clearings under authored spawns/POIs (via `clearanceZonesFrom`), and the document's sculpt snapshot. This is the seam that lets a game author its world footprint and flatten regions in the editor instead of hardcoding them — the `world.ts` that consumes it carries only engine tuning.
|
|
199
202
|
- `lakebedFromWaterVolumes` (function): function lakebedFromWaterVolumes(doc: EditorDocument): TerraformSnapshot | undefined — Derives a terrain-depression sculpt snapshot from the document's authored `water` volumes: each water box carves a lake bed that ramps from the shoreline down to below the box's bottom face, so an editor-authored pond/lake sits *in* the ground instead of floating as a sheet on top of it (and ground-sampled vegetation sinks below the surface rather than growing through it). Returns `undefined` when the document has no water volumes.
|
|
203
|
+
- `lightingFromDocument` (function): function lightingFromDocument(doc: EditorDocument): LightingConfig | undefined — Converts authored `light` markers into the runtime lighting contract.
|
|
200
204
|
- `skyFromDocument` (function): function skyFromDocument(doc: EditorDocument): SkyEnvironmentConfig | undefined — Maps the scene document's serializable environment bag onto the runtime sky config consumed by `sky()` / `environment({ sky })`. Returns `undefined` when the document has no environment field so callers can fall back to a world.ts default without inventing values.
|
|
201
205
|
- `terrainBoundsFromDocument` (function): function terrainBoundsFromDocument(doc: EditorDocument, options: EnvironmentContentOptions = {}): WorldBounds — The origin-centered terrain footprint that covers every authored object in a document, padded and floored to `minBounds`. An empty document yields exactly `minBounds`. Because `environment()` terrain is centered on the origin, the footprint is sized symmetrically to the farthest object on each axis, so no authored object falls off the ground.
|
|
202
206
|
|
|
@@ -291,6 +295,7 @@
|
|
|
291
295
|
|
|
292
296
|
## @jgengine/core/editor/types
|
|
293
297
|
|
|
298
|
+
- `EditorBake` (interface): interface EditorBake — A named baked artifact produced by an editor or build tool.
|
|
294
299
|
- `EditorCatalogData` (interface): interface EditorCatalogData — Persisted values for one gameplay data catalog (weapons, waves, economy, …). Schemas are not stored here — they come from the game's `editorCatalogs` export and drive SchemaInspector.
|
|
295
300
|
- `EditorCatalogDefinition` (interface): interface EditorCatalogDefinition — Game-exported catalog definition: a `ParamSchema` plus default entries. Schemas stay in code; entry values merge into `document.catalogs` and are what the editor/RPC edits and saves.
|
|
296
301
|
- `EditorCatalogEntry` (interface): interface EditorCatalogEntry — One row in a gameplay data catalog — id + optional label + a meta bag matching the catalog's `ParamSchema`. Values persist on the scene document; the schema lives in the game export.
|
|
@@ -322,6 +327,7 @@
|
|
|
322
327
|
- `EditorVolumeShape` (type): type EditorVolumeShape = "sphere" | "cylinder" | "box" — Collision shape a volume is rendered and tested as.
|
|
323
328
|
- `HudPanelTypeDef` (interface): interface HudPanelTypeDef — Declared panel type: growable axes, size limits, optional ParamSchema for the editor.
|
|
324
329
|
- `HudResizeAxes` (type): type HudResizeAxes = "none" | "x" | "y" | "both" — Which axes a panel type may grow when resized in canvas mode. Resize is semantic — content reflows (longer track, more rows) — never a CSS scale of the whole panel.
|
|
330
|
+
- `PointLightingConfig` (interface): interface PointLightingConfig — A bounded dynamic point light in world space.
|
|
325
331
|
- `WELL_KNOWN_MARKER_KINDS` (const): const WELL_KNOWN_MARKER_KINDS: readonly ["player_spawn", "mob", "boss", "vendor", "chest", "travel", "npc", "poi", "prop", "goal", "branch"] — Standard marker kinds recognized with default colors and behavior.
|
|
326
332
|
- `WELL_KNOWN_PATH_KINDS` (const): const WELL_KNOWN_PATH_KINDS: readonly ["road", "corridor", "branch", "route"] — Standard path kinds recognized with default colors and behavior.
|
|
327
333
|
- `WELL_KNOWN_VOLUME_KINDS` (const): const WELL_KNOWN_VOLUME_KINDS: readonly ["zone", "flatten", "cluster", "aggro", "leash", "discover", "capture", "prompt", "poi", "respawn_skip"] — Standard volume kinds recognized with default colors and behavior.
|
|
@@ -620,6 +626,11 @@
|
|
|
620
626
|
|
|
621
627
|
- `minimapHandlers` (const): const minimapHandlers: Pick<HandlerTable, "bake_minimap"> — Bake the authored terrain into a stored minimap PNG (#1036). Composes the live viewport's base ground field with the document's sculpt snapshot, rasterizes it top-down via the pure core bake, and stores `{ background, bounds }` on `document.minimap` as an undoable edit — runtime then feeds those straight into the `Minimap`/`WorldMap` props with no re-raster. Needs the mounted viewport's composed sampler, so it is a live-editor-only action, not a headless CLI verb.
|
|
622
628
|
|
|
629
|
+
## @jgengine/editor/handlers/navmesh
|
|
630
|
+
|
|
631
|
+
- `navMeshHandlers` (const): const navMeshHandlers: Pick<HandlerTable, "bakeNavMesh"> — Bake caller-provided indexed geometry into a named document navigation mesh.
|
|
632
|
+
- `warmNavBake` (function): function warmNavBake(): void — Start loading the recast module so the first bake request does not have to wait.
|
|
633
|
+
|
|
623
634
|
## @jgengine/editor/handlers/runtime
|
|
624
635
|
|
|
625
636
|
- `runtimeHandlers` (const): const runtimeHandlers: Pick< HandlerTable, | "push_document_patch" | "pull_document_patches" | "document_revision" | "push_runtime_delta" | "pull_runtime_deltas" | "runtime_snapshot" | "runtime_summary" | "runtime_get" | "runtime_set" | "runtime_pause" | "runtime_resume" | "runtime_step" | "set_runt… — Live-sync document patches, the ephemeral runtime reverse channel, and play-mode poke verbs.
|
|
@@ -698,6 +709,7 @@
|
|
|
698
709
|
|
|
699
710
|
## @jgengine/editor/modelAnimationAuthoring
|
|
700
711
|
|
|
712
|
+
- `AnimGraphSource` (type): type AnimGraphSource = "authored" | "locomotion" | "auto" — Where the graph a placement plays comes from.
|
|
701
713
|
- `AnimationMode` (type): type AnimationMode = "default" | "auto" | "none" | "custom" — Which authoring mode a stored setting represents. `default` = no override key.
|
|
702
714
|
- `AnimationSetting` (type): type AnimationSetting = AuthoredAnimationConfig | "auto" | "none" — The value stored at `meta.animation`.
|
|
703
715
|
- `AuthoredAnimationConfig` (interface): interface AuthoredAnimationConfig — Structurally compatible with `ModelAnimationConfig`, but every field optional for authoring.
|
|
@@ -709,12 +721,16 @@
|
|
|
709
721
|
- `OneShotEvent` (type): type OneShotEvent = (typeof ONE_SHOT_EVENTS)[number] — One-shot animation event a placement can bind a clip to (attack/hit/death/...).
|
|
710
722
|
- `animationMetaPatch` (function): function animationMetaPatch(setting: AnimationSetting | undefined): { animation: AnimationSetting | undefined } — The meta patch that persists a setting (or clears the override when undefined). Shallow-merges onto `marker.meta` via `setMarker`; an undefined value drops out of the saved JSON document.
|
|
711
723
|
- `animationMode` (function): function animationMode(setting: AnimationSetting | undefined): AnimationMode — The authoring mode a stored setting maps to.
|
|
724
|
+
- `clearAnimGraph` (function): function clearAnimGraph(setting: AnimationSetting | undefined): AnimationSetting | undefined — Removes a stored graph so `states`/`oneShots` (or clip roles) drive the placement again.
|
|
712
725
|
- `defaultCustomConfig` (function): function defaultCustomConfig(clips: readonly string[]): AuthoredAnimationConfig — A concrete custom config derived from a rigged asset's clip roles — the `custom` mode seed.
|
|
726
|
+
- `effectiveAnimGraph` (function): function effectiveAnimGraph(setting: AnimationSetting | undefined, clips: readonly string[]): { graph: AnimGraph; source: AnimGraphSource } | null — The graph a placement plays at run time: its stored `graph`, else the locomotion graph of its custom `states`/`oneShots`, else the one clip roles derive for `"auto"` and no-override placements. `null` for `"none"`, a single-clip config, or a rig whose clips have no idle.
|
|
713
727
|
- `readAnimationSetting` (function): function readAnimationSetting(meta: Record<string, unknown> | undefined): AnimationSetting | undefined — Reads and shape-validates the animation override from a marker's meta; undefined when absent/invalid.
|
|
714
728
|
- `setAnimationMode` (function): function setAnimationMode(setting: AnimationSetting | undefined, mode: AnimationMode, clips: readonly string[] = []): AnimationSetting | undefined — Switches authoring mode. `custom` seeds from the asset's clip-role defaults (so the user starts from a working config, then overrides) when there is no existing object config; the other modes are the bare string/undefined values.
|
|
715
729
|
- `setLocomotionClip` (function): function setLocomotionClip(setting: AnimationSetting | undefined, role: LocomotionRole, clipName: string | null): AuthoredAnimationConfig — Sets or clears (null) a locomotion state clip; forces the setting into `custom`.
|
|
716
730
|
- `setLocomotionNumber` (function): function setLocomotionNumber(setting: AnimationSetting | undefined, key: LocomotionNumber, value: number | null): AuthoredAnimationConfig — Sets or clears (null) a numeric locomotion tuning.
|
|
717
731
|
- `setOneShotClip` (function): function setOneShotClip(setting: AnimationSetting | undefined, event: string, clipName: string | null): AuthoredAnimationConfig — Binds or clears (null) a one-shot event to a clip.
|
|
732
|
+
- `setTransitionDuration` (function): function setTransitionDuration(setting: AnimationSetting | undefined, graph: AnimGraph, layerId: string, index: number, duration: number): AuthoredAnimationConfig — Sets one transition's crossfade seconds in `graph` and stores the result, so editing a derived graph turns it into an authored one.
|
|
733
|
+
- `storeAnimGraph` (function): function storeAnimGraph(setting: AnimationSetting | undefined, graph: AnimGraph): AuthoredAnimationConfig — Stores `graph` on the placement, keeping its other fields; the stored graph wins at play time.
|
|
718
734
|
|
|
719
735
|
## @jgengine/editor/networkSnapshot
|
|
720
736
|
|
|
@@ -810,6 +826,18 @@
|
|
|
810
826
|
- `WORKSPACES` (const): const WORKSPACES: readonly RailEntry[] — Rail order and support map. Unsupported modes are visible but disabled — never fake panels.
|
|
811
827
|
- `WorkspaceRail` (function): function WorkspaceRail({ active, onSelect, }: { active: EditorWorkspace; onSelect: (workspace: EditorWorkspace) => void; }): React.JSX.Element — Narrow left workspace rail. Supported modes activate their home panels; planned modes are disabled with an explanatory tooltip so nothing pretends to work.
|
|
812
828
|
|
|
829
|
+
## @jgengine/editor/shell/animGraphPreview
|
|
830
|
+
|
|
831
|
+
- `GraphParamControl` (interface): interface GraphParamControl — A parameter the preview needs a control for: blend inputs and condition operands.
|
|
832
|
+
- `GraphPreviewFrame` (interface): interface GraphPreviewFrame — What the rig shows at the scrub time.
|
|
833
|
+
- `GraphPreviewInput` (interface): interface GraphPreviewInput — Inputs for {@link simulateGraphPreview}.
|
|
834
|
+
- `MAX_PREVIEW_SECONDS` (const): const MAX_PREVIEW_SECONDS: 20 — Longest preview timeline the scrubber offers, in seconds.
|
|
835
|
+
- `graphClipNames` (function): function graphClipNames(graph: AnimGraph): string[] — Every clip name a graph plays.
|
|
836
|
+
- `graphParamControls` (function): function graphParamControls(graph: AnimGraph): GraphParamControl[] — Parameters a graph reads, with a range covering its blend points and condition values.
|
|
837
|
+
- `graphTriggers` (function): function graphTriggers(graph: AnimGraph): string[] — Every trigger name a graph's transitions listen for, in first-seen order.
|
|
838
|
+
- `recordTrigger` (function): function recordTrigger(triggers: readonly GraphPreviewTrigger[], name: string, at: number): GraphPreviewTrigger[] — Adds a trigger press at `at`, keeping the log in time order.
|
|
839
|
+
- `simulateGraphPreview` (function): function simulateGraphPreview(input: GraphPreviewInput): GraphPreviewFrame — Replays `graph` from its entry states to `time` and reports the pose there.
|
|
840
|
+
|
|
813
841
|
## @jgengine/editor/shell/cameraTelemetry
|
|
814
842
|
|
|
815
843
|
- `CameraTelemetry` (interface): interface CameraTelemetry — Per-frame camera orientation channel between the in-canvas probe and the DOM orientation widget. Deliberately a mutable record, not React state: the probe writes every frame and the widget reads on its own rAF loop, applying styles directly — zero shell rerenders.
|
|
@@ -73,7 +73,7 @@ bun packages/editor/src/mcp/cli.ts --game <id> \
|
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
- **Required:** `id`, `kind`, and `x`/`z` (`y` optional, defaults to `0`). A game reads its own custom kinds off the document (`editorLayers.markers.filter(m => m.kind === "stash")`), so no engine change is needed to introduce one.
|
|
76
|
-
- **Optional:** `color`, `label`, `rotationY`, `meta` — `meta` is validated against the kind's registered schema when one exists (custom kinds skip validation), same as `set_marker`.
|
|
76
|
+
- **Optional:** `color`, `label`, `rotationY`, `catalogId`, `meta` — `catalogId` is the entity kind a `mob`/`boss` marker spawns (without it the marker spawns nothing); `set_marker` patches it too. `meta` is validated against the kind's registered schema when one exists (custom kinds skip validation), same as `set_marker`.
|
|
77
77
|
- **Id collisions re-id** exactly as `add_path`; the response's `result` carries the id the marker landed under. Use `place_asset` instead when the marker should carry a mesh (it stamps `catalogId`/`meta.assetId`); `add_marker` is for logical, mesh-free markers.
|
|
78
78
|
|
|
79
79
|
### Click-to-place custom kinds in the GUI
|
|
@@ -93,6 +93,17 @@ export const STASH_KIND = definePlaceableMarkerKind({
|
|
|
93
93
|
- **Load path:** register from a module the editor loads. Importing your `editorKinds.ts` (side effect) from `editorLayers.ts` covers it — `loadGameLayers` imports `editorLayers.ts` for every editor session, and the game runtime imports it too, so one registration serves both.
|
|
94
94
|
- `fields` also gives `add_marker`/`set_marker`/`set_meta` a schema to validate that kind's `meta` against; omit `fields` for a bare placeable marker.
|
|
95
95
|
|
|
96
|
+
## Placement animation
|
|
97
|
+
|
|
98
|
+
A placed rigged asset's animation override lives at `marker.meta.animation` and reaches the game through `markerAnimation` → `ModelConfig.animation`. It is `"auto"`, `"none"` or a config with `states`, `oneShots` and an optional stored `graph` (an `AnimGraph`, validated with `parseAnimGraph` on read).
|
|
99
|
+
|
|
100
|
+
- **Inspector → Animation** picks the mode and binds idle/walk/run and one-shot clips.
|
|
101
|
+
- **Animation workspace → Graph** (rail button, or the bottom dock's Animation tab) shows the graph the selected placement plays: layers, states and transitions, with the source (stored, built from states, or derived from clip roles).
|
|
102
|
+
- The scrub slider replays the graph runtime from its entry states. Parameter sliders come from the graph's blend points and conditions.
|
|
103
|
+
- Trigger buttons record a press at the playhead, so scrubbing back and forth replays it. The rig at the camera focus is posed from the runtime's output through the shell's `createGraphPose`.
|
|
104
|
+
- Editing a crossfade, or **Store graph**, writes the graph to `meta.animation.graph` as one undoable edit. **Use derived graph** drops it.
|
|
105
|
+
- Scripted: `set_meta` with `{ "animation": { "graph": { ... } } }` on the marker; see the `jgengine-world` recipe `character-animation.md` for the graph shape.
|
|
106
|
+
|
|
96
107
|
## Pure API (`@jgengine/editor`)
|
|
97
108
|
|
|
98
109
|
```ts
|
|
@@ -213,8 +224,7 @@ undoable `setMinimapBake` command. Runtime feeds the stored `background`/`bounds
|
|
|
213
224
|
mounted). It is **not** a headless CLI/MCP verb: with no viewport the sampler is null and
|
|
214
225
|
`bake_minimap` returns `{ ok:false, error:"bake_minimap needs the live editor viewport" }`. To bake
|
|
215
226
|
a committed scene offline, run a deterministic node script that rebuilds the base field with
|
|
216
|
-
`groundFieldFor(world)` and calls `bakeMinimapFromDocument
|
|
217
|
-
`scripts/bake-claudecraft-minimap.ts`).
|
|
227
|
+
`groundFieldFor(world)` and calls `bakeMinimapFromDocument`.
|
|
218
228
|
- GUI: the Terrain panel's **Bake minimap** button calls `bake_minimap` and surfaces any `ok:false`
|
|
219
229
|
error inline.
|
|
220
230
|
- RPC/CLI verb: `bake_minimap` (optional `padding`, `resolution`, `waterLevel`). The bake path uses
|
|
@@ -11,7 +11,7 @@ Own the spatial realization of game design: player metrics, topology, routes, la
|
|
|
11
11
|
|
|
12
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
13
|
|
|
14
|
-
|
|
14
|
+
For a greenfield build, read [references/application-playbook.md](references/application-playbook.md) §1 and produce its metric sheet, topology graph, beat sheet, and encounter cards before art; §3–5 hold the templates. Audits may read only the playbook's audit sections. Read [references/live-editor-loop.md](references/live-editor-loop.md) when a separate editor agent or live editor session applies the changes, or when repairing an existing scene from captures. Read [references/field-guide.md](references/field-guide.md) for metric families, topology, pacing, genre lenses, accessibility, and research.
|
|
15
15
|
|
|
16
16
|
## Choose the mode
|
|
17
17
|
|