@vgai/engine 0.5.22 → 0.5.23

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 (291) hide show
  1. package/README.md +6 -3
  2. package/dist/adapter/adapter-module.d.ts.map +1 -1
  3. package/dist/adapter/adapter-module.js +2 -4
  4. package/dist/adapter/adapter-surface.d.ts +1 -1
  5. package/dist/adapter/adapter-surface.js +1 -1
  6. package/dist/adapter/authoring.d.ts +19 -21
  7. package/dist/adapter/authoring.d.ts.map +1 -1
  8. package/dist/adapter/authoring.js +2 -2
  9. package/dist/adapter/binding.d.ts +341 -0
  10. package/dist/adapter/binding.d.ts.map +1 -0
  11. package/dist/adapter/binding.js +148 -0
  12. package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -1
  13. package/dist/adapter/colyseus-networking-adapter.js +23 -4
  14. package/dist/adapter/entrypoint-selection-readers.d.ts +24 -0
  15. package/dist/adapter/entrypoint-selection-readers.d.ts.map +1 -0
  16. package/dist/adapter/entrypoint-selection-readers.js +63 -0
  17. package/dist/adapter/entrypoint-selection-source.d.ts.map +1 -1
  18. package/dist/adapter/entrypoint-selection-source.js +1 -44
  19. package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts.map +1 -1
  20. package/dist/adapter/finders/scenes-from-entrypoint-selection.js +1 -52
  21. package/dist/adapter/host-context.d.ts +46 -15
  22. package/dist/adapter/host-context.d.ts.map +1 -1
  23. package/dist/adapter/host-context.js +2 -9
  24. package/dist/adapter/index.d.ts +11 -12
  25. package/dist/adapter/index.d.ts.map +1 -1
  26. package/dist/adapter/index.js +9 -10
  27. package/dist/adapter/ingest/game-contract.d.ts +0 -3
  28. package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
  29. package/dist/adapter/ingest/game-contract.js +0 -3
  30. package/dist/adapter/ingest/scene-capture.d.ts +19 -23
  31. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
  32. package/dist/adapter/ingest/scene-capture.js +143 -17
  33. package/dist/adapter/ingest/visible-capture-window.d.ts +34 -0
  34. package/dist/adapter/ingest/visible-capture-window.d.ts.map +1 -1
  35. package/dist/adapter/native-debug-module.d.ts +31 -5
  36. package/dist/adapter/native-debug-module.d.ts.map +1 -1
  37. package/dist/adapter/native-debug-module.js +25 -7
  38. package/dist/adapter/rapier-physics-adapter.d.ts +31 -1
  39. package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -1
  40. package/dist/adapter/rapier-physics-adapter.js +50 -36
  41. package/dist/adapter/renderer-config.d.ts +2 -2
  42. package/dist/adapter/renderer-config.js +2 -2
  43. package/dist/adapter/root-adapter.d.ts +7 -7
  44. package/dist/adapter/root-adapter.js +4 -4
  45. package/dist/adapter/system-adapter.d.ts +45 -7
  46. package/dist/adapter/system-adapter.d.ts.map +1 -1
  47. package/dist/adapter/system-seam-contract.d.ts +3 -3
  48. package/dist/adapter/system-seam-contract.js +3 -3
  49. package/dist/adapter/system-slot.d.ts +168 -0
  50. package/dist/adapter/system-slot.d.ts.map +1 -0
  51. package/dist/adapter/system-slot.js +229 -0
  52. package/dist/adapter/transform.d.ts +11 -1
  53. package/dist/adapter/transform.d.ts.map +1 -1
  54. package/dist/ai/navigation.d.ts +17 -1
  55. package/dist/ai/navigation.d.ts.map +1 -1
  56. package/dist/ai/navigation.js +26 -5
  57. package/dist/animation/anim-graph-types.d.ts +11 -3
  58. package/dist/animation/anim-graph-types.d.ts.map +1 -1
  59. package/dist/animation/theatre-clock-binding.d.ts +4 -4
  60. package/dist/animation/theatre-clock-binding.js +4 -4
  61. package/dist/animation/xstate-animation-binding.d.ts.map +1 -1
  62. package/dist/animation/xstate-animation-binding.js +2 -2
  63. package/dist/animation/xstate-animation-meta.d.ts +13 -0
  64. package/dist/animation/xstate-animation-meta.d.ts.map +1 -1
  65. package/dist/animation/xstate-animation-meta.js +14 -0
  66. package/dist/asset-formats/index.d.ts +4 -7
  67. package/dist/asset-formats/index.d.ts.map +1 -1
  68. package/dist/asset-formats/index.js +4 -7
  69. package/dist/asset-formats/render-env.d.ts +5 -8
  70. package/dist/asset-formats/render-env.d.ts.map +1 -1
  71. package/dist/asset-formats/render-env.js +3 -6
  72. package/dist/asset-parse-error.d.ts +2 -5
  73. package/dist/asset-parse-error.d.ts.map +1 -1
  74. package/dist/asset-parse-error.js +2 -5
  75. package/dist/audio/bus-mixer.d.ts +101 -0
  76. package/dist/audio/bus-mixer.d.ts.map +1 -0
  77. package/dist/audio/bus-mixer.js +115 -0
  78. package/dist/core/frame-pacing.d.ts +1 -1
  79. package/dist/core/frame-pacing.js +2 -2
  80. package/dist/core/game-loop.d.ts +1 -3
  81. package/dist/core/game-loop.d.ts.map +1 -1
  82. package/dist/core/game-loop.js +1 -3
  83. package/dist/core/seeded-random.d.ts +1 -1
  84. package/dist/core/sim-clock.d.ts +5 -6
  85. package/dist/core/sim-clock.d.ts.map +1 -1
  86. package/dist/core/sim-clock.js +4 -5
  87. package/dist/core/types.d.ts +1 -3
  88. package/dist/core/types.d.ts.map +1 -1
  89. package/dist/defaults.d.ts +6 -14
  90. package/dist/defaults.d.ts.map +1 -1
  91. package/dist/defaults.js +6 -14
  92. package/dist/dev/register-render-vitals.d.ts +1 -4
  93. package/dist/dev/register-render-vitals.d.ts.map +1 -1
  94. package/dist/dev/register-render-vitals.js +1 -4
  95. package/dist/dev/render-debug-adapter.d.ts +2 -3
  96. package/dist/dev/render-debug-adapter.d.ts.map +1 -1
  97. package/dist/dev/render-debug-adapter.js +2 -3
  98. package/dist/dev/render-vitals.d.ts +3 -3
  99. package/dist/dev/render-vitals.js +3 -3
  100. package/dist/dev/webgl-frame-capture.d.ts +1 -1
  101. package/dist/dev/webgl-frame-capture.js +1 -1
  102. package/dist/index.d.ts +2 -5
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +2 -4
  105. package/dist/input/host-pointer.d.ts +122 -0
  106. package/dist/input/host-pointer.d.ts.map +1 -0
  107. package/dist/input/host-pointer.js +160 -0
  108. package/dist/input/input-manager.d.ts +18 -5
  109. package/dist/input/input-manager.d.ts.map +1 -1
  110. package/dist/input/input-manager.js +33 -13
  111. package/dist/input/rebind-controller.d.ts.map +1 -1
  112. package/dist/input/rebind-controller.js +6 -8
  113. package/dist/input/schema.d.ts.map +1 -1
  114. package/dist/input/schema.js +56 -28
  115. package/dist/manifest/filename.d.ts.map +1 -1
  116. package/dist/manifest/filename.js +8 -12
  117. package/dist/manifest/load.d.ts +10 -10
  118. package/dist/manifest/load.d.ts.map +1 -1
  119. package/dist/manifest/load.js +9 -6
  120. package/dist/manifest/schema.d.ts +17 -21
  121. package/dist/manifest/schema.d.ts.map +1 -1
  122. package/dist/manifest/schema.js +45 -35
  123. package/dist/physics/collider-dimensions.d.ts +8 -12
  124. package/dist/physics/collider-dimensions.d.ts.map +1 -1
  125. package/dist/physics/collider-dimensions.js +8 -12
  126. package/dist/pixi/scene-capture.d.ts +11 -13
  127. package/dist/pixi/scene-capture.d.ts.map +1 -1
  128. package/dist/react/world-state.d.ts +1 -1
  129. package/dist/react/world-state.d.ts.map +1 -1
  130. package/dist/render/light-camera-factory.d.ts +5 -7
  131. package/dist/render/light-camera-factory.d.ts.map +1 -1
  132. package/dist/render/light-camera-factory.js +8 -11
  133. package/dist/render/material-factory.js +1 -1
  134. package/dist/render/render-batch-system.d.ts.map +1 -1
  135. package/dist/render/render-features.d.ts +17 -6
  136. package/dist/render/render-features.d.ts.map +1 -1
  137. package/dist/render/render-features.js +0 -28
  138. package/dist/runtime/create-runtime.d.ts +34 -25
  139. package/dist/runtime/create-runtime.d.ts.map +1 -1
  140. package/dist/runtime/create-runtime.js +218 -93
  141. package/dist/runtime/debug-registry.d.ts +77 -8
  142. package/dist/runtime/debug-registry.d.ts.map +1 -1
  143. package/dist/runtime/debug-registry.js +3 -3
  144. package/dist/runtime/dev-build.d.ts +2 -2
  145. package/dist/runtime/dev-build.js +2 -2
  146. package/dist/runtime/game-input-seams.d.ts +2 -2
  147. package/dist/runtime/game-input-seams.d.ts.map +1 -1
  148. package/dist/runtime/game.d.ts +90 -41
  149. package/dist/runtime/game.d.ts.map +1 -1
  150. package/dist/runtime/game.js +80 -54
  151. package/dist/runtime/mount-game.d.ts +0 -16
  152. package/dist/runtime/mount-game.d.ts.map +1 -1
  153. package/dist/runtime/mount-game.js +8 -39
  154. package/dist/runtime/mount-manifest.d.ts +22 -14
  155. package/dist/runtime/mount-manifest.d.ts.map +1 -1
  156. package/dist/runtime/mount-manifest.js +18 -18
  157. package/dist/runtime/playtest.d.ts +22 -0
  158. package/dist/runtime/playtest.d.ts.map +1 -0
  159. package/dist/runtime/playtest.js +12 -0
  160. package/dist/runtime/state-bridge.d.ts +2 -3
  161. package/dist/runtime/state-bridge.d.ts.map +1 -1
  162. package/dist/runtime/state-bridge.js +1 -0
  163. package/dist/setup/setup-audio.d.ts +12 -0
  164. package/dist/setup/setup-audio.d.ts.map +1 -1
  165. package/dist/setup/setup-audio.js +9 -10
  166. package/dist/setup/setup-renderer.d.ts +2 -25
  167. package/dist/setup/setup-renderer.d.ts.map +1 -1
  168. package/dist/setup/setup-renderer.js +2 -31
  169. package/dist/world3d-react/r3f-root-factory.d.ts +7 -7
  170. package/dist/world3d-react/r3f-root-factory.js +7 -7
  171. package/dist/world3d-react/rapier-physics-bridge.d.ts +9 -8
  172. package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -1
  173. package/dist/world3d-react/rapier-physics-bridge.js +100 -48
  174. package/package.json +1 -1
  175. package/schemas/engine-capabilities.json +16 -14
  176. package/schemas/vgai-project.schema.json +35 -26
  177. package/src/adapter/adapter-module.ts +2 -4
  178. package/src/adapter/adapter-surface.ts +1 -1
  179. package/src/adapter/authoring.ts +19 -21
  180. package/src/adapter/binding.ts +468 -0
  181. package/src/adapter/colyseus-networking-adapter.ts +20 -5
  182. package/src/adapter/entrypoint-selection-readers.ts +66 -0
  183. package/src/adapter/entrypoint-selection-source.ts +1 -40
  184. package/src/adapter/finders/scenes-from-entrypoint-selection.ts +1 -48
  185. package/src/adapter/host-context.ts +45 -15
  186. package/src/adapter/index.ts +23 -11
  187. package/src/adapter/ingest/game-contract.ts +0 -3
  188. package/src/adapter/ingest/scene-capture.ts +190 -39
  189. package/src/adapter/ingest/visible-capture-window.ts +35 -0
  190. package/src/adapter/native-debug-module.ts +43 -7
  191. package/src/adapter/rapier-physics-adapter.ts +76 -20
  192. package/src/adapter/renderer-config.ts +2 -2
  193. package/src/adapter/root-adapter.ts +7 -7
  194. package/src/adapter/system-adapter.ts +43 -8
  195. package/src/adapter/system-seam-contract.ts +3 -3
  196. package/src/adapter/system-slot.ts +291 -0
  197. package/src/adapter/transform.ts +18 -1
  198. package/src/ai/navigation.ts +30 -3
  199. package/src/animation/anim-graph-types.ts +11 -3
  200. package/src/animation/theatre-clock-binding.ts +4 -4
  201. package/src/animation/xstate-animation-binding.ts +2 -2
  202. package/src/animation/xstate-animation-meta.ts +16 -0
  203. package/src/asset-formats/index.ts +4 -7
  204. package/src/asset-formats/render-env.ts +3 -6
  205. package/src/asset-parse-error.ts +2 -5
  206. package/src/audio/bus-mixer.ts +161 -0
  207. package/src/core/frame-pacing.ts +2 -2
  208. package/src/core/game-loop.ts +1 -3
  209. package/src/core/seeded-random.ts +1 -1
  210. package/src/core/sim-clock.ts +5 -6
  211. package/src/core/types.ts +1 -3
  212. package/src/defaults.ts +6 -14
  213. package/src/dev/register-render-vitals.ts +1 -4
  214. package/src/dev/render-debug-adapter.ts +2 -3
  215. package/src/dev/render-vitals.ts +3 -3
  216. package/src/dev/webgl-frame-capture.ts +1 -1
  217. package/src/index.ts +2 -5
  218. package/src/input/host-pointer.ts +230 -0
  219. package/src/input/input-manager.ts +34 -13
  220. package/src/input/input-types.ts +1 -1
  221. package/src/input/rebind-controller.ts +6 -8
  222. package/src/input/schema.ts +216 -188
  223. package/src/manifest/filename.ts +8 -12
  224. package/src/manifest/load.ts +17 -13
  225. package/src/manifest/schema.ts +55 -47
  226. package/src/physics/collider-dimensions.ts +8 -12
  227. package/src/pixi/scene-capture.ts +12 -15
  228. package/src/react/world-state.tsx +1 -1
  229. package/src/render/light-camera-factory.ts +8 -11
  230. package/src/render/material-factory.ts +1 -1
  231. package/src/render/render-batch-system.ts +14 -6
  232. package/src/render/render-features.ts +17 -35
  233. package/src/runtime/create-runtime.ts +270 -108
  234. package/src/runtime/debug-registry.ts +84 -8
  235. package/src/runtime/dev-build.ts +2 -2
  236. package/src/runtime/game-input-seams.ts +2 -2
  237. package/src/runtime/game.ts +168 -80
  238. package/src/runtime/mount-game.ts +8 -56
  239. package/src/runtime/mount-manifest.ts +43 -34
  240. package/src/runtime/playtest.ts +22 -0
  241. package/src/runtime/state-bridge.ts +3 -3
  242. package/src/setup/setup-audio.ts +21 -11
  243. package/src/setup/setup-renderer.ts +2 -61
  244. package/src/world3d-react/r3f-root-factory.tsx +7 -7
  245. package/src/world3d-react/rapier-physics-bridge.tsx +107 -50
  246. package/dist/adapter/setup-three-root-adapter.d.ts +0 -86
  247. package/dist/adapter/setup-three-root-adapter.d.ts.map +0 -1
  248. package/dist/adapter/setup-three-root-adapter.js +0 -908
  249. package/dist/animation/clip-map.d.ts +0 -12
  250. package/dist/animation/clip-map.d.ts.map +0 -1
  251. package/dist/animation/clip-map.js +0 -31
  252. package/dist/asset-registry.d.ts +0 -38
  253. package/dist/asset-registry.d.ts.map +0 -1
  254. package/dist/asset-registry.js +0 -66
  255. package/dist/canvas-react/engine-bridge.d.ts +0 -45
  256. package/dist/canvas-react/engine-bridge.d.ts.map +0 -1
  257. package/dist/canvas-react/engine-bridge.js +0 -45
  258. package/dist/canvas-react/pixi-react-adapter.d.ts +0 -77
  259. package/dist/canvas-react/pixi-react-adapter.d.ts.map +0 -1
  260. package/dist/canvas-react/pixi-react-adapter.js +0 -294
  261. package/dist/canvas-react/world-context.d.ts +0 -98
  262. package/dist/canvas-react/world-context.d.ts.map +0 -1
  263. package/dist/canvas-react/world-context.js +0 -173
  264. package/dist/dev/debug-draw.d.ts +0 -24
  265. package/dist/dev/debug-draw.d.ts.map +0 -1
  266. package/dist/dev/debug-draw.js +0 -73
  267. package/dist/render/auto-batcher.d.ts +0 -34
  268. package/dist/render/auto-batcher.d.ts.map +0 -1
  269. package/dist/render/auto-batcher.js +0 -140
  270. package/dist/render/lod.d.ts +0 -13
  271. package/dist/render/lod.d.ts.map +0 -1
  272. package/dist/render/lod.js +0 -16
  273. package/dist/runtime/types.d.ts +0 -303
  274. package/dist/runtime/types.d.ts.map +0 -1
  275. package/dist/runtime/types.js +0 -1
  276. package/dist/world3d-react/engine-bridge.d.ts +0 -47
  277. package/dist/world3d-react/engine-bridge.d.ts.map +0 -1
  278. package/dist/world3d-react/engine-bridge.js +0 -73
  279. package/dist/world3d-react/r3f-adapter.d.ts +0 -58
  280. package/dist/world3d-react/r3f-adapter.d.ts.map +0 -1
  281. package/dist/world3d-react/r3f-adapter.js +0 -634
  282. package/dist/world3d-react/world-context.d.ts +0 -182
  283. package/dist/world3d-react/world-context.d.ts.map +0 -1
  284. package/dist/world3d-react/world-context.js +0 -235
  285. package/src/adapter/setup-three-root-adapter.ts +0 -1032
  286. package/src/animation/clip-map.ts +0 -34
  287. package/src/asset-registry.ts +0 -89
  288. package/src/dev/debug-draw.ts +0 -80
  289. package/src/render/auto-batcher.ts +0 -168
  290. package/src/render/lod.ts +0 -17
  291. package/src/runtime/types.ts +0 -328
@@ -16,7 +16,7 @@ import { createDebugRegistry, DebugError, registerDebugRegistry, } from './debug
16
16
  import { createGameplayRngTrap, registerGameplayRngTrapControl } from './gameplay-rng-trap';
17
17
  import { createStateBridge } from './state-bridge';
18
18
  /**
19
- * WO-P13 — the tail of `PHASE_ORDER` that presents rather than simulates, and
19
+ * The tail of `PHASE_ORDER` that presents rather than simulates, and
20
20
  * therefore runs once per DISPLAY frame (`runRenderFrameImpl`) rather than
21
21
  * once per fixed substep. The same two phases `runTicks`' `skipRenderPhases`
22
22
  * fast-forward skips and `render-control.ts`'s `renderOnce()` drives — one
@@ -31,7 +31,7 @@ const DISPLAY_RATE_PHASES = PHASE_ORDER.filter((phase) => phase === SystemPhase.
31
31
  * slice or later ones) gets identical throw behavior.
32
32
  */
33
33
  export function createRootInstance(init) {
34
- const { id, kind, pausable = true, adapter, mounted, scene, stage, container, physics, collisions, physics2d, camera, frame, } = init;
34
+ const { id, kind, pausable = true, adapter, mounted, scene, stage, container, physics, collisions, physics2d, camera, frame, binding = null, } = init;
35
35
  // A three world with no scene has nothing for `threeScene()` to return —
36
36
  // fail loudly HERE, at construction, rather than letting `threeScene()`
37
37
  // throw its generic "not a three world" message later for a world whose
@@ -64,11 +64,11 @@ export function createRootInstance(init) {
64
64
  // read, so this wraps `mounted.dispose` in place (mutating the SAME mount
65
65
  // object every holder of `mounted` shares — calling `mounted.dispose()`
66
66
  // directly, exactly like calling `world.mounted.dispose()`, trips this)
67
- // to flip a private flag, and wraps the frame hooks so they silently no-op
68
- // once that flag is set. `runFrame` itself needs no knowledge of disposal
69
- // a disposed world is skipped by construction from the next call
70
- // onward. (The opaque-world `mounted.update` fallback path is unaffected
71
- // by this guard no opaque-mount two-world scenario exists yet to need it.)
67
+ // to flip a flag this instance exposes as `disposed`, and wraps the frame
68
+ // hooks so they silently no-op once it is set. `runFrame` reads `disposed`
69
+ // and skips the world outright, which is what also covers the OPAQUE
70
+ // `mounted.update` fallback — the path every three root takes now that a
71
+ // mount is a plain `RootAdapter` with no phase-partitioned entry point.
72
72
  let disposed = false;
73
73
  const originalDispose = mounted.dispose.bind(mounted);
74
74
  mounted.dispose = () => {
@@ -100,6 +100,10 @@ export function createRootInstance(init) {
100
100
  physics2d,
101
101
  camera,
102
102
  frame: guardedFrame,
103
+ binding,
104
+ get disposed() {
105
+ return disposed;
106
+ },
103
107
  threeScene() {
104
108
  if (kind !== 'three' || !scene) {
105
109
  throw new Error(`RootInstance "${id}" (kind: ${kind}): threeScene() requested but this world is not ` +
@@ -130,22 +134,6 @@ export function createRootInstance(init) {
130
134
  },
131
135
  };
132
136
  }
133
- /**
134
- * Type guard for whether a `MountedThreeRoot` is a first-party
135
- * `SetupThreeRootAdapter` mount (has a live `GameContext` at `.ctx`). Used to
136
- * decide whether a world's `physics`/`collisions`/`camera` can be populated
137
- * from it — an external
138
- * adapter's mount has none of these first-party handles.
139
- *
140
- * Checks the `firstParty: true` brand (checklist item 1), NOT `'ctx' in
141
- * mounted` — a foreign mount may carry an unrelated `ctx` key, so a
142
- * structural `'ctx' in mounted` check would misfire. The probe is a plain property read, not an
143
- * `instanceof`/value import of `setup-three-root-adapter.ts` — the
144
- * `MountedSetupThreeRoot` import above stays type-only.
145
- */
146
- export function isFirstPartyMounted(mounted) {
147
- return mounted.firstParty === true;
148
- }
149
137
  /**
150
138
  * Read an owner's Rapier handles, treating an absent pair as "this owner holds
151
139
  * no rigid bodies" — the honest reading for a world (R3F, or a bare
@@ -162,15 +150,14 @@ function readRapierHandles(owner) {
162
150
  * only *when*; this is the *what*, and it lives here because it is the runtime
163
151
  * that knows about Rapier and shared geometry.
164
152
  *
165
- * The order mirrors `adapter/setup-three-root-adapter.ts`'s world teardown for
153
+ * The order mirrors `adapter/world3d-react/r3f-root-factory.tsx`'s world teardown for
166
154
  * ONE subtree. Within the physics step,
167
155
  * `rapierWorld.removeRigidBody(body)` comes BEFORE `physics.remove(node)`: the
168
156
  * registry's `remove()` only drops index entries, so reversing the two leaks
169
157
  * the Rapier body.
170
158
  *
171
- * `owners` is every world that could own part of the subtree `createGame`
172
- * passes all of its first-party three roots as their `GameContext`, a bare
173
- * adapter mount passes its own ctx. `physics.get` is a no-op for a node the
159
+ * `owners` is every world that could own part of the subtree. `physics.get`
160
+ * is a no-op for a node the
174
161
  * owner does not own, so offering the subtree to each is safe.
175
162
  *
176
163
  * Safe on an object already removed or already disposed: `removeFromParent` on
@@ -212,13 +199,17 @@ export function disposeDebrisSubtree(obj, owners) {
212
199
  }
213
200
  }
214
201
  /**
215
- * The {@link DebrisOwner}s one registered world contributes: its `GameContext`
216
- * when the mount is first-party, else nothing. Written as a standalone function
202
+ * The {@link DebrisOwner}s one registered world contributes. Written as a
203
+ * standalone function
217
204
  * so `createGame`'s clock disposer is one line and the "which mounts count"
218
205
  * rule has exactly one home.
219
206
  */
220
- function debrisOwnersOf(world) {
221
- return isFirstPartyMounted(world.mounted) ? [world.mounted.ctx] : [];
207
+ function debrisOwnersOf(_world) {
208
+ // No mount carries first-party Rapier handles: physics is a declared
209
+ // system built inside the world's own tree, and the library owns its
210
+ // bodies' lifecycles there. The owner list stays as the disposal seam's
211
+ // shape; today it is always empty.
212
+ return [];
222
213
  }
223
214
  /**
224
215
  * Construct the (host-internal) Game shell. Callers: `createGameRuntime`
@@ -233,7 +224,7 @@ export function createGame(opts) {
233
224
  const input = new InputManager();
234
225
  const stateBridge = createStateBridge();
235
226
  // D15 (T-D15.1) — the game-scoped seeded-random surface every world's
236
- // `ctx.random` aliases (see `setup-three-root-adapter.ts`'s `ctx.random =
227
+ // `ctx.random` aliases (see `world3d-react/r3f-root-factory.tsx`'s `ctx.random =
237
228
  // ...`, wired the same way `ctx.debug` is just below). Constructed
238
229
  // unconditionally (cheap — a handful of closures) regardless of whether
239
230
  // this project ever declares `determinism.seededRandom`; only the BOOT
@@ -266,7 +257,7 @@ export function createGame(opts) {
266
257
  // the CURRENT values.
267
258
  let tick = 0;
268
259
  let simT = 0;
269
- // WO-P13 — the display-rate half. `renderAlpha` is the last alpha
260
+ // The display-rate half. `renderAlpha` is the last alpha
270
261
  // `runRenderFrameImpl` presented at (0 until a host drives one); the set is
271
262
  // the `RenderStepped`-shaped registry `Game.onRenderStep` feeds. Deliberately
272
263
  // NOT beside `tick`/`simT` in meaning: neither of these ever advances sim
@@ -282,7 +273,7 @@ export function createGame(opts) {
282
273
  //
283
274
  // The disposer is supplied HERE rather than inside the clock because
284
275
  // `core/sim-clock.ts` deliberately knows nothing about Rapier or shared
285
- // geometry. It mirrors `setup-three-root-adapter.ts`'s world teardown
276
+ // geometry. It mirrors `world3d-react/r3f-root-factory.tsx`'s world teardown
286
277
  // ordering for ONE subtree.
287
278
  const simClock = createSimClock({
288
279
  // Every mount that could own part of the subtree is offered it:
@@ -341,6 +332,10 @@ export function createGame(opts) {
341
332
  * component registration for a declared slot is shadowed (with the
342
333
  * standard warning) rather than silently winning by running later. */
343
334
  const declaredSystemAdapters = new Map();
335
+ /** Per-root POSITIVE ABSENCES from the same declaration — `absent(reason)`
336
+ * slots. Nothing binds them (there is nothing to bind); they are kept so a
337
+ * reader can tell an answered absence from an unasked question. */
338
+ const declaredAbsences = new Map();
344
339
  // 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
345
340
  function computeSystemAdapters() {
346
341
  // Debug is game-scoped: React hooks, probes, and the built-in time
@@ -425,6 +420,14 @@ export function createGame(opts) {
425
420
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: fans out TWO independent capability gates (loop, audio) with the same "call it, else report once" shape per world — splitting the two gates into separate loops would duplicate the fan-out, not reduce real complexity
426
421
  function setRootGates(next) {
427
422
  for (const world of roots) {
423
+ // A disposed world stays in `roots` (there is no `unregisterRoot`), and
424
+ // its adapter's `setPaused`/`systems.audio` reach a renderer, ticker or
425
+ // audio graph that `dispose()` already released — the same reason
426
+ // `runFrame`/`runRenderFrame`/`runTicks` skip it. Without this, a
427
+ // pause/resume after a partial teardown calls into freed resources, and
428
+ // the audio leg re-mutes a context that no longer exists.
429
+ if (world.disposed)
430
+ continue;
428
431
  if (!world.pausable)
429
432
  continue; // pausable:false roots are untouched by design
430
433
  if (world.mounted.drivesOwnLoop) {
@@ -455,14 +458,14 @@ export function createGame(opts) {
455
458
  if (rngTrapEnabled)
456
459
  rngTrap.enable();
457
460
  profiler.beginFrame();
458
- // D15/T-D15.4 + WO-P13: the render-phase skip. Two callers set it, for the
461
+ // The render-phase skip. Two callers set it, for the
459
462
  // same reason — this substep is not the thing that paints. `runTicks`'s
460
463
  // `render: 'none'|'last'` fast-forward sets it on every tick it doesn't
461
464
  // want to paint (see `runTicks`'s doc comment on `GameInternal`), and a
462
465
  // DISPLAY-RATE host sets it on every substep because `runRenderFrame`
463
- // paints once per real frame instead. Unlike `onlyFrozen` below it is no
464
- // longer internal-only: it is part of the public `GameInternal.runFrame`
465
- // signature, since an external host is now one of those two callers.
466
+ // paints once per real frame instead. Unlike `onlyFrozen` below it is not
467
+ // internal-only: it is part of the public `GameInternal.runFrame`
468
+ // signature, since an external host is one of those two callers.
466
469
  const skipRenderPhases = frameOpts?.skipRenderPhases ?? false;
467
470
  // `onlyFrozen` is internal-only (not part of the public `GameInternal.runFrame`
468
471
  // signature — no external caller sets it) — `Game.play.step()` below is the
@@ -480,6 +483,8 @@ export function createGame(opts) {
480
483
  inputFrameActive = false;
481
484
  for (let i = 0; i < n; i++) {
482
485
  const world = roots[i];
486
+ if (world.disposed)
487
+ continue;
483
488
  if (onlyFrozen) {
484
489
  if (paused && world.pausable && !world.mounted.drivesOwnLoop) {
485
490
  inputFrameActive = true;
@@ -507,6 +512,8 @@ export function createGame(opts) {
507
512
  if (!onlyFrozen) {
508
513
  for (let i = 0; i < n; i++) {
509
514
  const world = roots[i];
515
+ if (world.disposed)
516
+ continue;
510
517
  if (!world.mounted.drivesOwnLoop)
511
518
  continue;
512
519
  if (!paused || !world.pausable || !world.mounted.setPaused) {
@@ -532,6 +539,8 @@ export function createGame(opts) {
532
539
  systems.runPhase(phase, dt);
533
540
  for (let i = 0; i < n; i++) {
534
541
  const world = roots[i];
542
+ if (world.disposed)
543
+ continue;
535
544
  if (world.mounted.drivesOwnLoop)
536
545
  continue;
537
546
  if (!(paused && world.pausable))
@@ -548,6 +557,8 @@ export function createGame(opts) {
548
557
  }
549
558
  for (let i = 0; i < n; i++) {
550
559
  const world = roots[i];
560
+ if (world.disposed)
561
+ continue;
551
562
  if (world.mounted.drivesOwnLoop)
552
563
  continue;
553
564
  if (!(paused && world.pausable))
@@ -583,6 +594,8 @@ export function createGame(opts) {
583
594
  systems.runPhase(phase, dt);
584
595
  for (let i = 0; i < n; i++) {
585
596
  const world = roots[i];
597
+ if (world.disposed)
598
+ continue;
586
599
  if (world.mounted.drivesOwnLoop)
587
600
  continue;
588
601
  // D10/T7.6: a `pausable` world under an active pause
@@ -610,6 +623,8 @@ export function createGame(opts) {
610
623
  }
611
624
  for (let i = 0; i < n; i++) {
612
625
  const world = roots[i];
626
+ if (world.disposed)
627
+ continue;
613
628
  if (world.mounted.drivesOwnLoop)
614
629
  continue;
615
630
  // A fully-frozen world gets no `endFrame`/opaque-`update` call either —
@@ -665,7 +680,7 @@ export function createGame(opts) {
665
680
  rngTrap.disable();
666
681
  }
667
682
  /**
668
- * WO-P13 — one display frame's PRESENTATION pass. See
683
+ * One display frame's PRESENTATION pass. See
669
684
  * `GameInternal.runRenderFrame`'s doc comment for the contract; this is the
670
685
  * `preRender`+`render` slice of `runFrameImpl`'s phase loop, lifted out and
671
686
  * driven by the loop's own per-real-frame callback instead of by the substep
@@ -713,6 +728,8 @@ export function createGame(opts) {
713
728
  systems.runPhase(phase, displayDt);
714
729
  for (let i = 0; i < n; i++) {
715
730
  const world = roots[i];
731
+ if (world.disposed)
732
+ continue;
716
733
  if (world.mounted.drivesOwnLoop)
717
734
  continue;
718
735
  // D10/T7.6, carried over verbatim in substance: a frozen world still
@@ -761,7 +778,10 @@ export function createGame(opts) {
761
778
  for (const listener of systemAdapterListeners)
762
779
  listener();
763
780
  },
764
- installDeclaredSystemAdapters(rootId, slots) {
781
+ get declaredSystemAbsences() {
782
+ return [...declaredAbsences.values()].flat();
783
+ },
784
+ installDeclaredSystemAdapters(rootId, slots, absent = []) {
765
785
  if (!roots.some((w) => w.id === rootId)) {
766
786
  throw new Error(`installDeclaredSystemAdapters: no mounted root is named "${rootId}" ` +
767
787
  `(mounted: ${roots.map((w) => `"${w.id}"`).join(', ') || 'none'}).`);
@@ -771,6 +791,11 @@ export function createGame(opts) {
771
791
  'systems — a declaration is static and installs exactly once per mount.');
772
792
  }
773
793
  declaredSystemAdapters.set(rootId, slots);
794
+ // ALWAYS set, never merge: a re-install (an HMR of the entry's `systems`
795
+ // table) that dropped an `absent()` marker must also drop the recorded
796
+ // absence, or the coverage report keeps printing a game statement the
797
+ // game no longer makes.
798
+ declaredAbsences.set(rootId, absent);
774
799
  gameInternal.notifySystemAdaptersChanged();
775
800
  },
776
801
  input,
@@ -801,6 +826,11 @@ export function createGame(opts) {
801
826
  // not paused, nothing here runs — step() is a whole-call no-op.
802
827
  if (paused) {
803
828
  for (const world of roots) {
829
+ // Same disposed-world guard `runFrameImpl` (and `setRootGates`)
830
+ // make: a disposed world's `mounted.step` drives a loop whose
831
+ // resources are already freed.
832
+ if (world.disposed)
833
+ continue;
804
834
  if (!world.pausable || !world.mounted.drivesOwnLoop)
805
835
  continue;
806
836
  if (!world.mounted.setPaused)
@@ -826,8 +856,8 @@ export function createGame(opts) {
826
856
  // `endFrame` called once per registration) and double-dispose-wrapped
827
857
  // (`createRootInstance` wraps `mounted.dispose` in place — a second
828
858
  // wrap would flip `disposed` and call through on ITS OWN wrapped
829
- // `originalDispose`, which is harmless today only by accident of
830
- // `SetupThreeRootAdapter.dispose` being idempotent; a foreign adapter
859
+ // `originalDispose`, which would be harmless only if the adapter's
860
+ // dispose happened to be idempotent; a foreign adapter
831
861
  // has no such guarantee). Reject it outright instead.
832
862
  if (roots.some((w) => w.mounted === world.mounted)) {
833
863
  throw new Error(`Game.registerRoot: world "${world.id}" shares its \`mounted\` object with an ` +
@@ -837,14 +867,14 @@ export function createGame(opts) {
837
867
  roots.push(world);
838
868
  gameInternal.notifySystemAdaptersChanged();
839
869
  // Notify state-bridge subscribers THE INSTANT the world list changes —
840
- // not just at the next completed `runFrame`. Root-cause fix for the
841
- // "roots: " (empty) hang in `36-r3f-first-party.spec.ts` on CI (gate
842
- // 4): `mountAllRootSpecs` (`create-runtime.ts`) mounts roots
870
+ // not just at the next completed `runFrame`. Otherwise a UI that lists
871
+ // worlds hangs on an empty list: `mountAllRootSpecs`
872
+ // (`create-runtime.ts`) mounts roots
843
873
  // SEQUENTIALLY, and a react world's `adapter.mount()`
844
874
  // (`resolveDefaultReactAdapter`/`mountOneReactRoot`) renders its tree —
845
875
  // synchronously in some React builds, but React 19's concurrent
846
876
  // renderer does NOT guarantee a synchronous first commit (see
847
- // `r3f-adapter.tsx`'s own doc comment on `onCreated`) — BEFORE the
877
+ // `r3f-root-factory.tsx`'s own doc comment on `onCreated`) — BEFORE the
848
878
  // caller calls `registerRoot` for that very world. A `useWorldState`
849
879
  // selector reading `g.roots` can therefore render for the first time
850
880
  // while `roots` is still missing entries that register moments later.
@@ -888,15 +918,11 @@ export function createGame(opts) {
888
918
  // world mount), eroding the signal for a genuinely un-observable
889
919
  // ingested world.
890
920
  // A HOST-DRIVEN mount (`drivesOwnLoop: false`, notably the R3F adapter)
891
- // is observable through `Game.state` even though it does not carry the
892
- // classic scene adapter's `firstParty` brand: it ticks inside
893
- // `runFrame`, so the frame-versioned bridge covers it. Requiring a
921
+ // is observable through `Game.state` when it ticks inside
922
+ // `runFrame` the frame-versioned bridge covers it. Requiring a
894
923
  // foreign-world `observe` bridge there produces a false warning while
895
924
  // the canonical bridge is already live.
896
- if (!isFirstPartyMounted(world.mounted) &&
897
- world.mounted.drivesOwnLoop &&
898
- world.kind !== 'dom' &&
899
- !world.mounted.observe) {
925
+ if (world.mounted.drivesOwnLoop && world.kind !== 'dom' && !world.mounted.observe) {
900
926
  console.warn(`[game] world "${world.id}" (kind: ${world.kind}, adapter: "${world.adapter.id}"): ` +
901
927
  'no state bridge — this mounted game has no `observe` (RootStateObserver); ' +
902
928
  'react HUDs/useRootObservation cannot subscribe to its state.');
@@ -984,7 +1010,7 @@ export function createGame(opts) {
984
1010
  // root's `mounted.dispose()`, whereas a per-root teardown may be ending
985
1011
  // just one sub-session while sibling roots keep running (see the
986
1012
  // disposed-world guard in `runFrame`). It used to be disposed from
987
- // `setup-three-root-adapter.ts`'s teardown, which meant disposing one of
1013
+ // `world3d-react/r3f-root-factory.tsx`'s teardown, which meant disposing one of
988
1014
  // two three roots froze `now()` for the whole Game, rejected the other
989
1015
  // world's pending `delay`s and turned its `after()` calls into silent
990
1016
  // no-ops. Note the asymmetry that gives the bug away: `seededRandom` and
@@ -80,22 +80,6 @@ export declare function isAdapterRegistered(kind: string): boolean;
80
80
  * registry without cross-test leakage.
81
81
  */
82
82
  export declare function __clearAdapterSurfaceRegistryForTests(): void;
83
- /**
84
- * A ready-to-register {@link AdapterSurfaceFactory} for `kind: 'three'` roots
85
- * that follow the first-party entry-module convention (`export const
86
- * adapter` and/or `export async function setup`). Threejs is safe to
87
- * ship as an exported convenience (unlike canvas/react) because `three`/
88
- * `SetupThreeRootAdapter` are already unconditional engine dependencies —
89
- * see `mount-manifest.ts`'s header comment. Still never auto-registered:
90
- * the registry itself stays zero-policy (see this file's header comment) —
91
- * a caller opts in with `registerAdapter('three', defaultThreeAdapterFactory)`.
92
- *
93
- * Resolution mirrors `mount-manifest.ts`'s own `resolveThreeAdapter` branch
94
- * order: an entry module's `adapter` export wins outright; else its `setup`
95
- * export (wrapping via `fromSetup` happens inside `mountManifestRoots`
96
- * itself — this factory just returns the `MountEntry` shape).
97
- */
98
- export declare const defaultThreeAdapterFactory: AdapterSurfaceFactory;
99
83
  export interface MountGameOptions {
100
84
  /** Explicit per-world entries, same shape `mountManifestRoots` accepts —
101
85
  * ALWAYS wins over a registered kind factory for that world id (backward
@@ -1 +1 @@
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"}
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;AAOxF;;;;;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;AAMD,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;AA+BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,OAAO,EACtB,IAAI,EAAE,YAAY,EAClB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,WAAW,CAAC,CAqDtB"}
@@ -12,10 +12,11 @@
12
12
  // callers register, but it registers NONE itself. In particular there is no
13
13
  // built-in 'canvas'/'react' registration here (that would require this file
14
14
  // to value-import `pixi.js`/`react`/`react-dom`, exactly what `mount-manifest
15
- // .ts` forbids); a project that has a canvas or react world MUST register a
16
- // factory for that kind itself — see `defaultThreeAdapterFactory` below for why
17
- // even the 'three' convenience export is a plain function the CALLER
18
- // registers, not something this module wires up automatically.
15
+ // .ts` forbids); a project that has a three, canvas, or react world MUST
16
+ // register a factory for that kind itself — the factories live with the
17
+ // modules that own their dependencies (`r3fRootFactory` in
18
+ // `@engine/world3d-react`, its Pixi twin in `@engine/canvas-react`), never
19
+ // wired up here automatically.
19
20
  import { declaredRoots } from '../adapter/manifest-interpreter';
20
21
  import { installNativeDebugBindings, installNativeSystemsBindings, nativeDebugBindingFromEntryModule, nativeSystemsBindingFromEntryModule, } from '../adapter/native-debug-module';
21
22
  import { publishDevInstruments } from '../dev/instruments';
@@ -63,44 +64,12 @@ export function isAdapterRegistered(kind) {
63
64
  export function __clearAdapterSurfaceRegistryForTests() {
64
65
  registry.clear();
65
66
  }
66
- /**
67
- * A ready-to-register {@link AdapterSurfaceFactory} for `kind: 'three'` roots
68
- * that follow the first-party entry-module convention (`export const
69
- * adapter` and/or `export async function setup`). Threejs is safe to
70
- * ship as an exported convenience (unlike canvas/react) because `three`/
71
- * `SetupThreeRootAdapter` are already unconditional engine dependencies —
72
- * see `mount-manifest.ts`'s header comment. Still never auto-registered:
73
- * the registry itself stays zero-policy (see this file's header comment) —
74
- * a caller opts in with `registerAdapter('three', defaultThreeAdapterFactory)`.
75
- *
76
- * Resolution mirrors `mount-manifest.ts`'s own `resolveThreeAdapter` branch
77
- * order: an entry module's `adapter` export wins outright; else its `setup`
78
- * export (wrapping via `fromSetup` happens inside `mountManifestRoots`
79
- * itself — this factory just returns the `MountEntry` shape).
80
- */
81
- export const defaultThreeAdapterFactory = (world, ctx) => {
82
- const mod = ctx.entryModule;
83
- if (mod?.adapter)
84
- return { kind: 'three', adapter: mod.adapter };
85
- if (mod?.setup)
86
- return { kind: 'three', setup: mod.setup };
87
- if (world.entry !== undefined) {
88
- throw new Error(`defaultThreeAdapterFactory: entry module "${world.entry}" for world "${world.id}" exports ` +
89
- 'neither `adapter` nor `setup` — every first-party entry module exports at least one ' +
90
- '(export one from the declared entry module).');
91
- }
92
- throw new Error(`defaultThreeAdapterFactory: world "${world.id}" declares no \`entry\` — a three root is ` +
93
- 'authored as a TSX/R3F world module; point `entry` at it.');
94
- };
95
67
  /** True for the one shape `mountManifestRoots` can ALREADY mount with zero
96
68
  * `entries[id]` at all.
97
69
  *
98
- * WO-8: nothing is self-sufficient any more. The one shape that was — a plain
99
- * `default`-adapter, SCENE-driven, no-`entry` three world, which
100
- * `resolveThreeAdapter`'s scene branch could mount from the manifest alone —
101
- * died with the `.vscn.json` format. `load.ts` now rejects a three root with no
70
+ * NOTHING is self-sufficient: `load.ts` rejects a three root with no
102
71
  * `entry` outright, so every world needs a registered factory or an explicit
103
- * entry, and this predicate is retained only to keep the loud-degrade error the
72
+ * entry. This predicate is retained so the loud-degrade error stays the
104
73
  * documented outcome rather than a silent skip. */
105
74
  function worldIsSelfSufficient(_world) {
106
75
  return false;
@@ -164,7 +133,7 @@ export async function mountGameFromManifest(manifestInput, host, opts = {}) {
164
133
  throw new Error(`mountGameFromManifest: root "${world.id}" (adapter "${world.adapter.identity}") has no registered ` +
165
134
  `adapter factory and no explicit entries["${world.id}"] — call ` +
166
135
  `registerAdapter("${world.adapter.identity}", factory) before mounting (see ` +
167
- '`defaultThreeAdapterFactory` for a worked three example), or pass ' +
136
+ '`r3fRootFactory` in `@vgai/engine/world3d-react` for the worked three factory), or pass ' +
168
137
  `opts.entries["${world.id}"] directly (see mount-manifest.ts's \`MountEntry\`).`);
169
138
  }
170
139
  const session = await mountManifestRoots({
@@ -1,8 +1,9 @@
1
+ import type { RootDeclaration } from '../adapter/binding';
1
2
  import type { RootAdapter } from '../adapter/root-adapter';
2
3
  import { type ResolvedGameManifest } from '../manifest/load';
3
4
  import { type GameSession } from './create-runtime';
4
5
  import { type DebugBridgeWindowTarget } from './debug-bridge';
5
- import type { GameSetupFn, PlaytestContext } from './types';
6
+ import type { PlaytestContext } from './playtest';
6
7
  /**
7
8
  * A caller-supplied entry for a `kind: 'three'` world — two ways to satisfy
8
9
  * it, matching the two shapes `resolveDefaultThreeAdapter` supports (an
@@ -11,20 +12,27 @@ import type { GameSetupFn, PlaytestContext } from './types';
11
12
  * - `{ adapter }` — a fully-constructed {@link RootAdapter} (first-party or
12
13
  * not). Always wins if present, regardless of the world's `entry` field —
13
14
  * full caller control, including for a `{ module }`-adapter world
14
- * (mountManifestRoots cannot import an arbitrary module path itself).
15
- * - `{ setup }` — for an `entry`-declaring world: the project's own
16
- * `entry` module's exported `setup` function (the same `GameSetupFn`
17
- * shape `loadProjectScripts` extracts editor-side). Wrapped in a
18
- * `SetupThreeRootAdapter` here, mirroring `resolveDefaultThreeAdapter`'s
19
- * entry branch exactly.
20
- *
21
- * The former third shape, `{ componentRegistry }` for a `scene`-declaring
22
- * world, went with the `.vscn.json` format in WO-8.
15
+ * (mountManifestRoots cannot import an arbitrary module path itself
16
+ * for a default-exported world, build the adapter with
17
+ * `resolveR3FEntryAdapter(entryModule, worldId)` from
18
+ * `@vgai/engine/world3d-react` and pass it here).
23
19
  */
24
- export interface ThreeMountEntry {
20
+ export interface ThreeMountEntry extends MountEntryDeclaration {
25
21
  readonly kind: 'three';
26
22
  readonly adapter?: RootAdapter | undefined;
27
- readonly setup?: GameSetupFn | undefined;
23
+ }
24
+ /**
25
+ * The half of a root's binding declaration a CALLER holds — everything in
26
+ * `adapter/binding.ts`'s {@link RootDeclaration} except `root`, which this
27
+ * file already has from the manifest it just resolved.
28
+ *
29
+ * Optional throughout, and absent is the honest state for a caller who built
30
+ * an adapter by hand out of its own module graph: there is no entry namespace
31
+ * to report a static surface for, so the root registers with `binding: null`
32
+ * rather than one describing a module nobody loaded.
33
+ */
34
+ export interface MountEntryDeclaration {
35
+ readonly declaration?: Omit<RootDeclaration, 'root'> | undefined;
28
36
  }
29
37
  /**
30
38
  * A caller-supplied entry for a `kind: 'canvas'` world — ALWAYS a
@@ -34,7 +42,7 @@ export interface ThreeMountEntry {
34
42
  * `pixi.js`, which it deliberately never does (see this file's header
35
43
  * comment).
36
44
  */
37
- export interface PixiMountEntry {
45
+ export interface PixiMountEntry extends MountEntryDeclaration {
38
46
  readonly kind: 'canvas';
39
47
  readonly adapter: RootAdapter<'canvas'>;
40
48
  }
@@ -51,7 +59,7 @@ export interface PixiMountEntry {
51
59
  * itself (see this file's header comment) — building the adapter is
52
60
  * entirely the caller's job.
53
61
  */
54
- export interface ReactMountEntry {
62
+ export interface ReactMountEntry extends MountEntryDeclaration {
55
63
  readonly kind: 'dom';
56
64
  readonly adapter: RootAdapter<'dom'>;
57
65
  }
@@ -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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"}
@@ -1,8 +1,8 @@
1
1
  // The standalone manifest-mount helper: an ENGINE-side generalization of
2
2
  // `examples/tri-world/src/main.ts`'s hand-built `RootMountSpec[]`.
3
3
  //
4
- // `resolveAllRoots`/`resolveRootAdapter` (`packages/editor/src/
5
- // adapter-resolver.ts`) already do this translation for the EDITOR, but they
4
+ // `resolveAllRoots`/`resolveRootBinding` (`packages/editor/src/
5
+ // binding-resolver.ts`) already do this translation for the EDITOR, but they
6
6
  // are Vite-coupled by construction (`/@fs/` dynamic imports of project files
7
7
  // through the dev server, §0.1/§0.5 of the design doc) — unusable from a
8
8
  // plain static build. This module mirrors their per-kind dispatch
@@ -17,16 +17,12 @@
17
17
  // type-only import): this file never value-imports
18
18
  // `pixi.js`, `react`, or `react-dom` — a
19
19
  // canvas or react world's adapter is ALWAYS supplied already-constructed via
20
- // `entries[id].adapter` (the caller's own module graph built it). Threejs is
21
- // different: `three`/
22
- // `SetupThreeRootAdapter` are already unconditional dependencies of every
23
- // caller of `createGameRuntime`, so wrapping a `setup` with
24
- // `fromSetup` here adds no NEW bundle weight — only pixi/react are avoided.
20
+ // `entries[id].adapter` (the caller's own module graph built it), so no
21
+ // surface's library is pulled into a game that has no world on it.
25
22
  import { assertNever } from '../adapter/adapter-surface';
26
23
  import { declaredRoots } from '../adapter/manifest-interpreter';
27
24
  // Value-imported from the implementer's OWN path, not the type-only
28
25
  // `../adapter` barrel (P-6).
29
- import { fromSetup } from '../adapter/setup-three-root-adapter';
30
26
  import { loadGameManifest, } from '../manifest/load';
31
27
  import { createGameRuntime } from './create-runtime';
32
28
  import { maybeInstallDebugBridge } from './debug-bridge';
@@ -104,8 +100,8 @@ export function resolveManifest(raw) {
104
100
  return loadGameManifest(raw);
105
101
  }
106
102
  // ---------------------------------------------------------------------------
107
- // Per-kind entry -> adapter resolution (mirrors `resolveRootAdapter`'s
108
- // per-identity dispatch, `packages/editor/src/adapter-resolver.ts`)
103
+ // Per-kind entry -> adapter resolution (mirrors `resolveRootBinding`'s
104
+ // per-identity dispatch, `packages/editor/src/binding-resolver.ts`)
109
105
  // ---------------------------------------------------------------------------
110
106
  function resolveThreeAdapter(world, entry) {
111
107
  if (entry?.adapter)
@@ -125,17 +121,15 @@ function resolveThreeAdapter(world, entry) {
125
121
  }
126
122
  // type === 'default'
127
123
  if (world.entry !== undefined) {
128
- if (!entry?.setup) {
129
- throw new Error(`mountManifestRoots: world "${world.id}" (three) declares \`entry\` "${world.entry}" ` +
130
- `— supply entries["${world.id}"] = { kind: 'three', setup } (the entry module's ` +
131
- "exported `setup` function) or { kind: 'three', adapter } for full control. Got " +
132
- `${entry === undefined ? 'no entry at all' : 'an entry with neither `setup` nor `adapter`'}.`);
133
- }
134
- return fromSetup(world.id, entry.setup);
124
+ throw new Error(`mountManifestRoots: world "${world.id}" (three) declares \`entry\` "${world.entry}" ` +
125
+ `— supply entries["${world.id}"] = { kind: 'three', adapter } (for a default-exported ` +
126
+ 'world, build it with `resolveR3FEntryAdapter(entryModule, worldId)` from ' +
127
+ '`@vgai/engine/world3d-react`). Got ' +
128
+ `${entry === undefined ? 'no entry at all' : 'an entry with no `adapter`'}.`);
135
129
  }
136
130
  // Unreachable in practice: `load.ts`'s `checkAdapterSceneEntryRules` requires
137
131
  // `entry` for every 'default' THREE adapter world at manifest-load time (and
138
- // rejects `scene` outright the `.vscn.json` format was removed in WO-8).
132
+ // rejects any other content declaration on one outright).
139
133
  throw new Error(`mountManifestRoots: world "${world.id}" is default-three with no \`entry\` — this ` +
140
134
  'should have been rejected by manifest validation.');
141
135
  }
@@ -167,6 +161,12 @@ function buildRootMountSpec(world, entry) {
167
161
  id: world.id,
168
162
  zOrder: world.zOrder,
169
163
  pausable: world.pausable,
164
+ // `root` is this file's own resolved manifest record; the rest — the
165
+ // parsed `vgai.adapter.ts`, the entry namespace, the entry's declared
166
+ // debug/systems bindings — only the caller who loaded the entry can know.
167
+ ...(entry?.declaration === undefined
168
+ ? {}
169
+ : { declaration: { root: world, ...entry.declaration } }),
170
170
  };
171
171
  // `entry`'s `kind` is guaranteed to agree with `world.kind` past the guard
172
172
  // above (or `entry` is `undefined`) — TS can't narrow a `Record` lookup
@@ -0,0 +1,22 @@
1
+ /**
2
+ * WHO IS PLAYING, and under what identity — the host's own declaration for one
3
+ * private play run or coordinated team test.
4
+ *
5
+ * Its own module because it is a PUBLISHED path: a project's Colyseus
6
+ * networking adapter (the `colyseus` capability, copied into every game) names
7
+ * this type, so it must live somewhere that survives. The engine never joins a
8
+ * room and never couples this authoring identity to a networking library —
9
+ * games may pass `roomKey` as a Colyseus filter/join option, and that is the
10
+ * whole of the coupling.
11
+ */
12
+ /** Host-supplied identity for one private play run or coordinated team test.
13
+ * Games may pass `roomKey` as a Colyseus filter/join option; the engine never
14
+ * joins a room or couples this authoring identity to a networking library. */
15
+ export interface PlaytestContext {
16
+ readonly mode: 'private' | 'team';
17
+ readonly id: string;
18
+ readonly roomKey: string;
19
+ readonly revision: number | null;
20
+ readonly participantId: string | null;
21
+ }
22
+ //# sourceMappingURL=playtest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playtest.d.ts","sourceRoot":"","sources":["../../src/runtime/playtest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;8EAE8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC"}