@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
@@ -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
 
20
21
  import { declaredRoots } from '../adapter/manifest-interpreter';
21
22
  import {
@@ -26,12 +27,10 @@ import {
26
27
  nativeDebugBindingFromEntryModule,
27
28
  nativeSystemsBindingFromEntryModule,
28
29
  } from '../adapter/native-debug-module';
29
- import type { RootAdapter } from '../adapter/root-adapter';
30
30
  import { publishDevInstruments } from '../dev/instruments';
31
31
  import type { ResolvedAdapterRoot } from '../manifest/load';
32
32
  import type { GameSession } from './create-runtime';
33
33
  import { type MountEntry, mountManifestRoots, resolveManifest } from './mount-manifest';
34
- import type { GameSetupFn } from './types';
35
34
  import { assertExportedOrInEditor } from './unexported-game-trap';
36
35
 
37
36
  // ---------------------------------------------------------------------------
@@ -149,50 +148,6 @@ export function __clearAdapterSurfaceRegistryForTests(): void {
149
148
  registry.clear();
150
149
  }
151
150
 
152
- // ---------------------------------------------------------------------------
153
- // `defaultThreeAdapterFactory` — an OPT-IN convenience, never auto-registered
154
- // ---------------------------------------------------------------------------
155
-
156
- /** The entry-module export shape every first-party entry module follows
157
- * (an explicit world entry module, including `examples/*` projects'
158
- * `src/index.ts` — see CLAUDE.md's "Adding an example project"). */
159
- interface ThreeEntryModuleExports {
160
- readonly adapter?: RootAdapter;
161
- readonly setup?: GameSetupFn;
162
- }
163
-
164
- /**
165
- * A ready-to-register {@link AdapterSurfaceFactory} for `kind: 'three'` roots
166
- * that follow the first-party entry-module convention (`export const
167
- * adapter` and/or `export async function setup`). Threejs is safe to
168
- * ship as an exported convenience (unlike canvas/react) because `three`/
169
- * `SetupThreeRootAdapter` are already unconditional engine dependencies —
170
- * see `mount-manifest.ts`'s header comment. Still never auto-registered:
171
- * the registry itself stays zero-policy (see this file's header comment) —
172
- * a caller opts in with `registerAdapter('three', defaultThreeAdapterFactory)`.
173
- *
174
- * Resolution mirrors `mount-manifest.ts`'s own `resolveThreeAdapter` branch
175
- * order: an entry module's `adapter` export wins outright; else its `setup`
176
- * export (wrapping via `fromSetup` happens inside `mountManifestRoots`
177
- * itself — this factory just returns the `MountEntry` shape).
178
- */
179
- export const defaultThreeAdapterFactory: AdapterSurfaceFactory = (world, ctx) => {
180
- const mod = ctx.entryModule as ThreeEntryModuleExports | undefined;
181
- if (mod?.adapter) return { kind: 'three', adapter: mod.adapter };
182
- if (mod?.setup) return { kind: 'three', setup: mod.setup };
183
- if (world.entry !== undefined) {
184
- throw new Error(
185
- `defaultThreeAdapterFactory: entry module "${world.entry}" for world "${world.id}" exports ` +
186
- 'neither `adapter` nor `setup` — every first-party entry module exports at least one ' +
187
- '(export one from the declared entry module).',
188
- );
189
- }
190
- throw new Error(
191
- `defaultThreeAdapterFactory: world "${world.id}" declares no \`entry\` — a three root is ` +
192
- 'authored as a TSX/R3F world module; point `entry` at it.',
193
- );
194
- };
195
-
196
151
  // ---------------------------------------------------------------------------
197
152
  // The composer
198
153
  // ---------------------------------------------------------------------------
@@ -208,12 +163,9 @@ export interface MountGameOptions {
208
163
  /** True for the one shape `mountManifestRoots` can ALREADY mount with zero
209
164
  * `entries[id]` at all.
210
165
  *
211
- * WO-8: nothing is self-sufficient any more. The one shape that was — a plain
212
- * `default`-adapter, SCENE-driven, no-`entry` three world, which
213
- * `resolveThreeAdapter`'s scene branch could mount from the manifest alone —
214
- * died with the `.vscn.json` format. `load.ts` now rejects a three root with no
166
+ * NOTHING is self-sufficient: `load.ts` rejects a three root with no
215
167
  * `entry` outright, so every world needs a registered factory or an explicit
216
- * entry, and this predicate is retained only to keep the loud-degrade error the
168
+ * entry. This predicate is retained so the loud-degrade error stays the
217
169
  * documented outcome rather than a silent skip. */
218
170
  function worldIsSelfSufficient(_world: ResolvedAdapterRoot): boolean {
219
171
  return false;
@@ -292,7 +244,7 @@ export async function mountGameFromManifest(
292
244
  `mountGameFromManifest: root "${world.id}" (adapter "${world.adapter.identity}") has no registered ` +
293
245
  `adapter factory and no explicit entries["${world.id}"] — call ` +
294
246
  `registerAdapter("${world.adapter.identity}", factory) before mounting (see ` +
295
- '`defaultThreeAdapterFactory` for a worked three example), or pass ' +
247
+ '`r3fRootFactory` in `@vgai/engine/world3d-react` for the worked three factory), or pass ' +
296
248
  `opts.entries["${world.id}"] directly (see mount-manifest.ts's \`MountEntry\`).`,
297
249
  );
298
250
  }
@@ -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,18 +17,15 @@
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
 
26
23
  import { assertNever } from '../adapter/adapter-surface';
24
+ import type { RootDeclaration } from '../adapter/binding';
27
25
  import { declaredRoots } from '../adapter/manifest-interpreter';
28
26
  import type { RootAdapter } from '../adapter/root-adapter';
29
27
  // Value-imported from the implementer's OWN path, not the type-only
30
28
  // `../adapter` barrel (P-6).
31
- import { fromSetup } from '../adapter/setup-three-root-adapter';
32
29
  import {
33
30
  loadGameManifest,
34
31
  type ResolvedAdapterRoot,
@@ -38,8 +35,8 @@ import { createGameRuntime, type GameSession, type RootMountSpec } from './creat
38
35
  import { type DebugBridgeWindowTarget, maybeInstallDebugBridge } from './debug-bridge';
39
36
  import { getDebugRegistry } from './debug-registry';
40
37
  import { getGameplayRngTrapControl } from './gameplay-rng-trap';
38
+ import type { PlaytestContext } from './playtest';
41
39
  import { RENDER_SEED_QUERY_PARAM } from './render-seed';
42
- import type { GameSetupFn, PlaytestContext } from './types';
43
40
 
44
41
  // ---------------------------------------------------------------------------
45
42
  // The `entries` contract
@@ -53,20 +50,28 @@ import type { GameSetupFn, PlaytestContext } from './types';
53
50
  * - `{ adapter }` — a fully-constructed {@link RootAdapter} (first-party or
54
51
  * not). Always wins if present, regardless of the world's `entry` field —
55
52
  * full caller control, including for a `{ module }`-adapter world
56
- * (mountManifestRoots cannot import an arbitrary module path itself).
57
- * - `{ setup }` — for an `entry`-declaring world: the project's own
58
- * `entry` module's exported `setup` function (the same `GameSetupFn`
59
- * shape `loadProjectScripts` extracts editor-side). Wrapped in a
60
- * `SetupThreeRootAdapter` here, mirroring `resolveDefaultThreeAdapter`'s
61
- * entry branch exactly.
62
- *
63
- * The former third shape, `{ componentRegistry }` for a `scene`-declaring
64
- * world, went with the `.vscn.json` format in WO-8.
53
+ * (mountManifestRoots cannot import an arbitrary module path itself
54
+ * for a default-exported world, build the adapter with
55
+ * `resolveR3FEntryAdapter(entryModule, worldId)` from
56
+ * `@vgai/engine/world3d-react` and pass it here).
65
57
  */
66
- export interface ThreeMountEntry {
58
+ export interface ThreeMountEntry extends MountEntryDeclaration {
67
59
  readonly kind: 'three';
68
60
  readonly adapter?: RootAdapter | undefined;
69
- readonly setup?: GameSetupFn | undefined;
61
+ }
62
+
63
+ /**
64
+ * The half of a root's binding declaration a CALLER holds — everything in
65
+ * `adapter/binding.ts`'s {@link RootDeclaration} except `root`, which this
66
+ * file already has from the manifest it just resolved.
67
+ *
68
+ * Optional throughout, and absent is the honest state for a caller who built
69
+ * an adapter by hand out of its own module graph: there is no entry namespace
70
+ * to report a static surface for, so the root registers with `binding: null`
71
+ * rather than one describing a module nobody loaded.
72
+ */
73
+ export interface MountEntryDeclaration {
74
+ readonly declaration?: Omit<RootDeclaration, 'root'> | undefined;
70
75
  }
71
76
 
72
77
  /**
@@ -77,7 +82,7 @@ export interface ThreeMountEntry {
77
82
  * `pixi.js`, which it deliberately never does (see this file's header
78
83
  * comment).
79
84
  */
80
- export interface PixiMountEntry {
85
+ export interface PixiMountEntry extends MountEntryDeclaration {
81
86
  readonly kind: 'canvas';
82
87
  readonly adapter: RootAdapter<'canvas'>;
83
88
  }
@@ -95,7 +100,7 @@ export interface PixiMountEntry {
95
100
  * itself (see this file's header comment) — building the adapter is
96
101
  * entirely the caller's job.
97
102
  */
98
- export interface ReactMountEntry {
103
+ export interface ReactMountEntry extends MountEntryDeclaration {
99
104
  readonly kind: 'dom';
100
105
  readonly adapter: RootAdapter<'dom'>;
101
106
  }
@@ -244,8 +249,8 @@ export function resolveManifest(raw: unknown): ResolvedGameManifest {
244
249
  }
245
250
 
246
251
  // ---------------------------------------------------------------------------
247
- // Per-kind entry -> adapter resolution (mirrors `resolveRootAdapter`'s
248
- // per-identity dispatch, `packages/editor/src/adapter-resolver.ts`)
252
+ // Per-kind entry -> adapter resolution (mirrors `resolveRootBinding`'s
253
+ // per-identity dispatch, `packages/editor/src/binding-resolver.ts`)
249
254
  // ---------------------------------------------------------------------------
250
255
 
251
256
  function resolveThreeAdapter(
@@ -274,19 +279,17 @@ function resolveThreeAdapter(
274
279
 
275
280
  // type === 'default'
276
281
  if (world.entry !== undefined) {
277
- if (!entry?.setup) {
278
- throw new Error(
279
- `mountManifestRoots: world "${world.id}" (three) declares \`entry\` "${world.entry}" ` +
280
- `— supply entries["${world.id}"] = { kind: 'three', setup } (the entry module's ` +
281
- "exported `setup` function) or { kind: 'three', adapter } for full control. Got " +
282
- `${entry === undefined ? 'no entry at all' : 'an entry with neither `setup` nor `adapter`'}.`,
283
- );
284
- }
285
- return fromSetup(world.id, entry.setup);
282
+ throw new Error(
283
+ `mountManifestRoots: world "${world.id}" (three) declares \`entry\` "${world.entry}" ` +
284
+ `— supply entries["${world.id}"] = { kind: 'three', adapter } (for a default-exported ` +
285
+ 'world, build it with `resolveR3FEntryAdapter(entryModule, worldId)` from ' +
286
+ '`@vgai/engine/world3d-react`). Got ' +
287
+ `${entry === undefined ? 'no entry at all' : 'an entry with no `adapter`'}.`,
288
+ );
286
289
  }
287
290
  // Unreachable in practice: `load.ts`'s `checkAdapterSceneEntryRules` requires
288
291
  // `entry` for every 'default' THREE adapter world at manifest-load time (and
289
- // rejects `scene` outright the `.vscn.json` format was removed in WO-8).
292
+ // rejects any other content declaration on one outright).
290
293
  throw new Error(
291
294
  `mountManifestRoots: world "${world.id}" is default-three with no \`entry\` — this ` +
292
295
  'should have been rejected by manifest validation.',
@@ -337,6 +340,12 @@ function buildRootMountSpec(
337
340
  id: world.id,
338
341
  zOrder: world.zOrder,
339
342
  pausable: world.pausable,
343
+ // `root` is this file's own resolved manifest record; the rest — the
344
+ // parsed `vgai.adapter.ts`, the entry namespace, the entry's declared
345
+ // debug/systems bindings — only the caller who loaded the entry can know.
346
+ ...(entry?.declaration === undefined
347
+ ? {}
348
+ : { declaration: { root: world, ...entry.declaration } }),
340
349
  };
341
350
 
342
351
  // `entry`'s `kind` is guaranteed to agree with `world.kind` past the guard
@@ -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
+
13
+ /** Host-supplied identity for one private play run or coordinated team test.
14
+ * Games may pass `roomKey` as a Colyseus filter/join option; the engine never
15
+ * joins a room or couples this authoring identity to a networking library. */
16
+ export interface PlaytestContext {
17
+ readonly mode: 'private' | 'team';
18
+ readonly id: string;
19
+ readonly roomKey: string;
20
+ readonly revision: number | null;
21
+ readonly participantId: string | null;
22
+ }
@@ -48,9 +48,8 @@ export interface GameStateBridge {
48
48
  export interface GameStateBridgeInternal extends GameStateBridge {
49
49
  /** Bump `frameVersion` by one and notify every current subscriber, in
50
50
  * subscription order. Subscriber errors are isolated (per-subscriber
51
- * try/catch, loud `console.error`, never swallowed silently) — mirrors
52
- * the error-isolation idiom in `ecs/component-manager.ts`'s per-component
53
- * `update()` calls: one offending subscriber must not stop its siblings
51
+ * try/catch, loud `console.error`, never swallowed silently): one
52
+ * offending subscriber must not stop its siblings
54
53
  * from being notified, and must not break the frame loop. */
55
54
  bump(): void;
56
55
  }
@@ -84,6 +83,7 @@ export function createStateBridge(): GameStateBridgeInternal {
84
83
  try {
85
84
  onFrame();
86
85
  } catch (err) {
86
+ // biome-ignore lint/suspicious/noConsole: a throwing subscriber must not take the notify loop down, and the console (captured by the editor session ledger) is the engine runtime's one report channel.
87
87
  console.error('[state-bridge] subscriber threw:', err);
88
88
  }
89
89
  }
@@ -1,4 +1,5 @@
1
1
  import * as THREE from 'three';
2
+ import { type AudioBusMixer, createAudioBusMixer } from '../audio/bus-mixer';
2
3
 
3
4
  export interface AudioContext {
4
5
  listener: THREE.AudioListener;
@@ -8,10 +9,24 @@ export interface AudioContext {
8
9
  sfx: GainNode;
9
10
  voice: GainNode;
10
11
  };
12
+ /**
13
+ * The named-bus mixer the three below are buses OF (`../audio/bus-mixer.ts`).
14
+ *
15
+ * `buses` is a fixed struct because those three names are the ones the engine
16
+ * itself routes; a game with an `ambience`, a `ui` or a per-character bus asks
17
+ * the mixer for it by name — `audio.mixer.bus('ambience', 'master')` mints it
18
+ * under the master gain, `audio.mixer.setDb('ambience', -6)` sets it in
19
+ * decibels — and `audio.mixer.disconnect()` is the ONE teardown for all of
20
+ * them, the three struct members included.
21
+ */
22
+ mixer: AudioBusMixer;
11
23
  /** Call this on first user interaction (click/key) to resume audio context */
12
24
  resume: () => void;
13
25
  }
14
26
 
27
+ /** The bus every other bus routes into, and the node `masterGain` is. */
28
+ const MASTER_BUS = 'master';
29
+
15
30
  /**
16
31
  * Creates the audio listener and bus hierarchy.
17
32
  *
@@ -23,25 +38,19 @@ export function setupAudio(camera: THREE.Camera): AudioContext {
23
38
  camera.add(listener);
24
39
 
25
40
  const ctx = listener.context;
26
- const masterGain = ctx.createGain();
27
- masterGain.connect(ctx.destination);
41
+ const mixer = createAudioBusMixer({ context: ctx, destination: ctx.destination });
42
+ const masterGain = mixer.bus(MASTER_BUS);
28
43
 
29
44
  // Route the Three.js listener through masterGain so that THREE.Audio /
30
45
  // THREE.PositionalAudio objects are also silenced by the mute button.
31
46
  listener.gain.disconnect();
32
47
  listener.gain.connect(masterGain);
33
48
 
34
- const musicGain = ctx.createGain();
49
+ const musicGain = mixer.bus('music', MASTER_BUS);
35
50
  musicGain.gain.value = 0.7;
36
- musicGain.connect(masterGain);
37
-
38
- const sfxGain = ctx.createGain();
39
- sfxGain.gain.value = 1.0;
40
- sfxGain.connect(masterGain);
41
51
 
42
- const voiceGain = ctx.createGain();
43
- voiceGain.gain.value = 1.0;
44
- voiceGain.connect(masterGain);
52
+ const sfxGain = mixer.bus('sfx', MASTER_BUS);
53
+ const voiceGain = mixer.bus('voice', MASTER_BUS);
45
54
 
46
55
  return {
47
56
  listener,
@@ -51,6 +60,7 @@ export function setupAudio(camera: THREE.Camera): AudioContext {
51
60
  sfx: sfxGain,
52
61
  voice: voiceGain,
53
62
  },
63
+ mixer,
54
64
  resume() {
55
65
  if (ctx.state === 'suspended') {
56
66
  ctx.resume();
@@ -9,7 +9,7 @@ import {
9
9
  DepthOfFieldEffect,
10
10
  DotScreenEffect,
11
11
  type Effect,
12
- EffectComposer,
12
+ type EffectComposer,
13
13
  EffectPass,
14
14
  GlitchEffect,
15
15
  GodRaysEffect,
@@ -42,13 +42,6 @@ import { DEFAULTS } from '../defaults';
42
42
  import { detectKtx2Support } from '../loader';
43
43
  import { type RenderScope, resolveRenderSettings } from '../render/render-settings';
44
44
 
45
- export interface RendererContext {
46
- renderer: THREE.WebGLRenderer;
47
- scene: THREE.Scene;
48
- camera: THREE.PerspectiveCamera;
49
- composer: EffectComposer;
50
- }
51
-
52
45
  /**
53
46
  * Apply the live renderer-level render settings (shadows, resolution scale) from
54
47
  * the resolved cascade. `antialias`/`backend` are reload-only (renderer re-init)
@@ -73,7 +66,7 @@ export function applyRendererSettings(
73
66
  /**
74
67
  * Create ONLY the WebGL renderer. The HOST owns the renderer (see
75
68
  * `ThreeHostContext.renderer`); the game/adapter owns the scene/camera/composer it
76
- * renders into. Split out of `setupRenderer` for the adapter inversion.
69
+ * renders into.
77
70
  *
78
71
  * `rendering` is the scene-level render scope (`env.rendering`); it seeds the
79
72
  * reload-only `antialias` option at construction and the live shadow/resolution
@@ -118,58 +111,6 @@ export function createHostRenderer(
118
111
  return renderer;
119
112
  }
120
113
 
121
- /**
122
- * Create the scene, camera, and postprocessing composer that a first-party game
123
- * renders into, given a host-provided renderer. The GPU-only `composer` is
124
- * created here; a headless host (no GPU) skips this entirely.
125
- */
126
- export function createSceneView(
127
- renderer: THREE.WebGLRenderer,
128
- width = window.innerWidth,
129
- height = window.innerHeight,
130
- ): { scene: THREE.Scene; camera: THREE.PerspectiveCamera; composer: EffectComposer } {
131
- const safeWidth = Math.max(1, width);
132
- const safeHeight = Math.max(1, height);
133
- const scene = new THREE.Scene();
134
- scene.background = new THREE.Color(0x1a1a2e);
135
-
136
- const camera = new THREE.PerspectiveCamera(
137
- DEFAULTS.camera.fov,
138
- safeWidth / safeHeight,
139
- DEFAULTS.camera.near,
140
- DEFAULTS.camera.far,
141
- );
142
- camera.position.set(0, 5, 10);
143
- camera.lookAt(0, 0, 0);
144
-
145
- const composer = new EffectComposer(renderer);
146
- composer.addPass(new RenderPass(scene, camera));
147
- composer.addPass(
148
- new EffectPass(
149
- camera,
150
- new BloomEffect({ luminanceThreshold: DEFAULTS.postProcessing.bloom.luminanceThreshold }),
151
- ),
152
- );
153
-
154
- return { scene, camera, composer };
155
- }
156
-
157
- /**
158
- * Creates the Three.js renderer, scene, camera, and postprocessing pipeline.
159
- *
160
- * This is direct Three.js setup — no abstraction. Edit freely. (Now a thin
161
- * combination of {@link createHostRenderer} + {@link createSceneView}.)
162
- */
163
- export function setupRenderer(
164
- canvas: HTMLCanvasElement,
165
- width = window.innerWidth,
166
- height = window.innerHeight,
167
- ): RendererContext {
168
- const renderer = createHostRenderer(canvas, width, height);
169
- const { scene, camera, composer } = createSceneView(renderer, width, height);
170
- return { renderer, scene, camera, composer };
171
- }
172
-
173
114
  const toneMappingModes: Record<string, THREE.ToneMapping> = {
174
115
  none: THREE.NoToneMapping,
175
116
  linear: THREE.LinearToneMapping,
@@ -18,13 +18,13 @@
18
18
  *
19
19
  * ## Why this is NOT in `mount-game.ts`
20
20
  *
21
- * `defaultThreeAdapterFactory` lives beside the registry, and the registry
22
- * module is deliberately dependency-free: its own doc notes threejs is safe to
23
- * ship there because `three` is already an unconditional engine dependency.
24
- * `@react-three/fiber` is NOT it is the PROJECT's dependency, and
25
- * `world3d-react` is the opt-in module that owns it. Putting this factory
26
- * there would make R3F unconditional for every game, including ones with no
27
- * React at all.
21
+ * The adapter registry module is deliberately dependency-free beyond `three`
22
+ * (already an unconditional engine dependency). `@react-three/fiber` is NOT
23
+ * it is the PROJECT's dependency, and `world3d-react` is the opt-in module
24
+ * that owns it. Putting this factory beside the registry would make R3F
25
+ * unconditional for every game, including ones with no React at all; instead
26
+ * each project's `main.ts` registers it (`registerAdapter('three',
27
+ * r3fRootFactory)`).
28
28
  *
29
29
  * ## The mount mechanics (fiber v9, host-gated)
30
30
  *