@vgai/engine 0.5.2 → 0.5.3
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/README.md +18 -11
- package/package.json +10 -6
- package/schemas/engine-api.json +1 -68
- package/schemas/engine-api.md +1 -32
- package/schemas/engine-capabilities.json +30 -42
- package/schemas/{vgai-game.schema.json → vgai-project.schema.json} +52 -34
- package/src/adapter/adapter-surface.ts +5 -5
- package/src/adapter/authoring.ts +168 -226
- package/src/adapter/colyseus-networking-adapter.ts +44 -5
- package/src/adapter/first-party-systems.ts +156 -42
- package/src/adapter/host-context.ts +177 -46
- package/src/adapter/index.ts +47 -51
- package/src/adapter/ingest/game-contract.ts +2 -2
- package/src/adapter/ingest/scene-capture.ts +18 -19
- package/src/adapter/ingest/structural-ids.ts +127 -0
- package/src/adapter/ingest/upstream-pin.ts +9 -12
- package/src/adapter/loop-gate-report.ts +11 -11
- package/src/adapter/rapier-physics-adapter.ts +27 -9
- package/src/adapter/root-adapter.ts +217 -0
- package/src/adapter/{vgai-scene-game-adapter.ts → setup-three-root-adapter.ts} +173 -351
- package/src/adapter/system-adapter.ts +80 -63
- package/src/ai/navigation.ts +1 -1
- package/src/animation/animation-clock.ts +1 -1
- package/src/animation/camera-ownership.ts +1 -2
- package/src/animation/cubic-spline-interpolant.ts +132 -0
- package/src/animation/theatre-clock-binding.ts +2 -2
- package/src/animation/theatre-object-binding.ts +4 -4
- package/src/animation/xstate-animation-binding.ts +75 -5
- package/src/{scene/schema → asset-formats}/camera.ts +2 -5
- package/src/{scene/schema → asset-formats}/collider.ts +2 -5
- package/src/asset-formats/index.ts +54 -0
- package/src/{scene/schema → asset-formats}/instances.ts +10 -6
- package/src/{scene/schema → asset-formats}/light.ts +3 -6
- package/src/{scene/schema → asset-formats}/material.ts +4 -7
- package/src/{scene/schema → asset-formats}/mesh.ts +4 -7
- package/src/asset-formats/parse.ts +39 -0
- package/src/{scene/schema → asset-formats}/particles.ts +3 -6
- package/src/{scene/schema/environment.ts → asset-formats/render-env.ts} +23 -86
- package/src/{scene/schema → asset-formats}/tuples.ts +1 -1
- package/src/{scene/asset-loaders.ts → asset-loaders.ts} +8 -9
- package/src/asset-parse-error.ts +33 -0
- package/src/{scene/asset-registry.ts → asset-registry.ts} +1 -1
- package/src/assets.ts +1 -1
- package/src/audio/wav-encode.ts +9 -9
- package/src/canvas-react/engine-bridge.ts +59 -0
- package/src/canvas-react/index.ts +50 -0
- package/src/canvas-react/pixi-primitive.tsx +202 -0
- package/src/canvas-react/pixi-react-adapter.tsx +290 -0
- package/src/canvas-react/pixi-react-root-factory.tsx +88 -0
- package/src/canvas-react/world-context.ts +328 -0
- package/src/core/frame-pacing.ts +100 -0
- package/src/core/game-loop.ts +50 -28
- package/src/core/seeded-random.ts +7 -7
- package/src/core/sim-clock.ts +388 -0
- package/src/core/system-runner.ts +17 -63
- package/src/core/types.ts +34 -15
- package/src/data/data-asset.ts +3 -3
- package/src/data/data-check-core.ts +6 -7
- package/src/data/data-ref.ts +11 -11
- package/src/data/vite-plugin-data.ts +10 -10
- package/src/{scene/defaults.ts → defaults.ts} +18 -40
- package/src/dev/render-debug-adapter.ts +1 -1
- package/src/dev/webgl-frame-capture.ts +1 -1
- package/src/ecs/scene-index.ts +439 -0
- package/src/ecs/scene-query.ts +43 -0
- package/src/{scene → ecs}/user-data.ts +17 -36
- package/src/index.ts +7 -9
- package/src/input/input-manager.ts +29 -32
- package/src/input/input-types.ts +2 -2
- package/src/input/schema.ts +5 -5
- package/src/loader.ts +57 -0
- package/src/manifest/editor-port.ts +69 -0
- package/src/manifest/filename.ts +49 -0
- package/src/manifest/index.ts +8 -2
- package/src/manifest/load-file.ts +11 -0
- package/src/manifest/load.ts +65 -77
- package/src/manifest/locate.ts +55 -0
- package/src/manifest/schema.ts +400 -233
- package/src/{scene → physics}/collider-dimensions.ts +3 -3
- package/src/physics/physics-registry.ts +1 -1
- package/src/{world2d/authoring-2d.ts → pixi/authoring.ts} +24 -11
- package/src/pixi/index.ts +43 -0
- package/src/{world2d/ingest-iframe-2d.ts → pixi/ingest-iframe.ts} +9 -9
- package/src/{world2d/ingest2d.ts → pixi/ingest.ts} +28 -28
- package/src/{world2d/physics2d-registry.ts → pixi/physics-registry.ts} +1 -1
- package/src/{world2d/scene-capture-2d.ts → pixi/scene-capture.ts} +3 -3
- package/src/{world2d/system-adapters-2d.ts → pixi/system-adapters.ts} +2 -2
- package/src/react/unmanaged-root-detector.ts +26 -1
- package/src/react/use-data.ts +5 -5
- package/src/react/use-selection.tsx +15 -42
- package/src/react/{game-state.tsx → world-state.tsx} +44 -46
- package/src/render/auto-batcher.ts +1 -2
- package/src/{scene → render}/instance-mesh.ts +1 -1
- package/src/{scene → render}/light-camera-factory.ts +14 -13
- package/src/render/lod.ts +17 -0
- package/src/{scene → render}/material-factory.ts +8 -7
- package/src/{scene → render}/particles-factory.ts +62 -12
- package/src/render/render-batch-system.ts +14 -41
- package/src/render/render-features.ts +1 -1
- package/src/render/render-settings.ts +1 -2
- package/src/render/spark-renderer-lifecycle.ts +1 -1
- package/src/runtime/create-runtime.ts +352 -463
- package/src/runtime/debug-bridge.ts +148 -93
- package/src/runtime/debug-registry.ts +79 -54
- package/src/runtime/dev-layers.ts +40 -0
- package/src/runtime/frame-selector-cache.ts +4 -4
- package/src/runtime/game.ts +618 -369
- package/src/runtime/gameplay-rng-trap.ts +6 -7
- package/src/runtime/input-router.ts +11 -11
- package/src/runtime/mount-game.ts +54 -55
- package/src/runtime/mount-manifest.ts +154 -150
- package/src/runtime/presentation.ts +141 -0
- package/src/runtime/render-audio-control.ts +64 -53
- package/src/runtime/render-control.ts +45 -51
- package/src/runtime/render-seed.ts +3 -4
- package/src/runtime/state-bridge.ts +17 -18
- package/src/runtime/types.ts +94 -61
- package/src/setup/setup-renderer.ts +11 -6
- package/src/world3d-react/engine-bridge.ts +46 -33
- package/src/world3d-react/index.ts +31 -26
- package/src/world3d-react/r3f-adapter.tsx +211 -96
- package/src/world3d-react/r3f-root-factory.tsx +91 -0
- package/src/world3d-react/renderer-config.ts +137 -0
- package/src/world3d-react/world-context.ts +141 -111
- package/schemas/entity2d.schema.json +0 -468
- package/schemas/prefab.schema.json +0 -9992
- package/schemas/scn2d.schema.json +0 -494
- package/schemas/vscn.schema.json +0 -10851
- package/src/adapter/game-adapter.ts +0 -164
- package/src/adapter/ingest/overlay-applier.ts +0 -207
- package/src/adapter/ingest/overlay-apply.ts +0 -168
- package/src/adapter/ingest/overlay-file.ts +0 -126
- package/src/adapter/ingest/overlay-report.ts +0 -176
- package/src/animation/gsap-registration.ts +0 -184
- package/src/audio/audio-introspection.ts +0 -290
- package/src/audio/index.ts +0 -39
- package/src/audio/tone-clock-binding.ts +0 -98
- package/src/audio/tone-context.ts +0 -175
- package/src/audio/tone-offline-render.ts +0 -167
- package/src/ecs/component-manager.ts +0 -814
- package/src/ecs/game-component.ts +0 -260
- package/src/ecs/hmr-swap-report.ts +0 -65
- package/src/physics/trigger-dispatch.ts +0 -97
- package/src/react/root-adapter.tsx +0 -49
- package/src/scene/asset-paths.ts +0 -121
- package/src/scene/asset-ref-check.ts +0 -248
- package/src/scene/component-registry.ts +0 -51
- package/src/scene/parse.ts +0 -204
- package/src/scene/scene-apply.ts +0 -407
- package/src/scene/scene-diff-schema.ts +0 -115
- package/src/scene/scene-diff-types.ts +0 -29
- package/src/scene/scene-loader.ts +0 -1526
- package/src/scene/scene-query.ts +0 -63
- package/src/scene/scene-types.ts +0 -33
- package/src/scene/scene-version.ts +0 -40
- package/src/scene/schema/animation.ts +0 -46
- package/src/scene/schema/audio.ts +0 -25
- package/src/scene/schema/entity-ref.ts +0 -78
- package/src/scene/schema/entity.ts +0 -189
- package/src/scene/schema/index.ts +0 -51
- package/src/scene/schema/joint.ts +0 -26
- package/src/scene/schema/physics.ts +0 -49
- package/src/scene/schema/scene-file.ts +0 -292
- package/src/scene/schema/shadow.ts +0 -24
- package/src/scene/schema/spline.ts +0 -21
- package/src/world2d/asset-paths2d.ts +0 -44
- package/src/world2d/capture-to-scene2d.ts +0 -52
- package/src/world2d/collision-2d.ts +0 -99
- package/src/world2d/entity2d-asset.ts +0 -22
- package/src/world2d/index.ts +0 -91
- package/src/world2d/physics2d-transform.ts +0 -173
- package/src/world2d/physics2d-units.ts +0 -10
- package/src/world2d/pixi-game-adapter.ts +0 -439
- package/src/world2d/pixi-surface.ts +0 -78
- package/src/world2d/scene2d-identity.ts +0 -49
- package/src/world2d/scene2d-loader.ts +0 -433
- package/src/world2d/schema/entity2d.ts +0 -163
- package/src/world2d/schema/physics2d.ts +0 -64
- package/src/world2d/schema/sprite.ts +0 -99
- package/src/world2d/schema/tilemap.ts +0 -39
- package/src/world2d/schema/tuples2d.ts +0 -25
- package/src/world2d/transform-writer-2d.ts +0 -42
- package/src/world2d/types.ts +0 -74
- package/src/world3d-react/behavior.tsx +0 -146
- /package/src/{scene → render}/mesh-shadow.ts +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* `
|
|
5
|
-
* `
|
|
6
|
-
*
|
|
7
|
-
* SEE in source; this trap catches what the scan structurally can't: a
|
|
2
|
+
* The dev-mode `Math.random` phase trap (enforcer 3, T-D15.3). A project that
|
|
3
|
+
* declares `determinism.seededRandom` is claiming ALL gameplay RNG flows
|
|
4
|
+
* through `ctx.random` — the burn-down scan (`test/gameplay-rng-ban.test.ts`)
|
|
5
|
+
* catches raw `Math.random()`/`Date.now()`/`performance.now()` call sites it
|
|
6
|
+
* can SEE in source; this trap catches what the scan structurally can't: a
|
|
8
7
|
* TRANSITIVE draw made by a third-party library the game calls into during a
|
|
9
8
|
* gameplay tick.
|
|
10
9
|
*
|
|
@@ -69,7 +68,7 @@ export function createGameplayRngTrap(
|
|
|
69
68
|
// this warning STRING would otherwise false-positive against itself.
|
|
70
69
|
'[determinism] the global Math.random generator was drawn from during a gameplay frame ' +
|
|
71
70
|
'while this project declares determinism.seededRandom — use ctx.random() / ' +
|
|
72
|
-
`ctx.random.stream(name) instead
|
|
71
|
+
`ctx.random.stream(name) instead. Call site:\n${site}`,
|
|
73
72
|
);
|
|
74
73
|
}
|
|
75
74
|
// `previous` is always set by the time `trapped` can run — `enable()`
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The delegating input router (
|
|
3
|
-
* `createGameRuntime`'s roots path (T6.1 slice 1
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* The delegating input router (D5 §2a) —
|
|
3
|
+
* `createGameRuntime`'s roots path (T6.1 slice 1) uses this to route
|
|
4
|
+
* pointer input across N stacked world canvases with exactly ONE root
|
|
5
|
+
* listener.
|
|
6
6
|
*
|
|
7
7
|
* Split into two layers so the decision logic is unit-testable with plain
|
|
8
8
|
* fake roots — no real DOM/canvas needed:
|
|
9
9
|
*
|
|
10
|
-
* - `stackOrder` / `
|
|
10
|
+
* - `stackOrder` / `resolveClaimingRoot`: pure functions over
|
|
11
11
|
* `{id, zOrder, hitTest?}` — "who claims this point".
|
|
12
12
|
* - `applyPointerEventsStacking` / `createInputRouter`: the DOM wiring —
|
|
13
13
|
* sets `pointer-events` CSS per D5 §2a and forwards a claimed event to
|
|
14
14
|
* the claiming world's own canvas.
|
|
15
15
|
*
|
|
16
16
|
* Per-event fall-through (D5 §2b — the sanctioned mechanism for an
|
|
17
|
-
* authoring surface's own interior drag affordances, e.g.
|
|
18
|
-
* editor's gizmos) is explicitly NOT this file's job
|
|
19
|
-
*
|
|
17
|
+
* authoring surface's own interior drag affordances, e.g. a canvas
|
|
18
|
+
* editor's gizmos) is explicitly NOT this file's job — it stays inside
|
|
19
|
+
* whatever authoring surface needs it.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
/** The pure decision inputs — no DOM. */
|
|
@@ -59,7 +59,7 @@ export function stackOrder<T extends ClaimEntry>(entries: readonly T[]): T[] {
|
|
|
59
59
|
* (or via its own `hitTest`, if it declares one) — "no-claim falls to
|
|
60
60
|
* bottom". Returns `null` only when `entries` is empty.
|
|
61
61
|
*/
|
|
62
|
-
export function
|
|
62
|
+
export function resolveClaimingRoot(
|
|
63
63
|
entries: readonly ClaimEntry[],
|
|
64
64
|
x: number,
|
|
65
65
|
y: number,
|
|
@@ -191,7 +191,7 @@ export function createInputRouter(
|
|
|
191
191
|
const clientY = (evt as unknown as { clientY?: number }).clientY ?? 0;
|
|
192
192
|
const x = clientX - rect.left;
|
|
193
193
|
const y = clientY - rect.top;
|
|
194
|
-
const claimant =
|
|
194
|
+
const claimant = resolveClaimingRoot(entries, x, y);
|
|
195
195
|
if (claimant && claimant !== bottomId) {
|
|
196
196
|
const entry = byId.get(claimant);
|
|
197
197
|
if (entry) forwardEvent(entry.canvas, evt);
|
|
@@ -203,7 +203,7 @@ export function createInputRouter(
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
return {
|
|
206
|
-
resolveClaim: (x, y) =>
|
|
206
|
+
resolveClaim: (x, y) => resolveClaimingRoot(entries, x, y),
|
|
207
207
|
dispose() {
|
|
208
208
|
for (const type of ROUTED_EVENT_TYPES) {
|
|
209
209
|
container.removeEventListener?.(type, handler, true);
|
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// and then mounts with a single `mountGameFromManifest(manifest, host)` call.
|
|
1
|
+
// The S-D composer (design lineage Stage S-D). Builds ON `mount-manifest.ts`'s
|
|
2
|
+
// `mountManifestRoots` (never duplicates its per-kind dispatch/validation) to add
|
|
3
|
+
// the one thing that module deliberately does NOT have: a KIND REGISTRY, so a
|
|
4
|
+
// project doesn't have to hand-build an `entries` map inline in its own `main.ts`
|
|
5
|
+
// every time — it registers a `AdapterSurfaceFactory` per kind it uses (once, at
|
|
6
|
+
// module load) and then mounts with a single `mountGameFromManifest(manifest,
|
|
7
|
+
// host)` call.
|
|
9
8
|
//
|
|
10
9
|
// Engine-core react/pixi-free discipline (mirrors `mount-manifest.ts`'s own
|
|
11
10
|
// header comment, and the HARD INVARIANT this file was built under): this
|
|
12
11
|
// registry is pure mechanism — it holds whatever `AdapterSurfaceFactory` functions
|
|
13
12
|
// callers register, but it registers NONE itself. In particular there is no
|
|
14
|
-
// built-in '
|
|
13
|
+
// built-in 'canvas'/'react' registration here (that would require this file
|
|
15
14
|
// to value-import `pixi.js`/`react`/`react-dom`, exactly what `mount-manifest
|
|
16
|
-
// .ts` forbids); a project that has a
|
|
15
|
+
// .ts` forbids); a project that has a canvas or react world MUST register a
|
|
17
16
|
// factory for that kind itself — see `defaultThreeAdapterFactory` below for why
|
|
18
|
-
// even the '
|
|
17
|
+
// even the 'three' convenience export is a plain function the CALLER
|
|
19
18
|
// registers, not something this module wires up automatically.
|
|
20
19
|
|
|
21
|
-
import type {
|
|
20
|
+
import type { RootAdapter } from '../adapter/root-adapter';
|
|
22
21
|
import type { ResolvedAdapterRoot } from '../manifest/load';
|
|
23
|
-
import type { ComponentRegistry } from '../scene/component-registry';
|
|
24
22
|
import type { GameSession } from './create-runtime';
|
|
25
|
-
import { type MountEntry,
|
|
23
|
+
import { type MountEntry, mountManifestRoots, resolveManifest } from './mount-manifest';
|
|
26
24
|
import type { GameSetupFn } from './types';
|
|
27
25
|
|
|
28
26
|
// ---------------------------------------------------------------------------
|
|
@@ -37,7 +35,7 @@ import type { GameSetupFn } from './types';
|
|
|
37
35
|
*/
|
|
38
36
|
export interface ManifestHost {
|
|
39
37
|
/** The host creates one absolutely-positioned surface per world inside
|
|
40
|
-
* this element — see `
|
|
38
|
+
* this element — see `RootsRuntimeConfig.container`. */
|
|
41
39
|
readonly container: HTMLElement;
|
|
42
40
|
/**
|
|
43
41
|
* Resolve a manifest-declared `entry` (a project-relative module path,
|
|
@@ -62,7 +60,7 @@ export interface ManifestHost {
|
|
|
62
60
|
readonly width?: number | undefined;
|
|
63
61
|
readonly height?: number | undefined;
|
|
64
62
|
/** Forwarded to `createGameRuntime` — Node/headless test harnesses only,
|
|
65
|
-
* never a real host. See `
|
|
63
|
+
* never a real host. See `RootsRuntimeConfig.headless`. */
|
|
66
64
|
readonly headless?: boolean | undefined;
|
|
67
65
|
}
|
|
68
66
|
|
|
@@ -80,7 +78,7 @@ export interface AdapterSurfaceFactoryContext {
|
|
|
80
78
|
/**
|
|
81
79
|
* A caller-registered per-kind mount strategy: given the world's resolved
|
|
82
80
|
* manifest entry and the loaded entry module (if any), produce the
|
|
83
|
-
* `MountEntry` `
|
|
81
|
+
* `MountEntry` `mountManifestRoots` needs to mount it (exactly what a
|
|
84
82
|
* project used to hand-build inline as its own `entries[id]` — see
|
|
85
83
|
* `examples/tri-world/src/main.ts`'s pre-E4 shape). May be async (loading an
|
|
86
84
|
* asset, fetching a scene file, etc.).
|
|
@@ -97,8 +95,8 @@ export type AdapterSurfaceFactory = (
|
|
|
97
95
|
const registry = new Map<string, AdapterSurfaceFactory>();
|
|
98
96
|
|
|
99
97
|
/**
|
|
100
|
-
* Register a `AdapterSurfaceFactory` for a manifest world `kind` (`'
|
|
101
|
-
* `'
|
|
98
|
+
* Register a `AdapterSurfaceFactory` for a manifest world `kind` (`'three'` /
|
|
99
|
+
* `'canvas'` / `'react'`, or any future kind the manifest schema grows).
|
|
102
100
|
* Call once, at module load — mirrors `registerSceneUIRenderer()`'s existing
|
|
103
101
|
* "call before mounting" convention (`packages/editor/template/src/main.ts`).
|
|
104
102
|
*
|
|
@@ -148,33 +146,29 @@ export function __clearAdapterSurfaceRegistryForTests(): void {
|
|
|
148
146
|
* (an explicit world entry module, including `examples/*` projects'
|
|
149
147
|
* `src/index.ts` — see CLAUDE.md's "Adding an example project"). */
|
|
150
148
|
interface ThreeEntryModuleExports {
|
|
151
|
-
readonly adapter?:
|
|
149
|
+
readonly adapter?: RootAdapter;
|
|
152
150
|
readonly setup?: GameSetupFn;
|
|
153
|
-
readonly componentRegistry?: ComponentRegistry;
|
|
154
151
|
}
|
|
155
152
|
|
|
156
153
|
/**
|
|
157
|
-
* A ready-to-register {@link AdapterSurfaceFactory} for `kind: '
|
|
154
|
+
* A ready-to-register {@link AdapterSurfaceFactory} for `kind: 'three'` roots
|
|
158
155
|
* that follow the first-party entry-module convention (`export const
|
|
159
|
-
* adapter` and/or `export async function setup`)
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* `VgaiSceneGameAdapter` are already unconditional engine dependencies —
|
|
156
|
+
* adapter` and/or `export async function setup`). Threejs is safe to
|
|
157
|
+
* ship as an exported convenience (unlike canvas/react) because `three`/
|
|
158
|
+
* `SetupThreeRootAdapter` are already unconditional engine dependencies —
|
|
163
159
|
* see `mount-manifest.ts`'s header comment. Still never auto-registered:
|
|
164
160
|
* the registry itself stays zero-policy (see this file's header comment) —
|
|
165
|
-
* a caller opts in with `registerAdapter('
|
|
161
|
+
* a caller opts in with `registerAdapter('three', defaultThreeAdapterFactory)`.
|
|
166
162
|
*
|
|
167
163
|
* Resolution mirrors `mount-manifest.ts`'s own `resolveThreeAdapter` branch
|
|
168
164
|
* order: an entry module's `adapter` export wins outright; else its `setup`
|
|
169
|
-
* export (wrapping via `fromSetup` happens inside `
|
|
170
|
-
* itself — this factory just returns the `MountEntry` shape)
|
|
171
|
-
* `entry` at all) a scene-driven world, forwarding `componentRegistry` if
|
|
172
|
-
* the entry module supplied one.
|
|
165
|
+
* export (wrapping via `fromSetup` happens inside `mountManifestRoots`
|
|
166
|
+
* itself — this factory just returns the `MountEntry` shape).
|
|
173
167
|
*/
|
|
174
168
|
export const defaultThreeAdapterFactory: AdapterSurfaceFactory = (world, ctx) => {
|
|
175
169
|
const mod = ctx.entryModule as ThreeEntryModuleExports | undefined;
|
|
176
|
-
if (mod?.adapter) return { kind: '
|
|
177
|
-
if (mod?.setup) return { kind: '
|
|
170
|
+
if (mod?.adapter) return { kind: 'three', adapter: mod.adapter };
|
|
171
|
+
if (mod?.setup) return { kind: 'three', setup: mod.setup };
|
|
178
172
|
if (world.entry !== undefined) {
|
|
179
173
|
throw new Error(
|
|
180
174
|
`defaultThreeAdapterFactory: entry module "${world.entry}" for world "${world.id}" exports ` +
|
|
@@ -182,7 +176,10 @@ export const defaultThreeAdapterFactory: AdapterSurfaceFactory = (world, ctx) =>
|
|
|
182
176
|
'(export one from the declared entry module).',
|
|
183
177
|
);
|
|
184
178
|
}
|
|
185
|
-
|
|
179
|
+
throw new Error(
|
|
180
|
+
`defaultThreeAdapterFactory: world "${world.id}" declares no \`entry\` — a three root is ` +
|
|
181
|
+
'authored as a TSX/R3F world module; point `entry` at it.',
|
|
182
|
+
);
|
|
186
183
|
};
|
|
187
184
|
|
|
188
185
|
// ---------------------------------------------------------------------------
|
|
@@ -190,30 +187,32 @@ export const defaultThreeAdapterFactory: AdapterSurfaceFactory = (world, ctx) =>
|
|
|
190
187
|
// ---------------------------------------------------------------------------
|
|
191
188
|
|
|
192
189
|
export interface MountGameOptions {
|
|
193
|
-
/** Explicit per-world entries, same shape `
|
|
190
|
+
/** Explicit per-world entries, same shape `mountManifestRoots` accepts —
|
|
194
191
|
* ALWAYS wins over a registered kind factory for that world id (backward
|
|
195
192
|
* compat: a caller mid-migration, or one that just prefers building one
|
|
196
193
|
* entry by hand, never has to touch the registry at all). */
|
|
197
194
|
readonly entries?: Readonly<Record<string, MountEntry>> | undefined;
|
|
198
195
|
}
|
|
199
196
|
|
|
200
|
-
/** True for the one shape `
|
|
201
|
-
* `entries[id]` at all
|
|
202
|
-
*
|
|
203
|
-
* nothing
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
197
|
+
/** True for the one shape `mountManifestRoots` can ALREADY mount with zero
|
|
198
|
+
* `entries[id]` at all.
|
|
199
|
+
*
|
|
200
|
+
* WO-8: nothing is self-sufficient any more. The one shape that was — a plain
|
|
201
|
+
* `default`-adapter, SCENE-driven, no-`entry` three world, which
|
|
202
|
+
* `resolveThreeAdapter`'s scene branch could mount from the manifest alone —
|
|
203
|
+
* died with the `.vscn.json` format. `load.ts` now rejects a three root with no
|
|
204
|
+
* `entry` outright, so every world needs a registered factory or an explicit
|
|
205
|
+
* entry, and this predicate is retained only to keep the loud-degrade error the
|
|
206
|
+
* documented outcome rather than a silent skip. */
|
|
207
|
+
function worldIsSelfSufficient(_world: ResolvedAdapterRoot): boolean {
|
|
208
|
+
return false;
|
|
210
209
|
}
|
|
211
210
|
|
|
212
211
|
/**
|
|
213
|
-
* Mount every world declared by a `vgai.
|
|
212
|
+
* Mount every world declared by a `vgai.project.json` manifest onto `host
|
|
214
213
|
* .container`, resolving each world's kind through the `registerAdapter`
|
|
215
214
|
* registry — falling back to an explicit `opts.entries[id]` where supplied,
|
|
216
|
-
* exactly like `
|
|
215
|
+
* exactly like `mountManifestRoots` (so a caller can migrate one world at a
|
|
217
216
|
* time, or never touch the registry if it prefers hand-building entries).
|
|
218
217
|
*
|
|
219
218
|
* This is the "one call" scaffold/example projects mount through (E4
|
|
@@ -222,11 +221,11 @@ function worldIsSelfSufficient(world: ResolvedAdapterRoot): boolean {
|
|
|
222
221
|
* `packages/editor/template/src/main.ts` for the worked single-world
|
|
223
222
|
* example and `examples/tri-world/src/main.ts` for a multi-kind one.
|
|
224
223
|
*
|
|
225
|
-
* Degrades loudly (
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
224
|
+
* Degrades loudly (carried into E4): a world whose kind has no registered
|
|
225
|
+
* factory AND no explicit entry, and which cannot self-mount from the
|
|
226
|
+
* manifest alone, throws a named `Error` identifying the world id + kind and
|
|
227
|
+
* BOTH ways to fix it (`registerAdapter` or `opts.entries`) — never a silent
|
|
228
|
+
* skip.
|
|
230
229
|
*/
|
|
231
230
|
export async function mountGameFromManifest(
|
|
232
231
|
manifestInput: unknown,
|
|
@@ -249,18 +248,18 @@ export async function mountGameFromManifest(
|
|
|
249
248
|
continue;
|
|
250
249
|
}
|
|
251
250
|
|
|
252
|
-
if (worldIsSelfSufficient(world)) continue; //
|
|
251
|
+
if (worldIsSelfSufficient(world)) continue; // mountManifestRoots needs nothing further
|
|
253
252
|
|
|
254
253
|
throw new Error(
|
|
255
254
|
`mountGameFromManifest: root "${world.id}" (adapter "${world.adapter.identity}") has no registered ` +
|
|
256
255
|
`adapter factory and no explicit entries["${world.id}"] — call ` +
|
|
257
256
|
`registerAdapter("${world.adapter.identity}", factory) before mounting (see ` +
|
|
258
|
-
'`defaultThreeAdapterFactory` for a worked
|
|
257
|
+
'`defaultThreeAdapterFactory` for a worked three example), or pass ' +
|
|
259
258
|
`opts.entries["${world.id}"] directly (see mount-manifest.ts's \`MountEntry\`).`,
|
|
260
259
|
);
|
|
261
260
|
}
|
|
262
261
|
|
|
263
|
-
return
|
|
262
|
+
return mountManifestRoots({
|
|
264
263
|
manifest,
|
|
265
264
|
container: host.container,
|
|
266
265
|
entries,
|