@vgai/engine 0.5.21 → 0.5.22

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.
Files changed (87) hide show
  1. package/dist/adapter/manifest-interpreter.d.ts +59 -0
  2. package/dist/adapter/manifest-interpreter.d.ts.map +1 -0
  3. package/dist/adapter/manifest-interpreter.js +50 -0
  4. package/dist/adapter/native-debug-module.d.ts +45 -3
  5. package/dist/adapter/native-debug-module.d.ts.map +1 -1
  6. package/dist/adapter/native-debug-module.js +128 -10
  7. package/dist/adapter/renderer-config.d.ts +1 -1
  8. package/dist/adapter/renderer-config.js +1 -1
  9. package/dist/canvas-react/index.d.ts +5 -12
  10. package/dist/canvas-react/index.d.ts.map +1 -1
  11. package/dist/canvas-react/index.js +5 -12
  12. package/dist/canvas-react/pixi-react-root-factory.d.ts +34 -21
  13. package/dist/canvas-react/pixi-react-root-factory.d.ts.map +1 -1
  14. package/dist/canvas-react/pixi-react-root-factory.js +274 -36
  15. package/dist/core/countdown-timer.d.ts +118 -0
  16. package/dist/core/countdown-timer.d.ts.map +1 -0
  17. package/dist/core/countdown-timer.js +137 -0
  18. package/dist/core/deferred-commands.d.ts +127 -0
  19. package/dist/core/deferred-commands.d.ts.map +1 -0
  20. package/dist/core/deferred-commands.js +132 -0
  21. package/dist/core/sim-clock.d.ts +14 -2
  22. package/dist/core/sim-clock.d.ts.map +1 -1
  23. package/dist/core/sim-clock.js +14 -2
  24. package/dist/dev/instruments.d.ts +38 -11
  25. package/dist/dev/instruments.d.ts.map +1 -1
  26. package/dist/dev/instruments.js +81 -11
  27. package/dist/input/input-manager.d.ts +15 -0
  28. package/dist/input/input-manager.d.ts.map +1 -1
  29. package/dist/input/input-manager.js +15 -0
  30. package/dist/render/directional-shadow-fit.d.ts +88 -0
  31. package/dist/render/directional-shadow-fit.d.ts.map +1 -0
  32. package/dist/render/directional-shadow-fit.js +133 -0
  33. package/dist/render/environment-capture.d.ts +68 -0
  34. package/dist/render/environment-capture.d.ts.map +1 -0
  35. package/dist/render/environment-capture.js +90 -0
  36. package/dist/render/ibl-override-material.d.ts +97 -0
  37. package/dist/render/ibl-override-material.d.ts.map +1 -0
  38. package/dist/render/ibl-override-material.js +114 -0
  39. package/dist/runtime/game-input-seams.d.ts +51 -0
  40. package/dist/runtime/game-input-seams.d.ts.map +1 -0
  41. package/dist/runtime/game-input-seams.js +86 -0
  42. package/dist/runtime/game.d.ts +15 -0
  43. package/dist/runtime/game.d.ts.map +1 -1
  44. package/dist/runtime/game.js +40 -8
  45. package/dist/runtime/mount-game.d.ts.map +1 -1
  46. package/dist/runtime/mount-game.js +18 -2
  47. package/dist/runtime/mount-manifest.d.ts.map +1 -1
  48. package/dist/runtime/mount-manifest.js +4 -2
  49. package/dist/runtime/types.d.ts +1 -1
  50. package/dist/world3d-react/index.d.ts +15 -25
  51. package/dist/world3d-react/index.d.ts.map +1 -1
  52. package/dist/world3d-react/index.js +15 -25
  53. package/dist/world3d-react/r3f-root-factory.d.ts +19 -25
  54. package/dist/world3d-react/r3f-root-factory.d.ts.map +1 -1
  55. package/dist/world3d-react/r3f-root-factory.js +396 -50
  56. package/dist/world3d-react/rapier-physics-bridge.d.ts +24 -12
  57. package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -1
  58. package/dist/world3d-react/rapier-physics-bridge.js +82 -49
  59. package/package.json +1 -1
  60. package/schemas/engine-capabilities.json +3 -3
  61. package/src/adapter/manifest-interpreter.ts +64 -0
  62. package/src/adapter/native-debug-module.ts +212 -15
  63. package/src/adapter/renderer-config.ts +1 -1
  64. package/src/canvas-react/index.ts +5 -21
  65. package/src/canvas-react/pixi-react-root-factory.tsx +301 -39
  66. package/src/core/countdown-timer.ts +188 -0
  67. package/src/core/deferred-commands.ts +174 -0
  68. package/src/core/sim-clock.ts +14 -2
  69. package/src/dev/instruments.ts +108 -11
  70. package/src/input/input-manager.ts +15 -0
  71. package/src/render/directional-shadow-fit.ts +156 -0
  72. package/src/render/environment-capture.ts +102 -0
  73. package/src/render/ibl-override-material.ts +170 -0
  74. package/src/runtime/game-input-seams.ts +108 -0
  75. package/src/runtime/game.ts +65 -7
  76. package/src/runtime/mount-game.ts +23 -1
  77. package/src/runtime/mount-manifest.ts +4 -2
  78. package/src/runtime/types.ts +1 -1
  79. package/src/world3d-react/index.ts +15 -31
  80. package/src/world3d-react/r3f-root-factory.tsx +444 -53
  81. package/src/world3d-react/rapier-physics-bridge.tsx +88 -49
  82. package/src/canvas-react/engine-bridge.ts +0 -59
  83. package/src/canvas-react/pixi-react-adapter.tsx +0 -356
  84. package/src/canvas-react/world-context.ts +0 -253
  85. package/src/world3d-react/engine-bridge.ts +0 -86
  86. package/src/world3d-react/r3f-adapter.tsx +0 -717
  87. package/src/world3d-react/world-context.ts +0 -358
@@ -0,0 +1,86 @@
1
+ /**
2
+ * The GAME-SCOPED input wiring one world mount owns — HOST work performed from
3
+ * outside the world's own tree, shared verbatim by the three and canvas lanes
4
+ * (a project has ONE input map and one bot-input doctrine, whatever surface
5
+ * reads them).
6
+ *
7
+ * Two things happen here:
8
+ *
9
+ * 1. the project's input map is loaded through `Game.loadInputMap` (game-owned,
10
+ * load-once), so the actions the project declared exist;
11
+ * 2. this root's seams are registered on the game-scoped debug registry
12
+ * (`setVirtualInputTarget`/`setInputActionsSource`/`setInputTraceSource`),
13
+ * which is what makes `game.input.hold/tap/...` (the bot/`vgai eval` input
14
+ * doctrine) and the built-in `input.actions`/`input.trace` providers
15
+ * resolve to this world instead of throwing `DEBUG_INPUT_UNAVAILABLE`.
16
+ *
17
+ * A world's React tree receives no vgai context — this wiring is precisely the
18
+ * part that never needed one: every closure below reads GAME-scoped state the
19
+ * host owns (`game.input`, `game.loop.fixedDt`, the game's seed).
20
+ *
21
+ * `optionalInputMap` is the CONVENTIONAL-PATH probe used when the project
22
+ * never named a map: an absent file is the ordinary state of a brand-new
23
+ * project, so it resolves quietly instead of printing an error on every boot.
24
+ * A map that exists and fails to parse is as loud as ever.
25
+ *
26
+ * LIFETIME, honestly: `registry.strip(id)` runs on the mount's dispose, but it
27
+ * walks providers/commands only — the three seams set here survive it, keyed
28
+ * by this world's id, until a remount of the same id overwrites them. That
29
+ * residue is inert rather than hidden: every closure reads game-scoped state,
30
+ * so a stale entry actuates exactly what a live one would. What it can still
31
+ * do is name a dead world in `DEBUG_INPUT_WORLD_NOT_FOUND`'s registered list.
32
+ * Do not write "the strip clears the input seams" anywhere without changing
33
+ * `strip` to actually do it.
34
+ */
35
+ import { getSeededRandom } from '../core/seeded-random';
36
+ /** The conventional input-map location every scaffolded project ships
37
+ * (`public/inputmaps/default.inputmap.json`). */
38
+ export const DEFAULT_INPUT_MAP_PATH = '/inputmaps/default.inputmap.json';
39
+ export function wireGameInputSeams(host, registry, options) {
40
+ const { id, inputMapPath = DEFAULT_INPUT_MAP_PATH, optionalInputMap = false } = options;
41
+ if (!host.game)
42
+ return Promise.resolve();
43
+ const game = host.game;
44
+ const input = game.input;
45
+ registry.setInputActionsSource(id, () => input.actionNames().map((name) => ({ name, valueType: input.getActionValueType(name) })));
46
+ registry.setInputTraceSource(id, () => {
47
+ const raw = input.getInputTrace();
48
+ return {
49
+ version: raw.version,
50
+ seed: getSeededRandom(game)?.seed ?? null,
51
+ fixedDt: game.loop.fixedDt,
52
+ ticks: raw.ticks,
53
+ };
54
+ });
55
+ registry.setVirtualInputTarget(id, {
56
+ setVirtualAction: (action, value) => input.setVirtualAction(action, value),
57
+ tapVirtualAction: (action) => input.tapVirtualAction(action),
58
+ clearVirtualActions: () => input.clearVirtualActions(),
59
+ scheduleActionAtTick: (tick, action, value) => input.scheduleActionAtTick(tick, action, value),
60
+ startInputRecording: () => input.startInputRecording(),
61
+ stopInputRecording: () => input.stopInputRecording(),
62
+ isInputRecording: () => input.isInputRecording(),
63
+ injectAxis: (sourceId, value) => input.injectAxis(sourceId, value),
64
+ injectVector2: (sourceId, value) => input.injectVector2(sourceId, value),
65
+ injectPointerDelta: (sourceId, delta) => input.injectPointerDelta(sourceId, delta),
66
+ injectPointerPosition: (sourceId, value) => input.injectPointerPosition(sourceId, value),
67
+ });
68
+ if (host.headless || inputMapPath === null)
69
+ return Promise.resolve();
70
+ // Load-once through the game-owned path (competing paths across roots throw
71
+ // THERE, loudly). A FAILED load (missing/bad file) must not fail the mount:
72
+ // a world with no declared actions is legal. It degrades loudly instead —
73
+ // naming exactly what breaks.
74
+ // The non-optional call passes ONE argument, exactly as it always has — a
75
+ // trailing `undefined` is a different call to any observer of it.
76
+ const load = optionalInputMap
77
+ ? game.loadInputMap(inputMapPath, { optional: true })
78
+ : game.loadInputMap(inputMapPath);
79
+ return load.catch((err) => {
80
+ // biome-ignore lint/suspicious/noConsole: deliberate loud degrade — the documented alternative to failing the mount (see comment above)
81
+ console.error(`world "${id}": failed to load input map "${inputMapPath}" — declared input ` +
82
+ 'actions and `game.input.*` (bot/virtual input) will not work until a valid map ' +
83
+ `loads. Ship one at the conventional path (${DEFAULT_INPUT_MAP_PATH}). ` +
84
+ `Cause: ${err instanceof Error ? err.message : String(err)}`);
85
+ });
86
+ }
@@ -308,6 +308,21 @@ export interface Game {
308
308
  readonly systemAdapters: SystemAdapters;
309
309
  /** Subscribe when a mounted root registers or replaces a system adapter. */
310
310
  subscribeSystemAdapters?(listener: () => void): () => void;
311
+ /**
312
+ * Install a root's STATICALLY DECLARED system-adapter slots — the native
313
+ * module surface's `export const systems` (adapter/native-debug-module.ts),
314
+ * already validated by `contract-system-adapters.ts`. The host calls this
315
+ * once per declaring root at mount; project components never do
316
+ * (ARCHITECTURE-CORE §System adapters: "Components never call
317
+ * `registerSystemAdapter`" — this door is the replacement, and the slots it
318
+ * installs take precedence over a component registration for the same root
319
+ * in {@link systemAdapters}'s merge, with the standard collision warning).
320
+ * Throws on an unmounted root id or a second declaration for the same root.
321
+ * Optional for the same reason {@link subscribeSystemAdapters} is: partial
322
+ * `Game` doubles in tests; `installNativeSystemsBindings` refuses loudly
323
+ * when the hosting Game lacks it.
324
+ */
325
+ installDeclaredSystemAdapters?(rootId: string, slots: Readonly<Partial<SystemAdapters>>): void;
311
326
  /** The one game-owned `InputManager`, shared by every first-party root. */
312
327
  readonly input: InputManager;
313
328
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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"}
@@ -335,7 +335,13 @@ export function createGame(opts) {
335
335
  // above's "once per game instance" idiom.
336
336
  const warnedSystemAdapterKeys = new Set();
337
337
  const systemAdapterListeners = new Set();
338
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one cohesive merge-with-collision-report walk (per-world × per-key); splitting the collision-warn branch out would obscure that it's part of the same pass, not reduce real complexity
338
+ /** Per-root slots installed by `installDeclaredSystemAdapters` the native
339
+ * module surface's static `systems` declaration. Merged BEFORE the same
340
+ * root's live `mounted.systems` below, so during migration a lingering
341
+ * component registration for a declared slot is shadowed (with the
342
+ * standard warning) rather than silently winning by running later. */
343
+ const declaredSystemAdapters = new Map();
344
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one cohesive merge-with-collision-report walk (per-world × per-source × per-key); splitting the collision-warn branch out would obscure that it's part of the same pass, not reduce real complexity
339
345
  function computeSystemAdapters() {
340
346
  // Debug is game-scoped: React hooks, probes, and the built-in time
341
347
  // provider all register with the one registry created above, regardless
@@ -345,10 +351,7 @@ export function createGame(opts) {
345
351
  // intentional shared registration it is.
346
352
  const result = { debug: debugRegistry.adapter };
347
353
  const ownerRootId = new Map([['debug', '(game)']]);
348
- for (const world of roots) {
349
- const adapters = world.mounted.systems;
350
- if (!adapters)
351
- continue;
354
+ const merge = (owner, adapters, quietKeys) => {
352
355
  for (const key of Object.keys(adapters)) {
353
356
  if (adapters[key] === undefined)
354
357
  continue;
@@ -360,18 +363,35 @@ export function createGame(opts) {
360
363
  // collision, so it must never warn.
361
364
  if (result[key] === adapters[key])
362
365
  continue;
366
+ // A world's own DECLARED slot overriding that same world's
367
+ // substrate-seeded default (the three lane pre-seeds physics/audio/
368
+ // renderDebug into `mounted.systems`) is the door working as
369
+ // intended, not a collision — same silence `ctx.
370
+ // registerSystemAdapter` gives the same override. Cross-root
371
+ // collisions still warn.
372
+ if (quietKeys?.has(key))
373
+ continue;
363
374
  if (!warnedSystemAdapterKeys.has(key)) {
364
375
  warnedSystemAdapterKeys.add(key);
365
376
  // biome-ignore lint/suspicious/noConsole: structured, greppable — mirrors this file's own reportGateShortfallOnce's deliberate direct console.warn just above
366
- console.warn(`[game] systemAdapters: "${key}" is registered by both world "${existingOwner}" and ` +
367
- `world "${world.id}" — the FIRST registration ("${existingOwner}") wins; the later ` +
377
+ console.warn(`[game] systemAdapters: "${key}" is registered by both ${existingOwner} and ` +
378
+ `${owner} — the FIRST registration (${existingOwner}) wins; the later ` +
368
379
  'one is shadowed (game-scoped system adapters).');
369
380
  }
370
381
  continue;
371
382
  }
372
383
  // biome-ignore lint/suspicious/noExplicitAny: SystemAdapters is a plain optional-field record; the per-key copy is correct by construction (same key on both sides), just not expressible without a cast
373
384
  result[key] = adapters[key];
374
- ownerRootId.set(key, world.id);
385
+ ownerRootId.set(key, owner);
386
+ }
387
+ };
388
+ for (const world of roots) {
389
+ const declared = declaredSystemAdapters.get(world.id);
390
+ if (declared)
391
+ merge(`world "${world.id}" (declared systems export)`, declared);
392
+ const adapters = world.mounted.systems;
393
+ if (adapters) {
394
+ merge(`world "${world.id}"`, adapters, declared ? new Set(Object.keys(declared)) : undefined);
375
395
  }
376
396
  }
377
397
  return result;
@@ -741,6 +761,18 @@ export function createGame(opts) {
741
761
  for (const listener of systemAdapterListeners)
742
762
  listener();
743
763
  },
764
+ installDeclaredSystemAdapters(rootId, slots) {
765
+ if (!roots.some((w) => w.id === rootId)) {
766
+ throw new Error(`installDeclaredSystemAdapters: no mounted root is named "${rootId}" ` +
767
+ `(mounted: ${roots.map((w) => `"${w.id}"`).join(', ') || 'none'}).`);
768
+ }
769
+ if (declaredSystemAdapters.has(rootId)) {
770
+ throw new Error(`installDeclaredSystemAdapters: root "${rootId}" already installed its declared ` +
771
+ 'systems — a declaration is static and installs exactly once per mount.');
772
+ }
773
+ declaredSystemAdapters.set(rootId, slots);
774
+ gameInternal.notifySystemAdaptersChanged();
775
+ },
744
776
  input,
745
777
  state: stateBridge,
746
778
  play: {
@@ -1 +1 @@
1
- {"version":3,"file":"mount-game.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-game.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,KAAK,UAAU,EAAuC,MAAM,kBAAkB,CAAC;AAQxF;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;6DACyD;IACzD,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD;;;mFAG+E;IAC/E,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;gEAC4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACzC;AAED,+EAA+E;AAC/E,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,KAAK,EAAE,mBAAmB,EAC1B,GAAG,EAAE,4BAA4B,KAC9B,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAQtC;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAUlF;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D;AAcD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,0BAA0B,EAAE,qBAexC,CAAC;AAMF,MAAM,WAAW,gBAAgB;IAC/B;;;kEAG8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC;CACrE;AAyBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,OAAO,EACtB,IAAI,EAAE,YAAY,EAClB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,WAAW,CAAC,CA6CtB"}
1
+ {"version":3,"file":"mount-game.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-game.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,KAAK,UAAU,EAAuC,MAAM,kBAAkB,CAAC;AAQxF;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;6DACyD;IACzD,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD;;;mFAG+E;IAC/E,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;gEAC4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACzC;AAED,+EAA+E;AAC/E,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,KAAK,EAAE,mBAAmB,EAC1B,GAAG,EAAE,4BAA4B,KAC9B,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAQtC;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAUlF;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D;AAcD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,0BAA0B,EAAE,qBAexC,CAAC;AAMF,MAAM,WAAW,gBAAgB;IAC/B;;;kEAG8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC;CACrE;AAkCD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,OAAO,EACtB,IAAI,EAAE,YAAY,EAClB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,WAAW,CAAC,CAqDtB"}
@@ -16,7 +16,9 @@
16
16
  // factory for that kind itself — see `defaultThreeAdapterFactory` below for why
17
17
  // even the 'three' convenience export is a plain function the CALLER
18
18
  // registers, not something this module wires up automatically.
19
- import { installNativeDebugBindings, nativeDebugBindingFromEntryModule, } from '../adapter/native-debug-module';
19
+ import { declaredRoots } from '../adapter/manifest-interpreter';
20
+ import { installNativeDebugBindings, installNativeSystemsBindings, nativeDebugBindingFromEntryModule, nativeSystemsBindingFromEntryModule, } from '../adapter/native-debug-module';
21
+ import { publishDevInstruments } from '../dev/instruments';
20
22
  import { mountManifestRoots, resolveManifest } from './mount-manifest';
21
23
  import { assertExportedOrInEditor } from './unexported-game-trap';
22
24
  // ---------------------------------------------------------------------------
@@ -109,6 +111,12 @@ function nativeDebugForEntry(world, entryModule) {
109
111
  const binding = nativeDebugBindingFromEntryModule(world.id, entryModule);
110
112
  return binding ? [binding] : [];
111
113
  }
114
+ function nativeSystemsForEntry(world, entryModule) {
115
+ if (entryModule === undefined || world.adapter.type !== 'builtin')
116
+ return [];
117
+ const binding = nativeSystemsBindingFromEntryModule(world.id, entryModule, world.surface);
118
+ return binding ? [binding] : [];
119
+ }
112
120
  /**
113
121
  * Mount every world declared by a `vgai.project.json` manifest onto `host
114
122
  * .container`, resolving each world's kind through the `registerAdapter`
@@ -137,7 +145,8 @@ export async function mountGameFromManifest(manifestInput, host, opts = {}) {
137
145
  const manifest = resolveManifest(manifestInput);
138
146
  const entries = { ...opts.entries };
139
147
  const nativeDebug = [];
140
- for (const world of manifest.roots) {
148
+ const nativeSystems = [];
149
+ for (const world of declaredRoots(manifest)) {
141
150
  if (entries[world.id] !== undefined)
142
151
  continue; // explicit entry always wins
143
152
  const factory = registry.get(world.adapter.identity);
@@ -146,6 +155,7 @@ export async function mountGameFromManifest(manifestInput, host, opts = {}) {
146
155
  ? await host.loadEntryModule(world.entry)
147
156
  : undefined;
148
157
  nativeDebug.push(...nativeDebugForEntry(world, entryModule));
158
+ nativeSystems.push(...nativeSystemsForEntry(world, entryModule));
149
159
  entries[world.id] = await factory(world, { host, entryModule });
150
160
  continue;
151
161
  }
@@ -166,5 +176,11 @@ export async function mountGameFromManifest(manifestInput, host, opts = {}) {
166
176
  headless: host.headless,
167
177
  });
168
178
  installNativeDebugBindings(session.game, nativeDebug);
179
+ installNativeSystemsBindings(session.game, nativeSystems);
180
+ // The universal instruments are host furniture on EVERY mount path — the
181
+ // editor installs them in its own bindings pass; the standalone composer
182
+ // installs them here. The disposer is deliberately dropped: the set's one
183
+ // resource lives on this Game and dies with it.
184
+ publishDevInstruments(session.game);
169
185
  return session;
170
186
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mount-manifest.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mount-manifest.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-manifest.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,7 @@
23
23
  // caller of `createGameRuntime`, so wrapping a `setup` with
24
24
  // `fromSetup` here adds no NEW bundle weight — only pixi/react are avoided.
25
25
  import { assertNever } from '../adapter/adapter-surface';
26
+ import { declaredRoots } from '../adapter/manifest-interpreter';
26
27
  // Value-imported from the implementer's OWN path, not the type-only
27
28
  // `../adapter` barrel (P-6).
28
29
  import { fromSetup } from '../adapter/setup-three-root-adapter';
@@ -209,11 +210,12 @@ function buildRootMountSpec(world, entry) {
209
210
  */
210
211
  export async function mountManifestRoots(opts) {
211
212
  const manifest = resolveManifest(opts.manifest);
212
- if (manifest.roots.length === 0) {
213
+ const mountPlan = declaredRoots(manifest);
214
+ if (mountPlan.length === 0) {
213
215
  throw new Error('mountManifestRoots: manifest declares no roots — nothing to mount.');
214
216
  }
215
217
  const entries = opts.entries ?? {};
216
- const roots = manifest.roots.map((world) => buildRootMountSpec(world, entries[world.id]));
218
+ const roots = mountPlan.map((world) => buildRootMountSpec(world, entries[world.id]));
217
219
  // D15 (T-D15.1) — resolved BEFORE `createGameRuntime` (which constructs the
218
220
  // Game, and therefore `ctx.random`, before any world's `mount()`/`setup()`
219
221
  // runs — see `createGame`'s own doc comment): the seed must be baked in at
@@ -274,7 +274,7 @@ export interface EditorPreview {
274
274
  *
275
275
  * Its one former reader — `browser-play-entry.ts`'s whole-bundle `setup()`,
276
276
  * which dispatched over the generated `SETUP_BY_EXAMPLE_ID` table — is
277
- * DELETED. Hosted dispatch is per-root (`ADAPTER_BY_EXAMPLE_ROOT` /
277
+ * DELETED. Hosted dispatch is per-root (`THREE_BY_EXAMPLE_ROOT` /
278
278
  * `REACT_BY_EXAMPLE_ROOT`, resolved in `adapter-resolver.ts`) and never
279
279
  * consults this field; `exampleDispatchFor` still sets it as the marker for
280
280
  * "play the project's own shipped game" rather than a `?scene=` override
@@ -2,11 +2,8 @@
2
2
  * world3d-react — the react-three-fiber bridge for vgai's three surface
3
3
  * (`@engine/world3d-react`).
4
4
  *
5
- * An OPT-IN module, upstreamed
6
- * from the live-proven `examples/r3f-first-party` project copies (R4;
7
- * decision D24 — R3F TSX is the blessed three.js authoring path). Mirrors how
8
- * `pixi/` is the PixiJS surface's opt-in home: a peer surface module the engine
9
- * CORE never imports (enforced by
5
+ * An OPT-IN module, mirroring how `pixi/` is the PixiJS surface's opt-in home:
6
+ * a peer surface module the engine CORE never imports (enforced by
10
7
  * `packages/engine/test/react-core-import-ban.test.ts` — this directory is an
11
8
  * allowed react-importing entry alongside `react/`, and core files may not
12
9
  * import it).
@@ -14,34 +11,27 @@
14
11
  * Peer contract: an importing PROJECT already depends on `react`,
15
12
  * `@react-three/fiber`, and `three` (fiber's three must be deduped to the
16
13
  * host's single instance — `resolve.dedupe: ['three', 'react', 'react-dom']`
17
- * in the project's Vite config; see `createR3FAdapter`'s header). The engine
18
- * package deliberately declares no hard dependency on fiber: only projects
19
- * that already mount through fiber ever import this module.
14
+ * in the project's Vite config). The engine package deliberately declares no
15
+ * hard dependency on fiber: only projects that already mount through fiber
16
+ * ever import this module.
20
17
  *
21
18
  * Surface:
22
- * - `createR3FAdapter({ id, content })` — mount an R3F tree as a first-party
23
- * `kind: "three"` world under the host's gated loop.
24
- * - `useGameContext()` this root's `R3FGameContext` (`input`, `debug`,
25
- * `random`, `game`, `roots`, …) from inside any component in the tree. This
26
- * is how an R3F world reaches engine services: behavior is components +
27
- * hooks (D26b), not a class under a string key. The subsystems an R3F world
28
- * does not build are absent from that type — see its doc comment for what
29
- * to use instead.
30
- * - `EngineBridge` / `EngineBridgeValue` — the context contract, exported
31
- * for advanced adopters building their own bridge.
19
+ * - `r3fRootFactory` / `resolveR3FEntryAdapter`what a three entry module
20
+ * MEANS: a default-exported component (`export default function World()`),
21
+ * mounted as a first-party `kind: "three"` world under the host's gated
22
+ * loop. The world's vgai surface is its entry module's static exports
23
+ * (`export { debug, systems } from './commands'`), connected by the host
24
+ * at mount.
32
25
  *
33
26
  * Deliberately NOT re-exported here: `<RapierPhysicsBridge>`
34
- * (`@engine/world3d-react/rapier-physics-bridge`), which registers an R3F
35
- * world's `@react-three/rapier` physics as the game's
36
- * `SystemAdapters.physics` — so the colliders instrument and the
37
- * editor's transform coordination can see it. It imports
27
+ * (`@engine/world3d-react/rapier-physics-bridge`), which publishes an R3F
28
+ * world's `@react-three/rapier` physics to the module slot the entry's
29
+ * `systems.physics` declaration forwards — so the colliders instrument and
30
+ * the editor's transform coordination can see it. It imports
38
31
  * `@react-three/rapier`, and only a world that already depends on that library
39
32
  * should pull it into its graph; a deep import keeps this barrel's peer
40
33
  * contract to `react`/`@react-three/fiber`/`three` alone.
41
34
  */
42
35
  export { applyWorldRendererConfig, type WorldOutputColorSpace, type WorldRendererConfig, type WorldToneMapping, } from '../adapter/renderer-config';
43
- export { EngineBridge, type EngineBridgeValue, useGameContext } from './engine-bridge';
44
- export { type CreateR3FAdapterOptions, createR3FAdapter } from './r3f-adapter';
45
36
  export { r3fRootFactory, resolveR3FEntryAdapter } from './r3f-root-factory';
46
- export { createR3FRootContext, DEFAULT_INPUT_MAP_PATH, type R3FGameContext, type R3FRootContextOptions, type R3FRootRuntime, } from './world-context';
47
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/world3d-react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EACL,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAAE,KAAK,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/world3d-react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EACL,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -2,11 +2,8 @@
2
2
  * world3d-react — the react-three-fiber bridge for vgai's three surface
3
3
  * (`@engine/world3d-react`).
4
4
  *
5
- * An OPT-IN module, upstreamed
6
- * from the live-proven `examples/r3f-first-party` project copies (R4;
7
- * decision D24 — R3F TSX is the blessed three.js authoring path). Mirrors how
8
- * `pixi/` is the PixiJS surface's opt-in home: a peer surface module the engine
9
- * CORE never imports (enforced by
5
+ * An OPT-IN module, mirroring how `pixi/` is the PixiJS surface's opt-in home:
6
+ * a peer surface module the engine CORE never imports (enforced by
10
7
  * `packages/engine/test/react-core-import-ban.test.ts` — this directory is an
11
8
  * allowed react-importing entry alongside `react/`, and core files may not
12
9
  * import it).
@@ -14,33 +11,26 @@
14
11
  * Peer contract: an importing PROJECT already depends on `react`,
15
12
  * `@react-three/fiber`, and `three` (fiber's three must be deduped to the
16
13
  * host's single instance — `resolve.dedupe: ['three', 'react', 'react-dom']`
17
- * in the project's Vite config; see `createR3FAdapter`'s header). The engine
18
- * package deliberately declares no hard dependency on fiber: only projects
19
- * that already mount through fiber ever import this module.
14
+ * in the project's Vite config). The engine package deliberately declares no
15
+ * hard dependency on fiber: only projects that already mount through fiber
16
+ * ever import this module.
20
17
  *
21
18
  * Surface:
22
- * - `createR3FAdapter({ id, content })` — mount an R3F tree as a first-party
23
- * `kind: "three"` world under the host's gated loop.
24
- * - `useGameContext()` this root's `R3FGameContext` (`input`, `debug`,
25
- * `random`, `game`, `roots`, …) from inside any component in the tree. This
26
- * is how an R3F world reaches engine services: behavior is components +
27
- * hooks (D26b), not a class under a string key. The subsystems an R3F world
28
- * does not build are absent from that type — see its doc comment for what
29
- * to use instead.
30
- * - `EngineBridge` / `EngineBridgeValue` — the context contract, exported
31
- * for advanced adopters building their own bridge.
19
+ * - `r3fRootFactory` / `resolveR3FEntryAdapter`what a three entry module
20
+ * MEANS: a default-exported component (`export default function World()`),
21
+ * mounted as a first-party `kind: "three"` world under the host's gated
22
+ * loop. The world's vgai surface is its entry module's static exports
23
+ * (`export { debug, systems } from './commands'`), connected by the host
24
+ * at mount.
32
25
  *
33
26
  * Deliberately NOT re-exported here: `<RapierPhysicsBridge>`
34
- * (`@engine/world3d-react/rapier-physics-bridge`), which registers an R3F
35
- * world's `@react-three/rapier` physics as the game's
36
- * `SystemAdapters.physics` — so the colliders instrument and the
37
- * editor's transform coordination can see it. It imports
27
+ * (`@engine/world3d-react/rapier-physics-bridge`), which publishes an R3F
28
+ * world's `@react-three/rapier` physics to the module slot the entry's
29
+ * `systems.physics` declaration forwards — so the colliders instrument and
30
+ * the editor's transform coordination can see it. It imports
38
31
  * `@react-three/rapier`, and only a world that already depends on that library
39
32
  * should pull it into its graph; a deep import keeps this barrel's peer
40
33
  * contract to `react`/`@react-three/fiber`/`three` alone.
41
34
  */
42
35
  export { applyWorldRendererConfig, } from '../adapter/renderer-config';
43
- export { EngineBridge, useGameContext } from './engine-bridge';
44
- export { createR3FAdapter } from './r3f-adapter';
45
36
  export { r3fRootFactory, resolveR3FEntryAdapter } from './r3f-root-factory';
46
- export { createR3FRootContext, DEFAULT_INPUT_MAP_PATH, } from './world-context';
@@ -1,8 +1,6 @@
1
1
  /**
2
2
  * `r3fRootFactory` — mount a `three` root whose entry module DEFAULT-EXPORTS a
3
- * React component.
4
- *
5
- * The idiomatic-shape fix (D26). A model asked for an R3F world writes:
3
+ * React component. This is the ONE first-party three mount:
6
4
  *
7
5
  * ```tsx
8
6
  * export default function World() {
@@ -10,15 +8,13 @@
10
8
  * }
11
9
  * ```
12
10
  *
13
- * It does NOT write `export const adapter = createR3FAdapter({ id, content })`.
14
- * That export is pure vgai ceremony wrapped around a component the author
15
- * already wrote, and it is the second-largest non-idiomatic thing left in a
16
- * world file (the largest is the missing `<Canvas>`, which is a separate
17
- * question about who owns the canvas — see D26).
18
- *
19
- * The `dom` root already settled this convention: its factory reads
20
- * `entryModule.default` and wraps it. This is the same contract for three
21
- * roots, so both surfaces answer "what do I export?" the same way.
11
+ * The world is an ordinary R3F app. Everything vgai-shaped stays at the entry
12
+ * module's STATIC surface (`export { debug, systems } from './commands'`) and
13
+ * on the host's side of the seam; no vgai runtime context ever enters the
14
+ * React tree. The host controls Fiber's `frameloop: 'never'` scheduler, wires
15
+ * the game-scoped input seams from outside (`../runtime/game-input-seams.ts`),
16
+ * and installs `WorldProvider` off the Game handle so the lib-legal react
17
+ * doors (`useWorldState`, `useOptionalGame`, `useDebugProvider`) resolve.
22
18
  *
23
19
  * ## Why this is NOT in `mount-game.ts`
24
20
  *
@@ -30,12 +26,15 @@
30
26
  * there would make R3F unconditional for every game, including ones with no
31
27
  * React at all.
32
28
  *
33
- * ## Compatibility
29
+ * ## The mount mechanics (fiber v9, host-gated)
34
30
  *
35
- * An `adapter` export still wins, so existing worlds are untouched and a game
36
- * needing full control over its own `RootAdapter` keeps it.
31
+ * three.js identity: this module never imports `three` itself for scene
32
+ * objects fiber's internal `import * as THREE from 'three'` must resolve to
33
+ * the SAME instance the engine's `ThreeHostContext.three` points at, which the
34
+ * importing project guarantees via its Vite
35
+ * `resolve.dedupe: ['three', 'react', 'react-dom']`.
37
36
  */
38
- import type { RootAdapter } from '../adapter/root-adapter';
37
+ import type { RootAdapter } from '../adapter';
39
38
  import type { AdapterSurfaceFactory } from '../runtime/mount-game';
40
39
  /**
41
40
  * What a three entry module MEANS, in one place.
@@ -43,20 +42,15 @@ import type { AdapterSurfaceFactory } from '../runtime/mount-game';
43
42
  * Two callers need this answer and must never disagree about it: the runtime
44
43
  * mount ({@link r3fRootFactory}, below) and the EDITOR's design session
45
44
  * (`packages/editor/src/authoring/r3f-design-session.ts`), which design-mounts
46
- * the same entry so edit mode authors the live fiber scene. When only the
47
- * runtime knew about the default-export shape, the converted starter played
48
- * fine under `npm run game` and edit mode showed "(no scene loaded)".
45
+ * the same entry so edit mode authors the live fiber scene.
49
46
  *
50
- * Returns `null` when the module is neither shape — the callers differ on what
51
- * to do about that (the factory throws, the design session declines the world
52
- * and leaves existing paths alone).
47
+ * Returns `null` when the module has no default-exported component — the
48
+ * callers differ on what to do about that (the factory throws, the design
49
+ * session declines the world and leaves existing paths alone).
53
50
  */
54
51
  export declare function resolveR3FEntryAdapter(entryModule: unknown, rootId: string): RootAdapter | null;
55
52
  /**
56
53
  * Register with `registerAdapter('three', r3fRootFactory)`.
57
- *
58
- * Resolution order mirrors `defaultThreeAdapterFactory`'s (explicit adapter
59
- * wins) and then accepts the default-exported component.
60
54
  */
61
55
  export declare const r3fRootFactory: AdapterSurfaceFactory;
62
56
  //# sourceMappingURL=r3f-root-factory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"r3f-root-factory.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-root-factory.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAUnE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAwB/F;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,qBAQ5B,CAAC"}
1
+ {"version":3,"file":"r3f-root-factory.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-root-factory.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAWH,OAAO,KAAK,EAAoB,WAAW,EAAoB,MAAM,YAAY,CAAC;AAelF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAsZnE;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI/F;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,qBAO5B,CAAC"}