@vgai/engine 0.5.15 → 0.5.16

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 (174) hide show
  1. package/dist/adapter/adapter-module.d.ts +228 -17
  2. package/dist/adapter/adapter-module.d.ts.map +1 -1
  3. package/dist/adapter/adapter-module.js +224 -42
  4. package/dist/adapter/authoring-seam-contract.d.ts +530 -0
  5. package/dist/adapter/authoring-seam-contract.d.ts.map +1 -0
  6. package/dist/adapter/authoring-seam-contract.js +162 -0
  7. package/dist/adapter/authoring.d.ts +237 -50
  8. package/dist/adapter/authoring.d.ts.map +1 -1
  9. package/dist/adapter/authoring.js +2 -1
  10. package/dist/adapter/entrypoint-selection-source.d.ts +35 -0
  11. package/dist/adapter/entrypoint-selection-source.d.ts.map +1 -0
  12. package/dist/adapter/entrypoint-selection-source.js +151 -0
  13. package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts +7 -1
  14. package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts.map +1 -1
  15. package/dist/adapter/finders/scenes-from-entrypoint-selection.js +142 -21
  16. package/dist/adapter/first-party-systems.d.ts +13 -3
  17. package/dist/adapter/first-party-systems.d.ts.map +1 -1
  18. package/dist/adapter/first-party-systems.js +10 -3
  19. package/dist/adapter/index.d.ts +7 -2
  20. package/dist/adapter/index.d.ts.map +1 -1
  21. package/dist/adapter/index.js +4 -0
  22. package/dist/adapter/ingest/contract-system-adapters.d.ts +1 -1
  23. package/dist/adapter/ingest/contract-system-adapters.d.ts.map +1 -1
  24. package/dist/adapter/ingest/contract-system-adapters.js +13 -25
  25. package/dist/adapter/ingest/game-contract-seams.d.ts +214 -0
  26. package/dist/adapter/ingest/game-contract-seams.d.ts.map +1 -0
  27. package/dist/adapter/ingest/game-contract-seams.js +62 -0
  28. package/dist/adapter/ingest/game-contract.d.ts +5 -3
  29. package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
  30. package/dist/adapter/ingest/game-contract.js +4 -1
  31. package/dist/adapter/ingest/merge-debug-adapters.d.ts +52 -0
  32. package/dist/adapter/ingest/merge-debug-adapters.d.ts.map +1 -0
  33. package/dist/adapter/ingest/merge-debug-adapters.js +141 -0
  34. package/dist/adapter/ingest/observation-debug-adapter.d.ts +56 -0
  35. package/dist/adapter/ingest/observation-debug-adapter.d.ts.map +1 -0
  36. package/dist/adapter/ingest/observation-debug-adapter.js +131 -0
  37. package/dist/adapter/ingest/scene-capture.d.ts +38 -13
  38. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
  39. package/dist/adapter/ingest/scene-capture.js +101 -24
  40. package/dist/adapter/ingest/visible-capture-window.d.ts +22 -5
  41. package/dist/adapter/ingest/visible-capture-window.d.ts.map +1 -1
  42. package/dist/adapter/ingest/visible-capture-window.js +46 -7
  43. package/dist/adapter/native-debug-module.d.ts +43 -0
  44. package/dist/adapter/native-debug-module.d.ts.map +1 -0
  45. package/dist/adapter/native-debug-module.js +230 -0
  46. package/dist/adapter/object3d-authoring-subject.d.ts +32 -0
  47. package/dist/adapter/object3d-authoring-subject.d.ts.map +1 -0
  48. package/dist/adapter/object3d-authoring-subject.js +25 -0
  49. package/dist/adapter/root-adapter.d.ts +21 -56
  50. package/dist/adapter/root-adapter.d.ts.map +1 -1
  51. package/dist/adapter/root-adapter.js +4 -20
  52. package/dist/adapter/root-seam-contract.d.ts +124 -0
  53. package/dist/adapter/root-seam-contract.d.ts.map +1 -0
  54. package/dist/adapter/root-seam-contract.js +36 -0
  55. package/dist/adapter/seam-evidence.d.ts +118 -0
  56. package/dist/adapter/seam-evidence.d.ts.map +1 -0
  57. package/dist/adapter/seam-evidence.js +231 -0
  58. package/dist/adapter/setup-three-root-adapter.d.ts +2 -3
  59. package/dist/adapter/setup-three-root-adapter.d.ts.map +1 -1
  60. package/dist/adapter/setup-three-root-adapter.js +2 -3
  61. package/dist/adapter/system-adapter.d.ts +6 -1
  62. package/dist/adapter/system-adapter.d.ts.map +1 -1
  63. package/dist/adapter/system-seam-contract.d.ts +354 -0
  64. package/dist/adapter/system-seam-contract.d.ts.map +1 -0
  65. package/dist/adapter/system-seam-contract.js +95 -0
  66. package/dist/animation/xstate-animation-binding.d.ts +6 -0
  67. package/dist/animation/xstate-animation-binding.d.ts.map +1 -1
  68. package/dist/animation/xstate-animation-binding.js +142 -4
  69. package/dist/asset-formats/collider.d.ts +1 -1
  70. package/dist/asset-formats/mesh.d.ts +2 -2
  71. package/dist/asset-formats/particles.d.ts +1 -1
  72. package/dist/canvas-react/engine-bridge.d.ts +6 -6
  73. package/dist/canvas-react/engine-bridge.d.ts.map +1 -1
  74. package/dist/canvas-react/engine-bridge.js +2 -2
  75. package/dist/canvas-react/index.d.ts +2 -2
  76. package/dist/canvas-react/index.d.ts.map +1 -1
  77. package/dist/canvas-react/index.js +1 -1
  78. package/dist/canvas-react/pixi-react-adapter.d.ts +15 -9
  79. package/dist/canvas-react/pixi-react-adapter.d.ts.map +1 -1
  80. package/dist/canvas-react/pixi-react-adapter.js +43 -29
  81. package/dist/canvas-react/pixi-react-root-factory.d.ts.map +1 -1
  82. package/dist/canvas-react/pixi-react-root-factory.js +4 -0
  83. package/dist/canvas-react/world-context.d.ts +22 -12
  84. package/dist/canvas-react/world-context.d.ts.map +1 -1
  85. package/dist/canvas-react/world-context.js +12 -51
  86. package/dist/ecs/user-data.d.ts +5 -0
  87. package/dist/ecs/user-data.d.ts.map +1 -1
  88. package/dist/ecs/user-data.js +3 -0
  89. package/dist/input/input-manager.d.ts +49 -0
  90. package/dist/input/input-manager.d.ts.map +1 -1
  91. package/dist/input/input-manager.js +127 -0
  92. package/dist/manifest/schema.d.ts +9 -9
  93. package/dist/pixi/authoring.d.ts.map +1 -1
  94. package/dist/pixi/authoring.js +220 -1
  95. package/dist/pixi/ingest.d.ts +2 -1
  96. package/dist/pixi/ingest.d.ts.map +1 -1
  97. package/dist/pixi/ingest.js +4 -2
  98. package/dist/pixi/scene-capture.d.ts +9 -1
  99. package/dist/pixi/scene-capture.d.ts.map +1 -1
  100. package/dist/pixi/scene-capture.js +9 -6
  101. package/dist/render/particles-factory.d.ts +13 -6
  102. package/dist/render/particles-factory.d.ts.map +1 -1
  103. package/dist/render/particles-factory.js +6 -3
  104. package/dist/runtime/create-runtime.d.ts +23 -46
  105. package/dist/runtime/create-runtime.d.ts.map +1 -1
  106. package/dist/runtime/create-runtime.js +22 -67
  107. package/dist/runtime/game.d.ts +29 -71
  108. package/dist/runtime/game.d.ts.map +1 -1
  109. package/dist/runtime/game.js +15 -54
  110. package/dist/runtime/mount-game.d.ts.map +1 -1
  111. package/dist/runtime/mount-game.js +12 -1
  112. package/dist/runtime/mount-manifest.d.ts.map +1 -1
  113. package/dist/runtime/mount-manifest.js +4 -5
  114. package/dist/runtime/types.d.ts +18 -0
  115. package/dist/runtime/types.d.ts.map +1 -1
  116. package/dist/setup/setup-renderer.d.ts +3 -4
  117. package/dist/setup/setup-renderer.d.ts.map +1 -1
  118. package/dist/setup/setup-renderer.js +3 -4
  119. package/dist/world3d-react/engine-bridge.d.ts +1 -1
  120. package/dist/world3d-react/engine-bridge.js +1 -1
  121. package/dist/world3d-react/r3f-adapter.d.ts +7 -0
  122. package/dist/world3d-react/r3f-adapter.d.ts.map +1 -1
  123. package/dist/world3d-react/r3f-adapter.js +50 -21
  124. package/dist/world3d-react/r3f-root-factory.d.ts.map +1 -1
  125. package/dist/world3d-react/r3f-root-factory.js +4 -0
  126. package/dist/world3d-react/world-context.d.ts +9 -3
  127. package/dist/world3d-react/world-context.d.ts.map +1 -1
  128. package/dist/world3d-react/world-context.js +5 -18
  129. package/package.json +1 -1
  130. package/schemas/engine-capabilities.json +7 -7
  131. package/src/adapter/adapter-module.ts +407 -50
  132. package/src/adapter/authoring-seam-contract.ts +211 -0
  133. package/src/adapter/authoring.ts +242 -50
  134. package/src/adapter/entrypoint-selection-source.ts +159 -0
  135. package/src/adapter/finders/scenes-from-entrypoint-selection.ts +159 -28
  136. package/src/adapter/first-party-systems.ts +17 -3
  137. package/src/adapter/index.ts +51 -1
  138. package/src/adapter/ingest/contract-system-adapters.ts +26 -30
  139. package/src/adapter/ingest/game-contract-seams.ts +85 -0
  140. package/src/adapter/ingest/game-contract.ts +9 -4
  141. package/src/adapter/ingest/merge-debug-adapters.ts +193 -0
  142. package/src/adapter/ingest/observation-debug-adapter.ts +158 -0
  143. package/src/adapter/ingest/scene-capture.ts +126 -23
  144. package/src/adapter/ingest/visible-capture-window.ts +63 -9
  145. package/src/adapter/native-debug-module.ts +307 -0
  146. package/src/adapter/object3d-authoring-subject.ts +50 -0
  147. package/src/adapter/root-adapter.ts +21 -56
  148. package/src/adapter/root-seam-contract.ts +56 -0
  149. package/src/adapter/seam-evidence.ts +336 -0
  150. package/src/adapter/setup-three-root-adapter.ts +4 -6
  151. package/src/adapter/system-adapter.ts +6 -1
  152. package/src/adapter/system-seam-contract.ts +121 -0
  153. package/src/animation/xstate-animation-binding.ts +151 -4
  154. package/src/canvas-react/engine-bridge.ts +6 -6
  155. package/src/canvas-react/index.ts +2 -1
  156. package/src/canvas-react/pixi-react-adapter.tsx +55 -34
  157. package/src/canvas-react/pixi-react-root-factory.tsx +4 -0
  158. package/src/canvas-react/world-context.ts +26 -101
  159. package/src/ecs/user-data.ts +5 -0
  160. package/src/input/input-manager.ts +122 -0
  161. package/src/pixi/authoring.ts +236 -1
  162. package/src/pixi/ingest.ts +9 -2
  163. package/src/pixi/scene-capture.ts +20 -5
  164. package/src/render/particles-factory.ts +16 -6
  165. package/src/runtime/create-runtime.ts +41 -106
  166. package/src/runtime/game.ts +41 -111
  167. package/src/runtime/mount-game.ts +19 -1
  168. package/src/runtime/mount-manifest.ts +4 -5
  169. package/src/runtime/types.ts +22 -0
  170. package/src/setup/setup-renderer.ts +3 -4
  171. package/src/world3d-react/engine-bridge.ts +1 -1
  172. package/src/world3d-react/r3f-adapter.tsx +64 -24
  173. package/src/world3d-react/r3f-root-factory.tsx +4 -0
  174. package/src/world3d-react/world-context.ts +11 -36
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Serve-time rewrite of an entrypoint's swap-slot key.
3
+ *
4
+ * The scenes finder (`adapter/finders/scenes-from-entrypoint-selection.ts`)
5
+ * READS the same facts this module WRITES: a module-level `const <selection>
6
+ * = { … }` table, indexed by one identifier whose own module-level `const`
7
+ * is a string literal (`const activeScene = 'main'`). This is not an
8
+ * extraction of that finder — the finder stays the adapter-selected discovery
9
+ * algorithm, import-banned everywhere except the adapter loader. The rewrite
10
+ * is a host-owned mount parameter: play remounts the same entrypoint with a
11
+ * different declared key, without a new adapter slot and without mutating
12
+ * the file on disk.
13
+ *
14
+ * `typescript` is the same parser the finder already uses. This module is
15
+ * host-side only — a game's `vgai.adapter.ts` must not import it.
16
+ */
17
+ import ts from 'typescript';
18
+ function parse(path, source) {
19
+ return ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
20
+ }
21
+ function selectionTable(sf, name) {
22
+ for (const statement of sf.statements) {
23
+ if (!ts.isVariableStatement(statement))
24
+ continue;
25
+ for (const declaration of statement.declarationList.declarations) {
26
+ if (!ts.isIdentifier(declaration.name) || declaration.name.text !== name)
27
+ continue;
28
+ const initializer = declaration.initializer;
29
+ if (initializer && ts.isObjectLiteralExpression(initializer))
30
+ return initializer;
31
+ }
32
+ }
33
+ return undefined;
34
+ }
35
+ function propertyKey(property) {
36
+ const name = property.name;
37
+ if (!name)
38
+ return undefined;
39
+ if (ts.isIdentifier(name) || ts.isStringLiteral(name))
40
+ return name.text;
41
+ return undefined;
42
+ }
43
+ function tableKeys(table) {
44
+ const keys = [];
45
+ for (const property of table.properties) {
46
+ const key = propertyKey(property);
47
+ if (key !== undefined)
48
+ keys.push(key);
49
+ }
50
+ return keys;
51
+ }
52
+ /** The identifier in `scenes[activeScene]`, or a failure to read one. */
53
+ function indexingIdentifier(sf, selection) {
54
+ const names = new Set();
55
+ let unreadable = false;
56
+ const visit = (node) => {
57
+ if (ts.isElementAccessExpression(node) &&
58
+ ts.isIdentifier(node.expression) &&
59
+ node.expression.text === selection) {
60
+ if (ts.isIdentifier(node.argumentExpression))
61
+ names.add(node.argumentExpression.text);
62
+ else
63
+ unreadable = true;
64
+ }
65
+ ts.forEachChild(node, visit);
66
+ };
67
+ ts.forEachChild(sf, visit);
68
+ if (names.size === 0 && !unreadable)
69
+ return undefined;
70
+ if (names.size !== 1 || unreadable)
71
+ return null;
72
+ return [...names][0];
73
+ }
74
+ function moduleLevelStringLiteral(sf, name) {
75
+ for (const statement of sf.statements) {
76
+ if (!ts.isVariableStatement(statement))
77
+ continue;
78
+ if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0)
79
+ continue;
80
+ for (const declaration of statement.declarationList.declarations) {
81
+ if (!ts.isIdentifier(declaration.name) || declaration.name.text !== name)
82
+ continue;
83
+ const initializer = declaration.initializer;
84
+ if (initializer && ts.isStringLiteral(initializer))
85
+ return initializer;
86
+ return undefined;
87
+ }
88
+ }
89
+ return undefined;
90
+ }
91
+ /**
92
+ * Rewrite the entrypoint so its swap slot mounts `key` instead of the
93
+ * source-declared occupant.
94
+ *
95
+ * Fails (never guesses) when the source is not the template's shape: no
96
+ * table, a key the table does not declare, or an index that is not a
97
+ * module-level `const` string. A no-op rewrite (`key` already at the slot)
98
+ * is still `ok` — remounting the same key is a real restart.
99
+ */
100
+ export function rewriteEntrypointSelectionKey(source, path, selection, key) {
101
+ const sf = parse(path, source);
102
+ const table = selectionTable(sf, selection);
103
+ if (!table) {
104
+ return {
105
+ ok: false,
106
+ reason: `${path} declares no module-level \`const ${selection} = { … }\` selection table, ` +
107
+ 'so the host cannot remount it at another key.',
108
+ };
109
+ }
110
+ const keys = tableKeys(table);
111
+ if (!keys.includes(key)) {
112
+ return {
113
+ ok: false,
114
+ reason: `"${key}" is not a key of ${path}'s \`${selection}\` table ` +
115
+ `(known: ${keys.length > 0 ? keys.join(', ') : 'none'}).`,
116
+ };
117
+ }
118
+ const identifier = indexingIdentifier(sf, selection);
119
+ if (identifier === undefined) {
120
+ return {
121
+ ok: false,
122
+ reason: `${path} never indexes \`${selection}\`, so there is no slot key to rewrite.`,
123
+ };
124
+ }
125
+ if (identifier === null) {
126
+ return {
127
+ ok: false,
128
+ reason: `${path} indexes \`${selection}\` with something other than one single identifier, ` +
129
+ 'so the host cannot rewrite the key it mounts.',
130
+ };
131
+ }
132
+ const literal = moduleLevelStringLiteral(sf, identifier);
133
+ if (!literal) {
134
+ return {
135
+ ok: false,
136
+ reason: `${path} indexes \`${selection}\` with \`${identifier}\`, which is not a ` +
137
+ 'module-level `const` bound to a string literal — the running game cannot be ' +
138
+ 'sent to another key by rewriting the slot.',
139
+ };
140
+ }
141
+ if (literal.text === key)
142
+ return { ok: true, source, changed: false };
143
+ const start = literal.getStart(sf);
144
+ const end = literal.getEnd();
145
+ const quote = source[start] ?? "'";
146
+ return {
147
+ ok: true,
148
+ source: `${source.slice(0, start)}${quote}${key}${quote}${source.slice(end)}`,
149
+ changed: true,
150
+ };
151
+ }
@@ -15,7 +15,13 @@
15
15
  *
16
16
  * Two answers, and the difference is declared rather than sniffed:
17
17
  * - the adapter names a `selection` identifier ⇒ read that module-level
18
- * table and answer one entry per key, each reachable through it;
18
+ * table and answer one entry per key, each reachable through it — plus
19
+ * WHICH key the entrypoint indexes it with right now (`scenes[activeScene]`
20
+ * → `const activeScene = 'main'`), marked `reach.active`. That reference is
21
+ * load-bearing for the same reason the table is: the running world renders
22
+ * exactly that key's composition, which is why the host can treat the
23
+ * active entry as the region's own standing document rather than a second
24
+ * tab beside it;
19
25
  * - the adapter names none ⇒ the entrypoint mounts ONE composition, and the
20
26
  * answer is the single-scene DEGENERATE table: the region's own
21
27
  * composition, opened by mounting the region.
@@ -1 +1 @@
1
- {"version":3,"file":"scenes-from-entrypoint-selection.d.ts","sourceRoot":"","sources":["../../../src/adapter/finders/scenes-from-entrypoint-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAGV,mCAAmC,EACpC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,kCAAkC;IACjD;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAClD;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACjF;AA2MD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,mCAAmC,EAC3C,KAAK,EAAE,kCAAkC,GACxC,YAAY,CAwBd"}
1
+ {"version":3,"file":"scenes-from-entrypoint-selection.d.ts","sourceRoot":"","sources":["../../../src/adapter/finders/scenes-from-entrypoint-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAGH,OAAO,KAAK,EAGV,mCAAmC,EACpC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,kCAAkC;IACjD;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAClD;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACjF;AAkUD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,mCAAmC,EAC3C,KAAK,EAAE,kCAAkC,GACxC,YAAY,CA8Bd"}
@@ -15,7 +15,13 @@
15
15
  *
16
16
  * Two answers, and the difference is declared rather than sniffed:
17
17
  * - the adapter names a `selection` identifier ⇒ read that module-level
18
- * table and answer one entry per key, each reachable through it;
18
+ * table and answer one entry per key, each reachable through it — plus
19
+ * WHICH key the entrypoint indexes it with right now (`scenes[activeScene]`
20
+ * → `const activeScene = 'main'`), marked `reach.active`. That reference is
21
+ * load-bearing for the same reason the table is: the running world renders
22
+ * exactly that key's composition, which is why the host can treat the
23
+ * active entry as the region's own standing document rather than a second
24
+ * tab beside it;
19
25
  * - the adapter names none ⇒ the entrypoint mounts ONE composition, and the
20
26
  * answer is the single-scene DEGENERATE table: the region's own
21
27
  * composition, opened by mounting the region.
@@ -109,6 +115,98 @@ function propertyKey(property) {
109
115
  return name.text;
110
116
  return undefined;
111
117
  }
118
+ /**
119
+ * The identifier the entrypoint INDEXES the selection table with — the
120
+ * `activeScene` in `scenes[activeScene]`.
121
+ *
122
+ * `undefined` when the module never indexes the table, or indexes it with
123
+ * anything other than one single identifier: both are honest "cannot be read",
124
+ * and the caller turns each into its own note.
125
+ */
126
+ function indexingIdentifier(sf, selection) {
127
+ const names = new Set();
128
+ let unreadable = false;
129
+ const visit = (node) => {
130
+ if (ts.isElementAccessExpression(node) &&
131
+ ts.isIdentifier(node.expression) &&
132
+ node.expression.text === selection) {
133
+ if (ts.isIdentifier(node.argumentExpression))
134
+ names.add(node.argumentExpression.text);
135
+ else
136
+ unreadable = true;
137
+ }
138
+ ts.forEachChild(node, visit);
139
+ };
140
+ ts.forEachChild(sf, visit);
141
+ if (names.size === 0 && !unreadable)
142
+ return undefined; // never indexed at all
143
+ if (names.size !== 1 || unreadable)
144
+ return null; // indexed, but not readably
145
+ return [...names][0];
146
+ }
147
+ /**
148
+ * The string a module-level `const <name> = '…'` binds, or `undefined`.
149
+ *
150
+ * `const` and a STRING LITERAL are both required: a `let` can be reassigned and
151
+ * a computed initializer is not a fact the source states, so neither can be
152
+ * reported as the key the game executes. A type annotation
153
+ * (`const activeScene: keyof typeof scenes = 'main'`) is irrelevant here — the
154
+ * initializer is what runs.
155
+ */
156
+ function moduleLevelString(sf, name) {
157
+ for (const statement of sf.statements) {
158
+ if (!ts.isVariableStatement(statement))
159
+ continue;
160
+ if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0)
161
+ continue;
162
+ for (const declaration of statement.declarationList.declarations) {
163
+ if (!ts.isIdentifier(declaration.name) || declaration.name.text !== name)
164
+ continue;
165
+ const initializer = declaration.initializer;
166
+ if (initializer && ts.isStringLiteral(initializer))
167
+ return initializer.text;
168
+ return undefined;
169
+ }
170
+ }
171
+ return undefined;
172
+ }
173
+ /**
174
+ * WHICH key the entrypoint mounts at its slot right now, read off the source
175
+ * the game itself executes.
176
+ *
177
+ * Every failure is a NOTE and answers `undefined`: an unread active key costs
178
+ * a retitle, while a guessed one would open the wrong composition as the
179
+ * region's own document.
180
+ */
181
+ function activeSelectionKey(entrypoint, sf, selection, keys, notes) {
182
+ const identifier = indexingIdentifier(sf, selection);
183
+ if (identifier === undefined) {
184
+ notes.push(`scenesFromEntrypointSelection: ${entrypoint.path} never indexes \`${selection}\`, so ` +
185
+ 'which of its compositions the entrypoint mounts is not stated in the source and no ' +
186
+ 'entry is settled as the active one.');
187
+ return undefined;
188
+ }
189
+ if (identifier === null) {
190
+ notes.push(`scenesFromEntrypointSelection: ${entrypoint.path} indexes \`${selection}\` with ` +
191
+ 'something other than one single identifier, so the key it mounts cannot be read ' +
192
+ 'statically.');
193
+ return undefined;
194
+ }
195
+ const key = moduleLevelString(sf, identifier);
196
+ if (key === undefined) {
197
+ notes.push(`scenesFromEntrypointSelection: ${entrypoint.path} indexes \`${selection}\` with ` +
198
+ `\`${identifier}\`, which is not a module-level \`const\` bound to a string literal, ` +
199
+ 'so the key it mounts cannot be read statically.');
200
+ return undefined;
201
+ }
202
+ if (!keys.includes(key)) {
203
+ notes.push(`scenesFromEntrypointSelection: ${entrypoint.path} mounts \`${selection}\` under ` +
204
+ `"${key}", which is not a key of that table. The entrypoint and its own selection ` +
205
+ 'table disagree.');
206
+ return undefined;
207
+ }
208
+ return key;
209
+ }
112
210
  /** The identifier a selection entry's value names, if it names one at all. */
113
211
  function propertyIdentifier(property) {
114
212
  if (ts.isShorthandPropertyAssignment(property))
@@ -166,17 +264,21 @@ function degenerateEntry(entrypoint, sf) {
166
264
  finder: 'scenesFromEntrypointSelection',
167
265
  };
168
266
  }
169
- /** One entry per key of the entrypoint's own selection table. */
267
+ /**
268
+ * One entry per key of the entrypoint's own selection table, plus WHICH of
269
+ * them the entrypoint currently mounts at the slot (`active`).
270
+ */
170
271
  function selectionEntries(entrypoint, sf, selection, resolveModule, notes) {
171
272
  const table = selectionTable(sf, selection);
172
273
  if (!table) {
173
274
  notes.push(`scenesFromEntrypointSelection: ${entrypoint.path} declares no module-level ` +
174
275
  `\`const ${selection} = { … }\` selection table. Nothing is assumed in its ` +
175
276
  'place — fix the adapter’s `selection` or the entrypoint.');
176
- return [];
277
+ return { entries: [], active: undefined };
177
278
  }
178
279
  const bindings = importedBindings(sf);
179
- const entries = [];
280
+ const keys = [];
281
+ const built = [];
180
282
  for (const property of table.properties) {
181
283
  const key = propertyKey(property);
182
284
  if (key === undefined) {
@@ -185,19 +287,30 @@ function selectionEntries(entrypoint, sf, selection, resolveModule, notes) {
185
287
  continue;
186
288
  }
187
289
  const identifier = propertyIdentifier(property);
188
- const source = sourceFor(identifier ? bindings.get(identifier) : undefined, entrypoint.path, resolveModule);
189
- entries.push({
190
- id: key,
290
+ keys.push(key);
291
+ built.push({
292
+ key,
191
293
  label: identifier ?? key,
192
- kind: 'scene',
193
- region: entrypoint.regionId,
194
- authorable: true,
195
- reach: { kind: 'entrypoint-selection', selection, key },
196
- ...(source ? { source } : {}),
197
- finder: 'scenesFromEntrypointSelection',
294
+ source: sourceFor(identifier ? bindings.get(identifier) : undefined, entrypoint.path, resolveModule),
198
295
  });
199
296
  }
200
- return entries;
297
+ const active = activeSelectionKey(entrypoint, sf, selection, keys, notes);
298
+ const entries = built.map(({ key, label, source }) => ({
299
+ id: key,
300
+ label,
301
+ kind: 'scene',
302
+ region: entrypoint.regionId,
303
+ authorable: true,
304
+ reach: {
305
+ kind: 'entrypoint-selection',
306
+ selection,
307
+ key,
308
+ ...(key === active ? { active: true } : {}),
309
+ },
310
+ ...(source ? { source } : {}),
311
+ finder: 'scenesFromEntrypointSelection',
312
+ }));
313
+ return { entries, active };
201
314
  }
202
315
  /**
203
316
  * Answer the scene table this finder's selection describes.
@@ -208,6 +321,7 @@ function selectionEntries(entrypoint, sf, selection, resolveModule, notes) {
208
321
  export function scenesFromEntrypointSelection(params, input) {
209
322
  const notes = [];
210
323
  const entries = [];
324
+ const active = [];
211
325
  for (const entrypoint of targetedEntrypoints(params, input.entrypoints, notes)) {
212
326
  if (entrypoint.source === null) {
213
327
  notes.push(`scenesFromEntrypointSelection: could not read ${entrypoint.path} (region ` +
@@ -215,12 +329,19 @@ export function scenesFromEntrypointSelection(params, input) {
215
329
  continue;
216
330
  }
217
331
  const sf = parse(entrypoint.path, entrypoint.source);
218
- entries.push(...(params.selection === undefined
219
- ? [degenerateEntry(entrypoint, sf)]
220
- : selectionEntries(entrypoint, sf, params.selection, input.resolveModule, notes)));
332
+ if (params.selection === undefined) {
333
+ entries.push(degenerateEntry(entrypoint, sf));
334
+ continue;
335
+ }
336
+ const found = selectionEntries(entrypoint, sf, params.selection, input.resolveModule, notes);
337
+ entries.push(...found.entries);
338
+ if (found.active !== undefined)
339
+ active.push(found.active);
221
340
  }
222
- // One candidate settles the default; two or more is a choice, and a choice
223
- // belongs to the adapter author.
224
- const only = entries.length === 1 ? entries[0] : undefined;
225
- return only ? { entries, default: only.id, notes } : { entries, notes };
341
+ // The ACTIVE key settles the default outright: the entrypoint states which
342
+ // composition it mounts, so this is the finder READING an answer rather than
343
+ // choosing between candidates. Failing that, one candidate settles it; two or
344
+ // more is a choice, and a choice belongs to the adapter author.
345
+ const settled = active.length === 1 ? active[0] : entries.length === 1 ? entries[0]?.id : undefined;
346
+ return settled !== undefined ? { entries, default: settled, notes } : { entries, notes };
226
347
  }
@@ -10,14 +10,24 @@
10
10
  * `createInputManagerAdapter`/`createVgaiAssetAdapter` went with
11
11
  * `SystemAdapters.input`/`.assets` — registered, never read by anything.)
12
12
  */
13
+ import type * as THREE from 'three';
13
14
  import type { NavMeshManager } from '../ai/navigation';
14
15
  import type { AudioContext as GameAudio } from '../setup/setup-audio';
15
- import type { AudioAdapter, NavigationAdapter } from './system-adapter';
16
+ import type { AudioAdapter, NavBakeParams, NavigationAdapter } from './system-adapter';
16
17
  /** Release every meter tap still open on `adapter` (world stop / teardown). */
17
18
  export declare function releaseAudioMeters(adapter: AudioAdapter): void;
18
19
  export declare function createAudioSystemAdapter(audio: GameAudio): AudioAdapter;
19
20
  /** First-party `NavigationAdapter` over the engine `NavMeshManager` — the
20
21
  * blessed recast implementation, including the optional bake/export/crowd
21
- * capabilities the editor's Navigation panel binds through. */
22
- export declare function createNavigationAdapter(nav: NavMeshManager): NavigationAdapter;
22
+ * capabilities the editor's Navigation panel binds through.
23
+ *
24
+ * `clear` is deliberately owner-supplied: a manager cannot know which gameplay
25
+ * objects retain CrowdAgent handles, so disposing it generically would leave
26
+ * those handles pointing at freed WASM memory. A game that grants clear owns
27
+ * releasing/rebinding those references in the same callback. `bake` may be
28
+ * overridden for the same reason when a live crowd must be rebuilt. */
29
+ export declare function createNavigationAdapter(nav: NavMeshManager, ownerCapabilities?: {
30
+ readonly bake?: (meshes: THREE.Mesh[], params?: NavBakeParams) => boolean;
31
+ readonly clear?: (scene: THREE.Scene) => void;
32
+ }): NavigationAdapter;
23
33
  //# sourceMappingURL=first-party-systems.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"first-party-systems.d.ts","sourceRoot":"","sources":["../../src/adapter/first-party-systems.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,KAAK,EACV,YAAY,EAKZ,iBAAiB,EAElB,MAAM,kBAAkB,CAAC;AAmC1B,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAI9D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,GAAG,YAAY,CAiKvE;AAED;;gEAEgE;AAChE,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,cAAc,GAAG,iBAAiB,CAS9E"}
1
+ {"version":3,"file":"first-party-systems.d.ts","sourceRoot":"","sources":["../../src/adapter/first-party-systems.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,KAAK,EACV,YAAY,EAKZ,aAAa,EACb,iBAAiB,EAElB,MAAM,kBAAkB,CAAC;AAmC1B,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAI9D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,GAAG,YAAY,CAiKvE;AAED;;;;;;;;uEAQuE;AACvE,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,cAAc,EACnB,iBAAiB,GAAE;IACjB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC;CAC1C,GACL,iBAAiB,CAUnB"}
@@ -212,14 +212,21 @@ export function createAudioSystemAdapter(audio) {
212
212
  }
213
213
  /** First-party `NavigationAdapter` over the engine `NavMeshManager` — the
214
214
  * blessed recast implementation, including the optional bake/export/crowd
215
- * capabilities the editor's Navigation panel binds through. */
216
- export function createNavigationAdapter(nav) {
215
+ * capabilities the editor's Navigation panel binds through.
216
+ *
217
+ * `clear` is deliberately owner-supplied: a manager cannot know which gameplay
218
+ * objects retain CrowdAgent handles, so disposing it generically would leave
219
+ * those handles pointing at freed WASM memory. A game that grants clear owns
220
+ * releasing/rebinding those references in the same callback. `bake` may be
221
+ * overridden for the same reason when a live crowd must be rebuilt. */
222
+ export function createNavigationAdapter(nav, ownerCapabilities = {}) {
217
223
  return {
218
224
  hasNavMesh: () => nav.hasNavMesh(),
219
225
  findPath: (start, end) => nav.findPath(start, end),
220
226
  debugMesh: (scene) => nav.getDebugMesh(scene),
221
- bake: (meshes, params) => nav.buildFromMeshes(meshes, params),
227
+ bake: ownerCapabilities.bake ?? ((meshes, params) => nav.buildFromMeshes(meshes, params)),
222
228
  exportData: () => nav.exportData(),
229
+ ...(ownerCapabilities.clear ? { clear: ownerCapabilities.clear } : {}),
223
230
  crowdAgents: () => nav.getCrowdAgents(),
224
231
  };
225
232
  }
@@ -23,15 +23,20 @@
23
23
  * `@engine/adapter/first-party-systems` createNavigationAdapter
24
24
  */
25
25
  export type { AdapterSurface } from './adapter-surface';
26
- export type { AssetDropContext, AssetDropProvider, AssetSubjectProvider, AuthoringAdapter, AuthoringAssetSubject, AuthoringCapabilities, AuthoringProvenance, AuthoringProviderKey, BoxEditProvider, BoxEditReferencePoint, ColorSampleProvider, ComponentInstanceApplyResult, ComponentInstanceDescription, ComponentInstanceOverride, ComponentInstancesProvider, CreationSiteProvider, DOMRectLike, EditorNode, EditorNodeRole, HierarchyProvider, InspectorProvider, NodeCreationSite, PersistenceProvider, PickProvider, PropertyDescriptor, RectProvider, RelatedSubjectLink, RelatedSubjectsProvider, SelectionProvider, SelectionResolution, SpatialDragHandle, SpatialHandleGuide, SpatialHandleLayer, SpatialHandlesProvider, SpatialPoint3, StoriesProvider, StoryRef, StructureProvider, TextProvider, TransformChannel, TransformEditability, TransformObservation, TransformProvider, WriteAck, WriteAnchorKind, } from './authoring';
26
+ export type { AssetDropContext, AssetDropProvider, AssetSubjectProvider, AuthoringAdapter, AuthoringAssetSubject, AuthoringCapabilities, AuthoringProvenance, AuthoringProviderKey, AuthoringTruth, BoxEditProvider, BoxEditReferencePoint, ColorSampleProvider, ComponentInstanceApplyResult, ComponentInstanceDescription, ComponentInstanceOverride, ComponentInstancesProvider, DOMRectLike, EditorNode, EditorNodeRole, HierarchyProvider, InspectorProvider, NodeCreationSite, PersistenceProvider, PickProvider, PropertyDescriptor, RectProvider, RelatedSubjectLink, RelatedSubjectsProvider, SelectionProvider, SelectionResolution, SpatialDragHandle, SpatialHandleGuide, SpatialHandleLayer, SpatialHandlesProvider, SpatialPoint3, StoriesProvider, StoryRef, StructuralClipboardOutcome, StructuralIdsWrite, StructuralIdWrite, StructuralWriteOutcome, StructureProvider, TextProvider, TransformChannel, TransformEditability, TransformObservation, TransformProvider, TransformSourceCommitProvider, TruthProvider, WriteAck, WriteAnchorKind, } from './authoring';
27
27
  export { AUTHORING_PROVIDER_KEYS, emptyWriteAnchorKindCounts, measureAuthoringProviders, WRITE_ANCHOR_KINDS, } from './authoring';
28
+ export { AUTHORING_ADAPTER_SHAPE, AUTHORING_PROVIDER_SHAPES, HIERARCHY_PROVIDER_SHAPE, } from './authoring-seam-contract';
28
29
  export type { ColyseusNetworkingConfig } from './colyseus-networking-adapter';
29
30
  export type { CanvasHostContext, DomHostContext, HostContextBase, HostContextFor, HostSurface, ThreeHostContext, } from './host-context';
30
31
  export type { MountedPixiRoot, MountedReactRoot, MountedRoot, MountedRootBase, MountedThreeRoot, RootAdapter, RootStateObserver, SurfaceAdapter, SurfaceAdapterFor, } from './root-adapter';
32
+ export { MOUNTED_CANVAS_SURFACE_SHAPE, MOUNTED_DOM_SURFACE_SHAPE, MOUNTED_ROOT_BASE_SHAPE, MOUNTED_THREE_SURFACE_SHAPE, ROOT_ADAPTER_SHAPE, ROOT_STATE_OBSERVER_SHAPE, } from './root-seam-contract';
33
+ export type { SeamEvidenceOutcome, SeamEvidenceReceipt, SeamEvidenceSource, SeamEvidenceState, SeamEvidenceVerdict, SeamProofStage, SeamShape, } from './seam-evidence';
34
+ export { defineSeamShape, gradeSeamCarrier, gradeSeamEvidence, inspectSeamShape, SEAM_PROOF_STAGES, SeamEvidenceLedger, seamStageAtLeast, } from './seam-evidence';
31
35
  export type { MountedSetupThreeRoot, SetupThreeRootConfig } from './setup-three-root-adapter';
32
- export type { AudioAdapter, AudioDebugEvent, AudioGraphNode, AudioMeterFrame, AudioMeterHandle, AudioRecordingHandle, AudioTransportState, CameraAdapter, CameraRuntimeCamera, CameraRuntimeSnapshot, CameraRuntimeTransition, ConnectionState, NavCrowdAgentState, NavigationAdapter, NavPoint, NetConditioning, NetMessageEvent, NetPeer, NetPlayerIdentity, NetRates, NetServerConfig, NetworkingAdapter, PhysicsAdapter, PhysicsCarrier, PhysicsColliderShape, PhysicsColliderSnapshot, PhysicsJointSnapshot, PhysicsJointType, RenderDebugAdapter, ReplicationStats, RoomInfo, SystemAdapters, Unsubscribe, } from './system-adapter';
36
+ export type { AudioAdapter, AudioDebugEvent, AudioGraphNode, AudioMeterFrame, AudioMeterHandle, AudioRecordingHandle, AudioTransportState, CameraAdapter, CameraRuntimeCamera, CameraRuntimeSnapshot, CameraRuntimeTransition, ConnectionState, DebugAdapter, NavCrowdAgentState, NavigationAdapter, NavPoint, NetConditioning, NetMessageEvent, NetPeer, NetPlayerIdentity, NetRates, NetServerConfig, NetworkingAdapter, PhysicsAdapter, PhysicsCarrier, PhysicsColliderShape, PhysicsColliderSnapshot, PhysicsJointSnapshot, PhysicsJointType, RenderDebugAdapter, ReplicationStats, RoomInfo, SystemAdapters, Unsubscribe, } from './system-adapter';
33
37
  /** The two narrowings of the tagged `SystemAdapters['physics']` union — see
34
38
  * `PhysicsAdapter`'s comment for why it is tagged at all. */
35
39
  export { displayKeyedPhysics, nodeKeyedPhysics } from './system-adapter';
40
+ export { AUDIO_ADAPTER_SHAPE, CAMERA_ADAPTER_SHAPE, DEBUG_ADAPTER_SHAPE, NAVIGATION_ADAPTER_SHAPE, NETWORKING_ADAPTER_SHAPE, PHYSICS_2D_ADAPTER_SHAPE, PHYSICS_ADAPTER_SHAPE, RENDER_DEBUG_ADAPTER_SHAPE, SYSTEM_ADAPTERS_SHAPE, SYSTEM_PROVIDER_SHAPES, } from './system-seam-contract';
36
41
  export type { Transform, TransformOwner } from './transform';
37
42
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,4BAA4B,EAC5B,4BAA4B,EAC5B,yBAAyB,EACzB,0BAA0B,EAC1B,oBAAoB,EACpB,WAAW,EACX,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,eAAe,EACf,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,QAAQ,EACR,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAC9E,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,cAAc,EACd,WAAW,EACX,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAC9F,YAAY,EACV,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,eAAe,EACf,eAAe,EACf,OAAO,EACP,iBAAiB,EACjB,QAAQ,EACR,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAC1B;8DAC8D;AAC9D,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapter/index.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,10 @@
23
23
  * `@engine/adapter/first-party-systems` createNavigationAdapter
24
24
  */
25
25
  export { AUTHORING_PROVIDER_KEYS, emptyWriteAnchorKindCounts, measureAuthoringProviders, WRITE_ANCHOR_KINDS, } from './authoring';
26
+ export { AUTHORING_ADAPTER_SHAPE, AUTHORING_PROVIDER_SHAPES, HIERARCHY_PROVIDER_SHAPE, } from './authoring-seam-contract';
27
+ export { MOUNTED_CANVAS_SURFACE_SHAPE, MOUNTED_DOM_SURFACE_SHAPE, MOUNTED_ROOT_BASE_SHAPE, MOUNTED_THREE_SURFACE_SHAPE, ROOT_ADAPTER_SHAPE, ROOT_STATE_OBSERVER_SHAPE, } from './root-seam-contract';
28
+ export { defineSeamShape, gradeSeamCarrier, gradeSeamEvidence, inspectSeamShape, SEAM_PROOF_STAGES, SeamEvidenceLedger, seamStageAtLeast, } from './seam-evidence';
26
29
  /** The two narrowings of the tagged `SystemAdapters['physics']` union — see
27
30
  * `PhysicsAdapter`'s comment for why it is tagged at all. */
28
31
  export { displayKeyedPhysics, nodeKeyedPhysics } from './system-adapter';
32
+ export { AUDIO_ADAPTER_SHAPE, CAMERA_ADAPTER_SHAPE, DEBUG_ADAPTER_SHAPE, NAVIGATION_ADAPTER_SHAPE, NETWORKING_ADAPTER_SHAPE, PHYSICS_2D_ADAPTER_SHAPE, PHYSICS_ADAPTER_SHAPE, RENDER_DEBUG_ADAPTER_SHAPE, SYSTEM_ADAPTERS_SHAPE, SYSTEM_PROVIDER_SHAPES, } from './system-seam-contract';
@@ -54,7 +54,7 @@ export type ContractSystemSlot = keyof VgaiGameSystemAdapters;
54
54
  export type ContractSurface = 'three' | 'canvas' | 'dom';
55
55
  /** Fixed slot order, so two reports of the same mount are diffable line for
56
56
  * line (the same rule the coverage report's row order follows). */
57
- export declare const CONTRACT_SYSTEM_SLOTS: readonly ContractSystemSlot[];
57
+ export declare const CONTRACT_SYSTEM_SLOTS: ContractSystemSlot[];
58
58
  /** One slot the game positively answered as having nothing behind it. */
59
59
  export interface ContractSystemEmptySlot {
60
60
  readonly slot: ContractSystemSlot;
@@ -1 +1 @@
1
- {"version":3,"file":"contract-system-adapters.d.ts","sourceRoot":"","sources":["../../../src/adapter/ingest/contract-system-adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,sBAAsB,EAAuB,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEpG;wEACwE;AACxE,MAAM,MAAM,kBAAkB,GAAG,MAAM,sBAAsB,CAAC;AA+B9D;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAezD;oEACoE;AACpE,eAAO,MAAM,qBAAqB,EAAE,SAAS,kBAAkB,EAO9D,CAAC;AAEF,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,iEAAiE;AACjE,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,+BAA+B;IAC9C,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAClE,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,SAAS,uBAAuB,EAAE,CAAC;IACnD,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,SAAS,2BAA2B,EAAE,CAAC;CAC5D;AA8FD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI,EAC3C,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,GACpC,+BAA+B,CAoBjC"}
1
+ {"version":3,"file":"contract-system-adapters.d.ts","sourceRoot":"","sources":["../../../src/adapter/ingest/contract-system-adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AASxD,OAAO,KAAK,EAAE,sBAAsB,EAAuB,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGpG;wEACwE;AACxE,MAAM,MAAM,kBAAkB,GAAG,MAAM,sBAAsB,CAAC;AAoB9D;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAezD;oEACoE;AACpE,eAAO,MAAM,qBAAqB,EAE7B,kBAAkB,EAAE,CAAC;AAE1B,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,iEAAiE;AACjE,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,+BAA+B;IAC9C,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAClE,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,SAAS,uBAAuB,EAAE,CAAC;IACnD,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,SAAS,2BAA2B,EAAE,CAAC;CAC5D;AAiGD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI,EAC3C,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,GACpC,+BAA+B,CAoBjC"}
@@ -41,6 +41,8 @@
41
41
  *
42
42
  * Nothing here calls a declared method. Presence and shape only.
43
43
  */
44
+ import { AUDIO_ADAPTER_SHAPE, CAMERA_ADAPTER_SHAPE, NAVIGATION_ADAPTER_SHAPE, NETWORKING_ADAPTER_SHAPE, PHYSICS_ADAPTER_SHAPE, RENDER_DEBUG_ADAPTER_SHAPE, } from '../system-seam-contract';
45
+ import { GAME_SYSTEM_ADAPTERS_SHAPE } from './game-contract-seams';
44
46
  /**
45
47
  * The members each slot's interface makes NON-optional. A declaration missing
46
48
  * one of these cannot honour the interface, whatever else it carries.
@@ -50,22 +52,13 @@
50
52
  * is typed as keys of its own adapter), so it cannot drift into naming a member
51
53
  * that does not exist.
52
54
  */
53
- const REQUIRED_MEMBERS = {
54
- physics: ['ownerOf', 'freeze', 'commit', 'unfreeze'],
55
- networking: [
56
- 'peers',
57
- 'networkId',
58
- 'authority',
59
- 'editable',
60
- 'getConnectionState',
61
- 'getRoomInfo',
62
- 'getReplicationStats',
63
- 'subscribe',
64
- ],
65
- navigation: ['hasNavMesh', 'findPath', 'debugMesh'],
66
- audio: ['setMuted', 'isMuted'],
67
- camera: ['snapshot', 'subscribe'],
68
- renderDebug: ['captureFrame'],
55
+ const SYSTEM_SHAPES = {
56
+ physics: PHYSICS_ADAPTER_SHAPE,
57
+ networking: NETWORKING_ADAPTER_SHAPE,
58
+ navigation: NAVIGATION_ADAPTER_SHAPE,
59
+ audio: AUDIO_ADAPTER_SHAPE,
60
+ camera: CAMERA_ADAPTER_SHAPE,
61
+ renderDebug: RENDER_DEBUG_ADAPTER_SHAPE,
69
62
  };
70
63
  /**
71
64
  * THE surface→physics-vocabulary rule, stated once.
@@ -81,14 +74,7 @@ const PHYSICS_KEYING_BY_SURFACE = {
81
74
  };
82
75
  /** Fixed slot order, so two reports of the same mount are diffable line for
83
76
  * line (the same rule the coverage report's row order follows). */
84
- export const CONTRACT_SYSTEM_SLOTS = [
85
- 'physics',
86
- 'networking',
87
- 'navigation',
88
- 'audio',
89
- 'camera',
90
- 'renderDebug',
91
- ];
77
+ export const CONTRACT_SYSTEM_SLOTS = Object.keys(GAME_SYSTEM_ADAPTERS_SHAPE);
92
78
  const EMPTY_PROJECTION = {
93
79
  bound: {},
94
80
  empty: [],
@@ -99,7 +85,9 @@ function isEmptyRecord(value) {
99
85
  }
100
86
  function missingMembers(slot, value) {
101
87
  const missing = [];
102
- for (const member of REQUIRED_MEMBERS[slot]) {
88
+ for (const [member, spec] of Object.entries(SYSTEM_SHAPES[slot])) {
89
+ if (spec.optional)
90
+ continue;
103
91
  if (typeof value[member] !== 'function') {
104
92
  missing.push(member);
105
93
  }