@vgai/engine 0.2.0 → 0.3.0

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 (541) hide show
  1. package/README.md +3 -1
  2. package/dist/adapter/authoring.d.ts +404 -0
  3. package/dist/adapter/authoring.d.ts.map +1 -0
  4. package/dist/adapter/authoring.js +22 -0
  5. package/dist/adapter/colyseus-networking-adapter.d.ts +43 -0
  6. package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -0
  7. package/dist/adapter/colyseus-networking-adapter.js +38 -0
  8. package/dist/adapter/first-party-systems.d.ts +38 -0
  9. package/dist/adapter/first-party-systems.d.ts.map +1 -0
  10. package/dist/adapter/first-party-systems.js +77 -0
  11. package/dist/adapter/game-adapter.d.ts +133 -0
  12. package/dist/adapter/game-adapter.d.ts.map +1 -0
  13. package/dist/adapter/game-adapter.js +10 -0
  14. package/dist/adapter/host-context.d.ts +73 -0
  15. package/dist/adapter/host-context.d.ts.map +1 -0
  16. package/dist/adapter/host-context.js +16 -0
  17. package/dist/adapter/index.d.ts +22 -0
  18. package/dist/adapter/index.d.ts.map +1 -0
  19. package/dist/adapter/index.js +15 -0
  20. package/dist/adapter/ingest/game-contract.d.ts +53 -0
  21. package/dist/adapter/ingest/game-contract.d.ts.map +1 -0
  22. package/dist/adapter/ingest/game-contract.js +30 -0
  23. package/dist/adapter/ingest/overlay-applier.d.ts +118 -0
  24. package/dist/adapter/ingest/overlay-applier.d.ts.map +1 -0
  25. package/dist/adapter/ingest/overlay-applier.js +132 -0
  26. package/dist/adapter/ingest/overlay-apply.d.ts +60 -0
  27. package/dist/adapter/ingest/overlay-apply.d.ts.map +1 -0
  28. package/dist/adapter/ingest/overlay-apply.js +101 -0
  29. package/dist/adapter/ingest/overlay-file.d.ts +79 -0
  30. package/dist/adapter/ingest/overlay-file.d.ts.map +1 -0
  31. package/dist/adapter/ingest/overlay-file.js +66 -0
  32. package/dist/adapter/ingest/overlay-report.d.ts +113 -0
  33. package/dist/adapter/ingest/overlay-report.d.ts.map +1 -0
  34. package/dist/adapter/ingest/overlay-report.js +103 -0
  35. package/dist/adapter/ingest/scene-capture.d.ts +97 -0
  36. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -0
  37. package/dist/adapter/ingest/scene-capture.js +248 -0
  38. package/dist/adapter/ingest/upstream-pin.d.ts +47 -0
  39. package/dist/adapter/ingest/upstream-pin.d.ts.map +1 -0
  40. package/dist/adapter/ingest/upstream-pin.js +50 -0
  41. package/dist/adapter/loop-gate-report.d.ts +34 -0
  42. package/dist/adapter/loop-gate-report.d.ts.map +1 -0
  43. package/dist/adapter/loop-gate-report.js +37 -0
  44. package/dist/adapter/rapier-physics-adapter.d.ts +12 -0
  45. package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -0
  46. package/dist/adapter/rapier-physics-adapter.js +46 -0
  47. package/dist/adapter/system-adapter.d.ts +133 -0
  48. package/dist/adapter/system-adapter.d.ts.map +1 -0
  49. package/dist/adapter/system-adapter.js +13 -0
  50. package/dist/adapter/transform.d.ts +18 -0
  51. package/dist/adapter/transform.d.ts.map +1 -0
  52. package/dist/adapter/transform.js +1 -0
  53. package/dist/adapter/vgai-scene-game-adapter.d.ts +116 -0
  54. package/dist/adapter/vgai-scene-game-adapter.d.ts.map +1 -0
  55. package/dist/adapter/vgai-scene-game-adapter.js +714 -0
  56. package/dist/adapter/world-kind.d.ts +30 -0
  57. package/dist/adapter/world-kind.d.ts.map +1 -0
  58. package/dist/adapter/world-kind.js +18 -0
  59. package/dist/ai/navigation.d.ts +64 -0
  60. package/dist/ai/navigation.d.ts.map +1 -0
  61. package/dist/ai/navigation.js +133 -0
  62. package/dist/animation/anim-graph-types.d.ts +25 -0
  63. package/dist/animation/anim-graph-types.d.ts.map +1 -0
  64. package/dist/animation/anim-graph-types.js +1 -0
  65. package/dist/animation/animation-clock.d.ts +213 -0
  66. package/dist/animation/animation-clock.d.ts.map +1 -0
  67. package/dist/animation/animation-clock.js +301 -0
  68. package/dist/animation/blend-node.d.ts +22 -0
  69. package/dist/animation/blend-node.d.ts.map +1 -0
  70. package/dist/animation/blend-node.js +97 -0
  71. package/dist/animation/camera-ownership.d.ts +250 -0
  72. package/dist/animation/camera-ownership.d.ts.map +1 -0
  73. package/dist/animation/camera-ownership.js +169 -0
  74. package/dist/animation/cinematic-cues.d.ts +200 -0
  75. package/dist/animation/cinematic-cues.d.ts.map +1 -0
  76. package/dist/animation/cinematic-cues.js +213 -0
  77. package/dist/animation/clip-map.d.ts +12 -0
  78. package/dist/animation/clip-map.d.ts.map +1 -0
  79. package/dist/animation/clip-map.js +37 -0
  80. package/dist/animation/gsap-registration.d.ts +119 -0
  81. package/dist/animation/gsap-registration.d.ts.map +1 -0
  82. package/dist/animation/gsap-registration.js +92 -0
  83. package/dist/animation/theatre-clock-binding.d.ts +89 -0
  84. package/dist/animation/theatre-clock-binding.d.ts.map +1 -0
  85. package/dist/animation/theatre-clock-binding.js +29 -0
  86. package/dist/animation/theatre-director.d.ts +242 -0
  87. package/dist/animation/theatre-director.d.ts.map +1 -0
  88. package/dist/animation/theatre-director.js +235 -0
  89. package/dist/animation/theatre-object-binding.d.ts +305 -0
  90. package/dist/animation/theatre-object-binding.d.ts.map +1 -0
  91. package/dist/animation/theatre-object-binding.js +351 -0
  92. package/dist/animation/xstate-animation-binding.d.ts +111 -0
  93. package/dist/animation/xstate-animation-binding.d.ts.map +1 -0
  94. package/dist/animation/xstate-animation-binding.js +307 -0
  95. package/dist/animation/xstate-animation-meta.d.ts +228 -0
  96. package/dist/animation/xstate-animation-meta.d.ts.map +1 -0
  97. package/dist/animation/xstate-animation-meta.js +221 -0
  98. package/dist/assets.d.ts +26 -0
  99. package/dist/assets.d.ts.map +1 -0
  100. package/dist/assets.js +55 -0
  101. package/dist/audio/index.d.ts +4 -0
  102. package/dist/audio/index.d.ts.map +1 -0
  103. package/dist/audio/index.js +24 -0
  104. package/dist/audio/tone-clock-binding.d.ts +75 -0
  105. package/dist/audio/tone-clock-binding.d.ts.map +1 -0
  106. package/dist/audio/tone-clock-binding.js +29 -0
  107. package/dist/audio/tone-context.d.ts +114 -0
  108. package/dist/audio/tone-context.d.ts.map +1 -0
  109. package/dist/audio/tone-context.js +39 -0
  110. package/dist/audio/tone-offline-render.d.ts +90 -0
  111. package/dist/audio/tone-offline-render.d.ts.map +1 -0
  112. package/dist/audio/tone-offline-render.js +56 -0
  113. package/dist/audio/wav-encode.d.ts +38 -0
  114. package/dist/audio/wav-encode.d.ts.map +1 -0
  115. package/dist/audio/wav-encode.js +97 -0
  116. package/dist/core/game-loop.d.ts +21 -0
  117. package/dist/core/game-loop.d.ts.map +1 -0
  118. package/dist/core/game-loop.js +130 -0
  119. package/dist/core/system-runner.d.ts +120 -0
  120. package/dist/core/system-runner.d.ts.map +1 -0
  121. package/dist/core/system-runner.js +286 -0
  122. package/dist/core/types.d.ts +58 -0
  123. package/dist/core/types.d.ts.map +1 -0
  124. package/dist/core/types.js +25 -0
  125. package/dist/data/data-asset.d.ts +101 -0
  126. package/dist/data/data-asset.d.ts.map +1 -0
  127. package/dist/data/data-asset.js +122 -0
  128. package/dist/data/data-check-core.d.ts +110 -0
  129. package/dist/data/data-check-core.d.ts.map +1 -0
  130. package/dist/data/data-check-core.js +178 -0
  131. package/dist/data/data-ref.d.ts +79 -0
  132. package/dist/data/data-ref.d.ts.map +1 -0
  133. package/dist/data/data-ref.js +130 -0
  134. package/dist/data/vite-plugin-data.d.ts +79 -0
  135. package/dist/data/vite-plugin-data.d.ts.map +1 -0
  136. package/dist/data/vite-plugin-data.js +217 -0
  137. package/dist/dev/console-bridge.d.ts +22 -0
  138. package/dist/dev/console-bridge.d.ts.map +1 -0
  139. package/dist/dev/console-bridge.js +71 -0
  140. package/dist/dev/debug-draw.d.ts +24 -0
  141. package/dist/dev/debug-draw.d.ts.map +1 -0
  142. package/dist/dev/debug-draw.js +73 -0
  143. package/dist/dev/logger.d.ts +30 -0
  144. package/dist/dev/logger.d.ts.map +1 -0
  145. package/dist/dev/logger.js +90 -0
  146. package/dist/ecs/component-manager.d.ts +189 -0
  147. package/dist/ecs/component-manager.d.ts.map +1 -0
  148. package/dist/ecs/component-manager.js +676 -0
  149. package/dist/ecs/game-component.d.ts +97 -0
  150. package/dist/ecs/game-component.d.ts.map +1 -0
  151. package/dist/ecs/game-component.js +80 -0
  152. package/dist/ecs/hmr-swap-report.d.ts +53 -0
  153. package/dist/ecs/hmr-swap-report.d.ts.map +1 -0
  154. package/dist/ecs/hmr-swap-report.js +55 -0
  155. package/dist/index.d.ts +37 -0
  156. package/dist/index.d.ts.map +1 -0
  157. package/dist/index.js +30 -0
  158. package/dist/input/input-manager.d.ts +596 -0
  159. package/dist/input/input-manager.d.ts.map +1 -0
  160. package/dist/input/input-manager.js +1564 -0
  161. package/dist/input/input-types.d.ts +171 -0
  162. package/dist/input/input-types.d.ts.map +1 -0
  163. package/dist/input/input-types.js +1 -0
  164. package/dist/input/prompt-labels.d.ts +21 -0
  165. package/dist/input/prompt-labels.d.ts.map +1 -0
  166. package/dist/input/prompt-labels.js +121 -0
  167. package/dist/input/rebind-controller.d.ts +59 -0
  168. package/dist/input/rebind-controller.d.ts.map +1 -0
  169. package/dist/input/rebind-controller.js +85 -0
  170. package/dist/input/schema.d.ts +16 -0
  171. package/dist/input/schema.d.ts.map +1 -0
  172. package/dist/input/schema.js +228 -0
  173. package/dist/loader.d.ts +43 -0
  174. package/dist/loader.d.ts.map +1 -0
  175. package/dist/loader.js +59 -0
  176. package/dist/manifest/index.d.ts +5 -0
  177. package/dist/manifest/index.d.ts.map +1 -0
  178. package/dist/manifest/index.js +8 -0
  179. package/dist/manifest/load-file.d.ts +4 -0
  180. package/dist/manifest/load-file.d.ts.map +1 -0
  181. package/dist/manifest/load-file.js +14 -0
  182. package/dist/manifest/load.d.ts +117 -0
  183. package/dist/manifest/load.d.ts.map +1 -0
  184. package/dist/manifest/load.js +255 -0
  185. package/dist/manifest/schema.d.ts +173 -0
  186. package/dist/manifest/schema.d.ts.map +1 -0
  187. package/dist/manifest/schema.js +302 -0
  188. package/dist/physics/collision-system.d.ts +41 -0
  189. package/dist/physics/collision-system.d.ts.map +1 -0
  190. package/dist/physics/collision-system.js +64 -0
  191. package/dist/physics/physics-registry.d.ts +45 -0
  192. package/dist/physics/physics-registry.d.ts.map +1 -0
  193. package/dist/physics/physics-registry.js +65 -0
  194. package/dist/physics/transform-writer.d.ts +16 -0
  195. package/dist/physics/transform-writer.d.ts.map +1 -0
  196. package/dist/physics/transform-writer.js +38 -0
  197. package/dist/physics/trigger-dispatch.d.ts +24 -0
  198. package/dist/physics/trigger-dispatch.d.ts.map +1 -0
  199. package/dist/physics/trigger-dispatch.js +80 -0
  200. package/dist/react/game-state.d.ts +105 -0
  201. package/dist/react/game-state.d.ts.map +1 -0
  202. package/dist/react/game-state.js +144 -0
  203. package/dist/react/use-data.d.ts +60 -0
  204. package/dist/react/use-data.d.ts.map +1 -0
  205. package/dist/react/use-data.js +96 -0
  206. package/dist/react/use-selection.d.ts +75 -0
  207. package/dist/react/use-selection.d.ts.map +1 -0
  208. package/dist/react/use-selection.js +90 -0
  209. package/dist/render/auto-batcher.d.ts +34 -0
  210. package/dist/render/auto-batcher.d.ts.map +1 -0
  211. package/dist/render/auto-batcher.js +140 -0
  212. package/dist/render/render-batch-system.d.ts +33 -0
  213. package/dist/render/render-batch-system.d.ts.map +1 -0
  214. package/dist/render/render-batch-system.js +230 -0
  215. package/dist/render/render-features.d.ts +47 -0
  216. package/dist/render/render-features.d.ts.map +1 -0
  217. package/dist/render/render-features.js +105 -0
  218. package/dist/render/render-settings.d.ts +36 -0
  219. package/dist/render/render-settings.d.ts.map +1 -0
  220. package/dist/render/render-settings.js +51 -0
  221. package/dist/runtime/create-runtime.d.ts +280 -0
  222. package/dist/runtime/create-runtime.d.ts.map +1 -0
  223. package/dist/runtime/create-runtime.js +795 -0
  224. package/dist/runtime/frame-selector-cache.d.ts +41 -0
  225. package/dist/runtime/frame-selector-cache.d.ts.map +1 -0
  226. package/dist/runtime/frame-selector-cache.js +65 -0
  227. package/dist/runtime/game.d.ts +433 -0
  228. package/dist/runtime/game.d.ts.map +1 -0
  229. package/dist/runtime/game.js +569 -0
  230. package/dist/runtime/input-router.d.ts +78 -0
  231. package/dist/runtime/input-router.d.ts.map +1 -0
  232. package/dist/runtime/input-router.js +171 -0
  233. package/dist/runtime/mount-game.d.ts +129 -0
  234. package/dist/runtime/mount-game.d.ts.map +1 -0
  235. package/dist/runtime/mount-game.js +152 -0
  236. package/dist/runtime/mount-manifest.d.ts +119 -0
  237. package/dist/runtime/mount-manifest.d.ts.map +1 -0
  238. package/dist/runtime/mount-manifest.js +204 -0
  239. package/dist/runtime/render-audio-control.d.ts +110 -0
  240. package/dist/runtime/render-audio-control.d.ts.map +1 -0
  241. package/dist/runtime/render-audio-control.js +111 -0
  242. package/dist/runtime/render-control.d.ts +291 -0
  243. package/dist/runtime/render-control.d.ts.map +1 -0
  244. package/dist/runtime/render-control.js +264 -0
  245. package/dist/runtime/render-seed.d.ts +57 -0
  246. package/dist/runtime/render-seed.d.ts.map +1 -0
  247. package/dist/runtime/render-seed.js +74 -0
  248. package/dist/runtime/scene-ui-bridge.d.ts +69 -0
  249. package/dist/runtime/scene-ui-bridge.d.ts.map +1 -0
  250. package/dist/runtime/scene-ui-bridge.js +23 -0
  251. package/dist/runtime/scene-ui-data.d.ts +13 -0
  252. package/dist/runtime/scene-ui-data.d.ts.map +1 -0
  253. package/dist/runtime/scene-ui-data.js +92 -0
  254. package/dist/runtime/state-bridge.d.ts +47 -0
  255. package/dist/runtime/state-bridge.d.ts.map +1 -0
  256. package/dist/runtime/state-bridge.js +53 -0
  257. package/dist/runtime/types.d.ts +179 -0
  258. package/dist/runtime/types.d.ts.map +1 -0
  259. package/dist/runtime/types.js +1 -0
  260. package/dist/scene/asset-loaders.d.ts +79 -0
  261. package/dist/scene/asset-loaders.d.ts.map +1 -0
  262. package/dist/scene/asset-loaders.js +141 -0
  263. package/dist/scene/asset-paths.d.ts +11 -0
  264. package/dist/scene/asset-paths.d.ts.map +1 -0
  265. package/dist/scene/asset-paths.js +108 -0
  266. package/dist/scene/asset-ref-check.d.ts +88 -0
  267. package/dist/scene/asset-ref-check.d.ts.map +1 -0
  268. package/dist/scene/asset-ref-check.js +214 -0
  269. package/dist/scene/asset-registry.d.ts +30 -0
  270. package/dist/scene/asset-registry.d.ts.map +1 -0
  271. package/dist/scene/asset-registry.js +50 -0
  272. package/dist/scene/collider-dimensions.d.ts +63 -0
  273. package/dist/scene/collider-dimensions.d.ts.map +1 -0
  274. package/dist/scene/collider-dimensions.js +98 -0
  275. package/dist/scene/component-registry.d.ts +17 -0
  276. package/dist/scene/component-registry.d.ts.map +1 -0
  277. package/dist/scene/component-registry.js +28 -0
  278. package/dist/scene/defaults.d.ts +252 -0
  279. package/dist/scene/defaults.d.ts.map +1 -0
  280. package/dist/scene/defaults.js +151 -0
  281. package/dist/scene/geometries/index.d.ts +8 -0
  282. package/dist/scene/geometries/index.d.ts.map +1 -0
  283. package/dist/scene/geometries/index.js +7 -0
  284. package/dist/scene/geometries/terrain.d.ts +2 -0
  285. package/dist/scene/geometries/terrain.d.ts.map +1 -0
  286. package/dist/scene/geometries/terrain.js +37 -0
  287. package/dist/scene/geometry-registry.d.ts +24 -0
  288. package/dist/scene/geometry-registry.d.ts.map +1 -0
  289. package/dist/scene/geometry-registry.js +20 -0
  290. package/dist/scene/instance-registry.d.ts +36 -0
  291. package/dist/scene/instance-registry.d.ts.map +1 -0
  292. package/dist/scene/instance-registry.js +55 -0
  293. package/dist/scene/instancers/grid.d.ts +2 -0
  294. package/dist/scene/instancers/grid.d.ts.map +1 -0
  295. package/dist/scene/instancers/grid.js +36 -0
  296. package/dist/scene/instancers/index.d.ts +8 -0
  297. package/dist/scene/instancers/index.d.ts.map +1 -0
  298. package/dist/scene/instancers/index.js +7 -0
  299. package/dist/scene/light-camera-factory.d.ts +23 -0
  300. package/dist/scene/light-camera-factory.d.ts.map +1 -0
  301. package/dist/scene/light-camera-factory.js +68 -0
  302. package/dist/scene/material-factory.d.ts +17 -0
  303. package/dist/scene/material-factory.d.ts.map +1 -0
  304. package/dist/scene/material-factory.js +197 -0
  305. package/dist/scene/material-registry.d.ts +40 -0
  306. package/dist/scene/material-registry.d.ts.map +1 -0
  307. package/dist/scene/material-registry.js +44 -0
  308. package/dist/scene/materials/index.d.ts +8 -0
  309. package/dist/scene/materials/index.d.ts.map +1 -0
  310. package/dist/scene/materials/index.js +7 -0
  311. package/dist/scene/materials/water.d.ts +2 -0
  312. package/dist/scene/materials/water.d.ts.map +1 -0
  313. package/dist/scene/materials/water.js +54 -0
  314. package/dist/scene/parse.d.ts +23 -0
  315. package/dist/scene/parse.d.ts.map +1 -0
  316. package/dist/scene/parse.js +179 -0
  317. package/dist/scene/particles-factory.d.ts +33 -0
  318. package/dist/scene/particles-factory.d.ts.map +1 -0
  319. package/dist/scene/particles-factory.js +282 -0
  320. package/dist/scene/scene-apply.d.ts +109 -0
  321. package/dist/scene/scene-apply.d.ts.map +1 -0
  322. package/dist/scene/scene-apply.js +326 -0
  323. package/dist/scene/scene-diff-schema.d.ts +285 -0
  324. package/dist/scene/scene-diff-schema.d.ts.map +1 -0
  325. package/dist/scene/scene-diff-schema.js +92 -0
  326. package/dist/scene/scene-diff-types.d.ts +40 -0
  327. package/dist/scene/scene-diff-types.d.ts.map +1 -0
  328. package/dist/scene/scene-diff-types.js +14 -0
  329. package/dist/scene/scene-loader.d.ts +177 -0
  330. package/dist/scene/scene-loader.d.ts.map +1 -0
  331. package/dist/scene/scene-loader.js +1213 -0
  332. package/dist/scene/scene-query.d.ts +11 -0
  333. package/dist/scene/scene-query.d.ts.map +1 -0
  334. package/dist/scene/scene-query.js +63 -0
  335. package/dist/scene/scene-types.d.ts +10 -0
  336. package/dist/scene/scene-types.d.ts.map +1 -0
  337. package/dist/scene/scene-types.js +8 -0
  338. package/dist/scene/scene-version.d.ts +26 -0
  339. package/dist/scene/scene-version.d.ts.map +1 -0
  340. package/dist/scene/scene-version.js +34 -0
  341. package/dist/scene/schema/animation.d.ts +8 -0
  342. package/dist/scene/schema/animation.d.ts.map +1 -0
  343. package/dist/scene/schema/animation.js +42 -0
  344. package/dist/scene/schema/audio.d.ts +13 -0
  345. package/dist/scene/schema/audio.d.ts.map +1 -0
  346. package/dist/scene/schema/audio.js +22 -0
  347. package/dist/scene/schema/camera.d.ts +28 -0
  348. package/dist/scene/schema/camera.d.ts.map +1 -0
  349. package/dist/scene/schema/camera.js +17 -0
  350. package/dist/scene/schema/collider.d.ts +40 -0
  351. package/dist/scene/schema/collider.d.ts.map +1 -0
  352. package/dist/scene/schema/collider.js +55 -0
  353. package/dist/scene/schema/entity-ref.d.ts +31 -0
  354. package/dist/scene/schema/entity-ref.d.ts.map +1 -0
  355. package/dist/scene/schema/entity-ref.js +61 -0
  356. package/dist/scene/schema/entity.d.ts +1036 -0
  357. package/dist/scene/schema/entity.d.ts.map +1 -0
  358. package/dist/scene/schema/entity.js +153 -0
  359. package/dist/scene/schema/environment.d.ts +425 -0
  360. package/dist/scene/schema/environment.d.ts.map +1 -0
  361. package/dist/scene/schema/environment.js +357 -0
  362. package/dist/scene/schema/index.d.ts +39 -0
  363. package/dist/scene/schema/index.d.ts.map +1 -0
  364. package/dist/scene/schema/index.js +20 -0
  365. package/dist/scene/schema/instances.d.ts +14 -0
  366. package/dist/scene/schema/instances.d.ts.map +1 -0
  367. package/dist/scene/schema/instances.js +28 -0
  368. package/dist/scene/schema/joint.d.ts +23 -0
  369. package/dist/scene/schema/joint.d.ts.map +1 -0
  370. package/dist/scene/schema/joint.js +23 -0
  371. package/dist/scene/schema/light.d.ts +38 -0
  372. package/dist/scene/schema/light.d.ts.map +1 -0
  373. package/dist/scene/schema/light.js +26 -0
  374. package/dist/scene/schema/material.d.ts +199 -0
  375. package/dist/scene/schema/material.d.ts.map +1 -0
  376. package/dist/scene/schema/material.js +99 -0
  377. package/dist/scene/schema/mesh.d.ts +48 -0
  378. package/dist/scene/schema/mesh.d.ts.map +1 -0
  379. package/dist/scene/schema/mesh.js +82 -0
  380. package/dist/scene/schema/particles.d.ts +2178 -0
  381. package/dist/scene/schema/particles.d.ts.map +1 -0
  382. package/dist/scene/schema/particles.js +321 -0
  383. package/dist/scene/schema/physics.d.ts +56 -0
  384. package/dist/scene/schema/physics.d.ts.map +1 -0
  385. package/dist/scene/schema/physics.js +37 -0
  386. package/dist/scene/schema/scene-file.d.ts +304 -0
  387. package/dist/scene/schema/scene-file.d.ts.map +1 -0
  388. package/dist/scene/schema/scene-file.js +262 -0
  389. package/dist/scene/schema/shadow.d.ts +28 -0
  390. package/dist/scene/schema/shadow.d.ts.map +1 -0
  391. package/dist/scene/schema/shadow.js +20 -0
  392. package/dist/scene/schema/spline.d.ts +25 -0
  393. package/dist/scene/schema/spline.d.ts.map +1 -0
  394. package/dist/scene/schema/spline.js +15 -0
  395. package/dist/scene/schema/tuples.d.ts +12 -0
  396. package/dist/scene/schema/tuples.d.ts.map +1 -0
  397. package/dist/scene/schema/tuples.js +14 -0
  398. package/dist/scene/schema/ui.d.ts +880 -0
  399. package/dist/scene/schema/ui.d.ts.map +1 -0
  400. package/dist/scene/schema/ui.js +506 -0
  401. package/dist/scene/user-data.d.ts +171 -0
  402. package/dist/scene/user-data.d.ts.map +1 -0
  403. package/dist/scene/user-data.js +137 -0
  404. package/dist/setup/setup-audio.d.ts +20 -0
  405. package/dist/setup/setup-audio.d.ts.map +1 -0
  406. package/dist/setup/setup-audio.js +41 -0
  407. package/dist/setup/setup-particles.d.ts +17 -0
  408. package/dist/setup/setup-particles.d.ts.map +1 -0
  409. package/dist/setup/setup-particles.js +16 -0
  410. package/dist/setup/setup-physics.d.ts +25 -0
  411. package/dist/setup/setup-physics.d.ts.map +1 -0
  412. package/dist/setup/setup-physics.js +51 -0
  413. package/dist/setup/setup-renderer.d.ts +69 -0
  414. package/dist/setup/setup-renderer.d.ts.map +1 -0
  415. package/dist/setup/setup-renderer.js +363 -0
  416. package/dist/tools/define-tool.d.ts +105 -0
  417. package/dist/tools/define-tool.d.ts.map +1 -0
  418. package/dist/tools/define-tool.js +82 -0
  419. package/dist/world2d/authoring-2d.d.ts +76 -0
  420. package/dist/world2d/authoring-2d.d.ts.map +1 -0
  421. package/dist/world2d/authoring-2d.js +176 -0
  422. package/dist/world2d/capture-to-scene2d.d.ts +5 -0
  423. package/dist/world2d/capture-to-scene2d.d.ts.map +1 -0
  424. package/dist/world2d/capture-to-scene2d.js +49 -0
  425. package/dist/world2d/collision-2d.d.ts +52 -0
  426. package/dist/world2d/collision-2d.d.ts.map +1 -0
  427. package/dist/world2d/collision-2d.js +70 -0
  428. package/dist/world2d/components-2d.d.ts +47 -0
  429. package/dist/world2d/components-2d.d.ts.map +1 -0
  430. package/dist/world2d/components-2d.js +77 -0
  431. package/dist/world2d/index.d.ts +34 -0
  432. package/dist/world2d/index.d.ts.map +1 -0
  433. package/dist/world2d/index.js +32 -0
  434. package/dist/world2d/ingest-iframe-2d.d.ts +82 -0
  435. package/dist/world2d/ingest-iframe-2d.d.ts.map +1 -0
  436. package/dist/world2d/ingest-iframe-2d.js +166 -0
  437. package/dist/world2d/ingest2d.d.ts +97 -0
  438. package/dist/world2d/ingest2d.d.ts.map +1 -0
  439. package/dist/world2d/ingest2d.js +40 -0
  440. package/dist/world2d/physics2d-registry.d.ts +24 -0
  441. package/dist/world2d/physics2d-registry.d.ts.map +1 -0
  442. package/dist/world2d/physics2d-registry.js +38 -0
  443. package/dist/world2d/pixi-game-adapter.d.ts +107 -0
  444. package/dist/world2d/pixi-game-adapter.d.ts.map +1 -0
  445. package/dist/world2d/pixi-game-adapter.js +211 -0
  446. package/dist/world2d/pixi-surface.d.ts +39 -0
  447. package/dist/world2d/pixi-surface.d.ts.map +1 -0
  448. package/dist/world2d/pixi-surface.js +47 -0
  449. package/dist/world2d/scene-capture-2d.d.ts +43 -0
  450. package/dist/world2d/scene-capture-2d.d.ts.map +1 -0
  451. package/dist/world2d/scene-capture-2d.js +92 -0
  452. package/dist/world2d/scene2d-loader.d.ts +27 -0
  453. package/dist/world2d/scene2d-loader.d.ts.map +1 -0
  454. package/dist/world2d/scene2d-loader.js +274 -0
  455. package/dist/world2d/schema/entity2d.d.ts +102 -0
  456. package/dist/world2d/schema/entity2d.d.ts.map +1 -0
  457. package/dist/world2d/schema/entity2d.js +119 -0
  458. package/dist/world2d/schema/physics2d.d.ts +46 -0
  459. package/dist/world2d/schema/physics2d.d.ts.map +1 -0
  460. package/dist/world2d/schema/physics2d.js +45 -0
  461. package/dist/world2d/schema/sprite.d.ts +42 -0
  462. package/dist/world2d/schema/sprite.d.ts.map +1 -0
  463. package/dist/world2d/schema/sprite.js +63 -0
  464. package/dist/world2d/schema/tilemap.d.ts +15 -0
  465. package/dist/world2d/schema/tilemap.d.ts.map +1 -0
  466. package/dist/world2d/schema/tilemap.js +19 -0
  467. package/dist/world2d/schema/tuples2d.d.ts +20 -0
  468. package/dist/world2d/schema/tuples2d.d.ts.map +1 -0
  469. package/dist/world2d/schema/tuples2d.js +19 -0
  470. package/dist/world2d/system-adapters-2d.d.ts +16 -0
  471. package/dist/world2d/system-adapters-2d.d.ts.map +1 -0
  472. package/dist/world2d/system-adapters-2d.js +37 -0
  473. package/dist/world2d/transform-writer-2d.d.ts +16 -0
  474. package/dist/world2d/transform-writer-2d.d.ts.map +1 -0
  475. package/dist/world2d/transform-writer-2d.js +22 -0
  476. package/dist/world2d/types.d.ts +53 -0
  477. package/dist/world2d/types.d.ts.map +1 -0
  478. package/dist/world2d/types.js +1 -0
  479. package/package.json +18 -4
  480. package/src/adapter/authoring.ts +10 -0
  481. package/src/adapter/first-party-systems.ts +23 -34
  482. package/src/adapter/index.ts +1 -3
  483. package/src/adapter/system-adapter.ts +15 -22
  484. package/src/adapter/vgai-scene-game-adapter.ts +5 -14
  485. package/src/animation/anim-graph-types.ts +12 -43
  486. package/src/animation/animation-clock.ts +479 -0
  487. package/src/animation/camera-ownership.ts +467 -0
  488. package/src/animation/cinematic-cues.ts +451 -0
  489. package/src/animation/clip-map.ts +41 -0
  490. package/src/animation/gsap-registration.ts +184 -0
  491. package/src/animation/theatre-clock-binding.ts +111 -0
  492. package/src/animation/theatre-director.ts +347 -0
  493. package/src/animation/theatre-object-binding.ts +661 -0
  494. package/src/animation/xstate-animation-binding.ts +398 -0
  495. package/src/animation/xstate-animation-meta.ts +282 -0
  496. package/src/audio/index.ts +39 -7
  497. package/src/audio/tone-clock-binding.ts +98 -0
  498. package/src/audio/tone-context.ts +129 -0
  499. package/src/audio/tone-offline-render.ts +167 -0
  500. package/src/audio/wav-encode.ts +119 -0
  501. package/src/core/game-loop.ts +17 -0
  502. package/src/core/types.ts +13 -0
  503. package/src/data/data-asset.ts +167 -0
  504. package/src/data/data-check-core.ts +242 -0
  505. package/src/data/data-ref.ts +145 -0
  506. package/src/data/vite-plugin-data.ts +290 -0
  507. package/src/index.ts +48 -0
  508. package/src/input/input-manager.ts +1206 -32
  509. package/src/input/input-types.ts +155 -3
  510. package/src/input/prompt-labels.ts +122 -0
  511. package/src/input/rebind-controller.ts +105 -0
  512. package/src/input/schema.ts +206 -52
  513. package/src/react/use-data.ts +114 -0
  514. package/src/react/use-selection.tsx +135 -0
  515. package/src/runtime/create-runtime.ts +30 -9
  516. package/src/runtime/render-audio-control.ts +168 -0
  517. package/src/runtime/render-control.ts +522 -0
  518. package/src/runtime/render-seed.ts +79 -0
  519. package/src/runtime/types.ts +0 -5
  520. package/src/scene/asset-loaders.ts +10 -36
  521. package/src/scene/asset-paths.ts +0 -2
  522. package/src/scene/asset-ref-check.ts +248 -0
  523. package/src/scene/parse.ts +133 -0
  524. package/src/scene/scene-loader.ts +81 -96
  525. package/src/scene/schema/animation.ts +30 -79
  526. package/src/scene/schema/entity.ts +20 -0
  527. package/src/scene/schema/index.ts +2 -12
  528. package/src/scene/user-data.ts +8 -9
  529. package/src/setup/setup-renderer.ts +9 -2
  530. package/src/tools/define-tool.ts +152 -0
  531. package/src/animation/anim-graph.ts +0 -406
  532. package/src/animation/anim-system.ts +0 -28
  533. package/src/animation/property-track.ts +0 -178
  534. package/src/animation/schema.ts +0 -204
  535. package/src/audio/ambient.ts +0 -300
  536. package/src/audio/impacts.ts +0 -212
  537. package/src/audio/movement.ts +0 -140
  538. package/src/audio/musical.ts +0 -200
  539. package/src/audio/ui-sounds.ts +0 -171
  540. package/src/audio/vehicle.ts +0 -235
  541. package/src/audio/weapons.ts +0 -152
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Data assets — W1 of `docs/DATA-TOOLS-DESIGN.md` (§2.3 consumption API).
3
+ *
4
+ * A data asset is designer-tunable game data: a JSON file in the project's
5
+ * `src/data/`, governed by a Zod schema (`*.schema.ts`, engineer-owned) whose
6
+ * emitted JSON Schema (`*.schema.json`, see {@link toDataJsonSchema}) gives
7
+ * VS Code validation via the data file's `"$schema"` first line. Data assets
8
+ * are immutable at runtime — definitions, not state (§2.1).
9
+ *
10
+ * The blessed consumption shape, scaffolded working-at-birth by the project
11
+ * template (`src/data/` there is the worked example — §6.2):
12
+ *
13
+ * ```ts
14
+ * import raw from './tuning.data.json';
15
+ * import { TuningSchema } from './tuning.schema';
16
+ * import { defineData } from '@engine/data/data-asset';
17
+ *
18
+ * export const tuning = defineData(TuningSchema, raw, 'src/data/tuning.data.json');
19
+ * // Vite HMR needs the literal dep path in THIS module (static analysis) —
20
+ * // this one line is the entire live-tuning wiring (['default'] not .default:
21
+ * // strict tsconfigs index-signature ModuleNamespace):
22
+ * import.meta.hot?.accept('./tuning.data.json', (m) => tuning.hotSwap(m?.['default']));
23
+ * ```
24
+ *
25
+ * Game code reads `tuning.get()` inside its update loop (never cache fields
26
+ * across frames) or `subscribe()`s; an edit to the `.data.json` — from
27
+ * VS Code, an agent, or the future editor Data tab (W2) — flows through Vite
28
+ * HMR into the running game with no remount. React worlds/tools get a
29
+ * `useData` hook with W3's tool-hooks package (deferred with it: the engine
30
+ * core stays React-free).
31
+ */
32
+
33
+ import { z } from 'zod';
34
+
35
+ /**
36
+ * A live handle to one data asset (§2.3). `get`/`subscribe` are the whole
37
+ * runtime surface; `hotSwap` exists only for the owning module's
38
+ * `import.meta.hot.accept` callback.
39
+ */
40
+ export interface DataHandle<T> {
41
+ /** Current parsed values. Read every frame — HMR swaps them under you. */
42
+ get(): T;
43
+ /**
44
+ * Called with the new value after every successful hot swap (NOT with the
45
+ * initial value). Returns an unsubscribe function.
46
+ */
47
+ subscribe(fn: (value: T) => void): () => void;
48
+ /**
49
+ * HMR entry point — call from the owning module's
50
+ * `import.meta.hot.accept('<file>.data.json', (m) => handle.hotSwap(m?.default))`.
51
+ * Parses like load, but a FAILING edit keeps the last good value and
52
+ * `console.error`s instead of throwing: a typo mid-live-tune must not
53
+ * crash the running game. Fix the file and save again.
54
+ */
55
+ hotSwap(next: unknown): void;
56
+ /**
57
+ * The project-relative path this handle was defined with (`defineData`'s
58
+ * own `sourcePath` argument, populated automatically below) — OPTIONAL so
59
+ * any hand-rolled structural implementer stays valid. `getRef`
60
+ * (`./data-ref.ts`) reads this to catch a `getRef(wrongHandle, "stem#key")`
61
+ * mismatch with a teaching error instead of silently resolving against the
62
+ * wrong asset; without it, `getRef` just skips that one check.
63
+ */
64
+ readonly sourcePath?: string;
65
+ }
66
+
67
+ /**
68
+ * Define a data asset from its Zod schema, the statically imported JSON, and
69
+ * its project-relative path (used verbatim in error messages, so pass the
70
+ * real one). Parse-on-load: an invalid file fails loud at import time, naming
71
+ * the file, every bad path, and the fix (§2.3, §6.5 "errors teach").
72
+ *
73
+ * Schema fields should carry `.min/.max/.default/.describe` — the same
74
+ * annotations `GameComponent.static schema` uses — so the emitted JSON Schema
75
+ * documents the file and (W2+) the editor renders real widgets.
76
+ */
77
+ export function defineData<S extends z.ZodType>(
78
+ schema: S,
79
+ initial: unknown,
80
+ sourcePath: string,
81
+ ): DataHandle<z.output<S>> {
82
+ let current = parseDataJson(schema, initial, sourcePath);
83
+ const subscribers = new Set<(value: z.output<S>) => void>();
84
+ return {
85
+ get: () => current,
86
+ sourcePath,
87
+ subscribe(fn) {
88
+ subscribers.add(fn);
89
+ return () => subscribers.delete(fn);
90
+ },
91
+ hotSwap(next) {
92
+ let parsed: z.output<S>;
93
+ try {
94
+ parsed = parseDataJson(schema, next, sourcePath);
95
+ } catch (err) {
96
+ // Keep the last good value alive — see the JSDoc on DataHandle.hotSwap.
97
+ // biome-ignore lint/suspicious/noConsole: deliberate, greppable — a rejected live-tune edit must be loud without crashing the running game (mirrors overlay-report.ts's direct console use)
98
+ console.error(`[data] hot edit rejected, keeping previous values.\n${String(err)}`);
99
+ return;
100
+ }
101
+ current = parsed;
102
+ for (const fn of subscribers) fn(current);
103
+ },
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Emit the JSON Schema interchange artifact for a data asset's Zod schema
109
+ * (§2.1: `*.schema.json` is EMITTED, never hand-written; D4: generated and
110
+ * committed by default so VS Code works with no dev server running).
111
+ *
112
+ * Wraps `z.toJSONSchema` with `io: 'input'` — the one non-obvious knob:
113
+ * defaulted fields must be OPTIONAL in the file schema (a data file may omit
114
+ * them), whereas the default output mode would mark every field `required`
115
+ * and make VS Code reject valid files. The template's root `emit-schemas.ts`
116
+ * is the blessed caller (`npm run emit-schemas`).
117
+ *
118
+ * The emitted root schema also explicitly ALLOWS the `"$schema"` string
119
+ * property, mirroring the parse-side strip below: without it, a TABLE
120
+ * asset's emitted schema (`z.record` → `additionalProperties: <rowSchema>`)
121
+ * makes VS Code flag the data file's own `"$schema"` line as an invalid row.
122
+ */
123
+ export function toDataJsonSchema(schema: z.ZodType): Record<string, unknown> {
124
+ const emitted = z.toJSONSchema(schema, { io: 'input' }) as Record<string, unknown>;
125
+ if (emitted['type'] === 'object') {
126
+ const properties = (emitted['properties'] ?? {}) as Record<string, unknown>;
127
+ properties['$schema'] ??= { type: 'string' };
128
+ emitted['properties'] = properties;
129
+ }
130
+ return emitted;
131
+ }
132
+
133
+ /**
134
+ * Parse a raw `.data.json` payload: strips the `"$schema"` interchange line,
135
+ * validates through the Zod schema, throws the teaching error on failure.
136
+ * `defineData` uses this internally on load and hot swap; it is exported for
137
+ * emit/doctor-style scripts (the template's `emit-schemas.ts` validates every
138
+ * data file through it, so file validation and runtime validation can never
139
+ * disagree).
140
+ */
141
+ export function parseDataJson<S extends z.ZodType>(
142
+ schema: S,
143
+ data: unknown,
144
+ sourcePath: string,
145
+ ): z.output<S> {
146
+ // Strip the data file's `"$schema"` interchange line before validating —
147
+ // singleton (z.object, strip-mode) schemas ignored it by luck, but a TABLE
148
+ // asset (z.record) would try to validate it as a row and fail.
149
+ const payload =
150
+ data !== null && typeof data === 'object' && !Array.isArray(data) && '$schema' in data
151
+ ? Object.fromEntries(Object.entries(data).filter(([key]) => key !== '$schema'))
152
+ : data;
153
+ const result = schema.safeParse(payload);
154
+ if (!result.success) {
155
+ const issues = result.error.issues
156
+ .map((issue) => ` - ${issue.path.join('.') || '(root)'}: ${issue.message}`)
157
+ .join('\n');
158
+ throw new Error(
159
+ `Data asset "${sourcePath}" failed its schema:\n${issues}\n` +
160
+ `Fix the JSON to match the Zod schema (its emitted twin, ` +
161
+ `"${sourcePath.replace(/\.data\.json$/, '.schema.json')}", documents every field — ` +
162
+ `re-emit with \`npm run emit-schemas\` if the schema changed). ` +
163
+ `Worked example: the template's src/data/.`,
164
+ );
165
+ }
166
+ return result.data;
167
+ }
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Data-asset integrity core — the PURE half of W5 enforcement
3
+ * (docs/DATA-TOOLS-DESIGN.md §6.6 "dangling `file#key` ref" / §6.7 build-path
4
+ * validation). No filesystem, no vite, no zod: plain parsed-JSON in, findings
5
+ * out, so BOTH consumers — `vgai doctor`'s data checks
6
+ * (`packages/editor/src/doctor/data-checks.ts`) and the build-time plugin
7
+ * (`./vite-plugin-data.ts`) — share one definition of "what is a ref" and
8
+ * "what counts as dangling" and can never drift apart.
9
+ *
10
+ * What is a ref (§2.2): a cross-asset reference is a plain string
11
+ * `"file#key"` — optionally with a field path, `"tuning#economy.slotGrowth"`
12
+ * (file `#` key `.` field-path). There is no branded-ref Zod helper shipped
13
+ * yet (W1 deferred it), so ref DETECTION is by convention, tuned against
14
+ * false positives: a string is treated as a ref IFF it matches
15
+ * {@link DATA_REF_PATTERN} AND its `file` prefix names a data asset that
16
+ * actually exists in the project (`src/data/<file>.data.json`). Strings that
17
+ * merely contain `#` — hex colors (`"#ff0000"`, no prefix), URLs with
18
+ * fragments (`/` and `:` never match), musical pitches (`"C#4"` only matches
19
+ * if a `C.data.json` exists) — never fire. The flip side is deliberate and
20
+ * honest: a ref whose file prefix names a NONEXISTENT asset is
21
+ * indistinguishable from an arbitrary string and is NOT flagged ("error if
22
+ * refs exist yet" — the check only bites once the target file exists).
23
+ *
24
+ * `dataRef` (`./data-ref.ts`) now exists, closing that flip side for anyone
25
+ * who adopts it: a `dataRef(target)` field's EMITTED schema carries
26
+ * `"x-vgai-ref": target` — a declared intent, independent of whether the
27
+ * target file currently exists. {@link collectDeclaredRefFields} /
28
+ * {@link findMissingRefTargets} below walk that (zod-free — plain emitted
29
+ * JSON Schema in, findings out, same purity contract as the rest of this
30
+ * module) to catch the §9.4 hole for DECLARED refs: renaming/deleting a
31
+ * target file used to silently un-check every ref into it; now a declared
32
+ * ref's target is checked by NAME, not by "does a string happen to look
33
+ * like one right now." Undeclared conventional-string refs keep the
34
+ * calibrated behavior above, unchanged.
35
+ */
36
+
37
+ /**
38
+ * `file#key(.field)*` — prefix must look like an asset stem (letters,
39
+ * digits, `_`, `-`), key path is dot-separated segments of the same alphabet.
40
+ */
41
+ export const DATA_REF_PATTERN = /^([A-Za-z0-9_-]+)#([A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)*)$/;
42
+
43
+ /** One ref-shaped string found while walking a data file's parsed JSON. */
44
+ export interface DataRefOccurrence {
45
+ /** Asset stem of the data file the ref string was found IN (e.g. `"tuning"`). */
46
+ readonly inAsset: string;
47
+ /** JSON path of the string inside that file (e.g. `"rows.goblin.drops[2]"`). */
48
+ readonly atPath: string;
49
+ /** The full ref string, verbatim (e.g. `"enemies#goblin"`). */
50
+ readonly ref: string;
51
+ /** Parsed target asset stem (`"enemies"`). */
52
+ readonly targetAsset: string;
53
+ /** Parsed dot-separated key path into the target (`["goblin"]`). */
54
+ readonly targetKeyPath: readonly string[];
55
+ }
56
+
57
+ /** One dangling ref: the target FILE exists but the key path does not resolve in it. */
58
+ export interface DanglingRefFinding extends DataRefOccurrence {
59
+ /** The first key-path segment that failed to resolve, for the teaching message. */
60
+ readonly missingSegment: string;
61
+ }
62
+
63
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
64
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
65
+ }
66
+
67
+ /**
68
+ * Walk one data file's parsed JSON and collect every ref-shaped string whose
69
+ * file prefix names an asset in `assetNames`. The top-level `"$schema"`
70
+ * interchange line is skipped (it is wiring, not data — same special-casing
71
+ * as `parseDataJson`'s strip).
72
+ */
73
+ export function collectDataRefs(
74
+ inAsset: string,
75
+ json: unknown,
76
+ assetNames: ReadonlySet<string>,
77
+ ): DataRefOccurrence[] {
78
+ const out: DataRefOccurrence[] = [];
79
+ visitForRefs(json, '', true, (node, path) => {
80
+ const occurrence = asRefOccurrence(inAsset, node, path, assetNames);
81
+ if (occurrence) out.push(occurrence);
82
+ });
83
+ return out;
84
+ }
85
+
86
+ /** Depth-first walk over parsed JSON, calling `onString` for every string leaf with its JSON path. */
87
+ function visitForRefs(
88
+ node: unknown,
89
+ path: string,
90
+ topLevel: boolean,
91
+ onString: (value: string, path: string) => void,
92
+ ): void {
93
+ if (typeof node === 'string') {
94
+ onString(node, path);
95
+ return;
96
+ }
97
+ if (Array.isArray(node)) {
98
+ node.forEach((item, i) => {
99
+ visitForRefs(item, `${path}[${i}]`, false, onString);
100
+ });
101
+ return;
102
+ }
103
+ if (isPlainObject(node)) {
104
+ for (const [key, value] of Object.entries(node)) {
105
+ if (topLevel && key === '$schema') continue;
106
+ visitForRefs(value, path ? `${path}.${key}` : key, false, onString);
107
+ }
108
+ }
109
+ }
110
+
111
+ /** The string is a ref iff it matches the pattern AND its file prefix names a real asset. */
112
+ function asRefOccurrence(
113
+ inAsset: string,
114
+ value: string,
115
+ path: string,
116
+ assetNames: ReadonlySet<string>,
117
+ ): DataRefOccurrence | null {
118
+ const m = DATA_REF_PATTERN.exec(value);
119
+ if (!m || !assetNames.has(m[1] as string)) return null;
120
+ return {
121
+ inAsset,
122
+ atPath: path || '(root)',
123
+ ref: value,
124
+ targetAsset: m[1] as string,
125
+ targetKeyPath: (m[2] as string).split('.'),
126
+ };
127
+ }
128
+
129
+ /**
130
+ * Find every dangling `file#key(.field)*` ref across a project's data assets.
131
+ *
132
+ * @param files parsed `.data.json` payloads keyed by asset stem (the
133
+ * filename minus `.data.json` — the same name the ref's prefix uses, §2.2).
134
+ * Pass only files that parsed as JSON; unparseable files are already an
135
+ * error in their own right and can't be resolved against anyway.
136
+ * @returns one finding per ref whose target FILE is in `files` but whose key
137
+ * path does not fully resolve inside it (a table row that doesn't exist, a
138
+ * singleton field path that walks off the object).
139
+ */
140
+ export function findDanglingDataRefs(files: ReadonlyMap<string, unknown>): DanglingRefFinding[] {
141
+ const assetNames = new Set(files.keys());
142
+ const findings: DanglingRefFinding[] = [];
143
+ for (const [name, json] of files) {
144
+ for (const occurrence of collectDataRefs(name, json, assetNames)) {
145
+ const missing = firstUnresolvedSegment(files.get(occurrence.targetAsset), occurrence);
146
+ if (missing !== null) findings.push({ ...occurrence, missingSegment: missing });
147
+ }
148
+ }
149
+ return findings;
150
+ }
151
+
152
+ /** The first key-path segment that fails to resolve in the target payload, or `null` if the whole path resolves. */
153
+ function firstUnresolvedSegment(target: unknown, ref: DataRefOccurrence): string | null {
154
+ let node: unknown = target;
155
+ for (const segment of ref.targetKeyPath) {
156
+ if (!isPlainObject(node) || !(segment in node)) return segment;
157
+ node = node[segment];
158
+ }
159
+ return null;
160
+ }
161
+
162
+ /** One `dataRef` field declared in an emitted JSON Schema. */
163
+ export interface DeclaredRefField {
164
+ /** Dot-separated field path within the schema (e.g. `"drop"`, `"loot.dropTable"`). A table's row-schema fields are reported WITHOUT a row-key segment — the declaration applies to every row alike. */
165
+ readonly fieldPath: string;
166
+ /** The asset stem the field's `dataRef(...)` call named. */
167
+ readonly targetStem: string;
168
+ }
169
+
170
+ /** One declared ref whose target stem names no asset that currently exists. */
171
+ export interface MissingRefTargetFinding {
172
+ readonly fieldPath: string;
173
+ readonly targetStem: string;
174
+ }
175
+
176
+ /** Loosely-typed view of an emitted JSON Schema node — walked structurally, never through Zod (this module stays zod-free). */
177
+ interface JsonSchemaNode {
178
+ properties?: Record<string, unknown>;
179
+ additionalProperties?: unknown;
180
+ 'x-vgai-ref'?: unknown;
181
+ }
182
+
183
+ function asSchemaNode(value: unknown): JsonSchemaNode | null {
184
+ return value && typeof value === 'object' && !Array.isArray(value)
185
+ ? (value as JsonSchemaNode)
186
+ : null;
187
+ }
188
+
189
+ /**
190
+ * Walk an emitted data-asset JSON Schema (`toDataJsonSchema`'s output, or the
191
+ * committed `.schema.json` twin — same shape either way) and collect every
192
+ * field stamped `"x-vgai-ref": <target>` by `dataRef` (`./data-ref.ts`).
193
+ * Handles both blessed shapes (spec §2.1): a singleton's `properties`, and a
194
+ * table's `additionalProperties` row schema — walked with the SAME field
195
+ * path (a table's declared ref applies uniformly to every row, there is no
196
+ * per-row schema variation). Nested `properties` inside a ref-declaring
197
+ * field are not walked further (a ref leaf has no children); nested groups
198
+ * elsewhere recurse via their own `properties`.
199
+ */
200
+ export function collectDeclaredRefFields(schema: unknown): DeclaredRefField[] {
201
+ const out: DeclaredRefField[] = [];
202
+ walkForDeclaredRefs(schema, '', out);
203
+ return out;
204
+ }
205
+
206
+ function walkForDeclaredRefs(raw: unknown, path: string, out: DeclaredRefField[]): void {
207
+ const node = asSchemaNode(raw);
208
+ if (!node) return;
209
+
210
+ if (typeof node['x-vgai-ref'] === 'string') {
211
+ out.push({ fieldPath: path || '(root)', targetStem: node['x-vgai-ref'] });
212
+ return; // a ref leaf — nothing further to walk under it
213
+ }
214
+
215
+ if (isPlainObject(node.properties)) {
216
+ for (const [key, child] of Object.entries(node.properties)) {
217
+ if (key === '$schema') continue;
218
+ walkForDeclaredRefs(child, path ? `${path}.${key}` : key, out);
219
+ }
220
+ }
221
+ // A table's row schema (`z.record(rowSchema)` emits an object-valued
222
+ // `additionalProperties`) — same field-path grammar, no row-key segment.
223
+ if (isPlainObject(node.additionalProperties)) {
224
+ walkForDeclaredRefs(node.additionalProperties, path, out);
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Every declared ref field whose target stem names no asset in
230
+ * `assetNames` — the §9.4 fix: a `dataRef('items')` field stays flagged if
231
+ * `items.data.json` is renamed or deleted, independent of whether any
232
+ * CURRENT value happens to look like an `items#...` string (the gap the
233
+ * conventional-string calibration above deliberately leaves open).
234
+ */
235
+ export function findMissingRefTargets(
236
+ declared: readonly DeclaredRefField[],
237
+ assetNames: ReadonlySet<string>,
238
+ ): MissingRefTargetFinding[] {
239
+ return declared
240
+ .filter((d) => !assetNames.has(d.targetStem))
241
+ .map((d) => ({ fieldPath: d.fieldPath, targetStem: d.targetStem }));
242
+ }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * `file#key` refs — the resolvable half (docs/DATA-TOOLS-DESIGN.md §2.2).
3
+ *
4
+ * Cross-asset references (`"enemies#goblin"`, `"tuning#economy.slotGrowth"`)
5
+ * have been DETECTED and VALIDATED since W5 (`data-check-core.ts`'s
6
+ * `DATA_REF_PATTERN` + `findDanglingDataRefs`, enforced by both `vgai doctor`
7
+ * and the build plugin) — but nothing could actually RESOLVE one at runtime,
8
+ * and nothing declared a field AS a ref in its schema (detection was by
9
+ * string-shape convention alone). This module closes both halves:
10
+ *
11
+ * - {@link dataRef} — a typed Zod schema for a ref FIELD. Stamps the emitted
12
+ * JSON Schema with a precise `pattern` (the target stem is baked into the
13
+ * regex, so VS Code validates the prefix for free) and a machine-readable
14
+ * `"x-vgai-ref": target` marker (a Zod `.meta()` that survives
15
+ * `toDataJsonSchema`, including inside a table's `additionalProperties` row
16
+ * schema — no emitter changes needed). The editor's Data panel
17
+ * (`json-schema-fields.ts`'s `'ref'` kind) reads that marker to render a
18
+ * `stem#key` PICKER instead of free text.
19
+ * - {@link getRef} — lazy, read-time resolution. The caller names the target
20
+ * HANDLE explicitly (`getRef(items, goblin.drop)`), so the resolved type is
21
+ * the handle's own row type — no stem→handle registry, no load-order
22
+ * problem, no cycle hazard (nothing walks a graph; two refs resolved when
23
+ * you choose to resolve them isn't a cycle), and it's HMR-correct for free
24
+ * (it reads `target.get()` at CALL time, same doctrine as every other data
25
+ * read — "read every frame", never cache across frames).
26
+ *
27
+ * Deliberately NOT built (see docs/DATA-TOOLS-DESIGN.md §2.2 and the design
28
+ * note this module's history carries): eager resolution inside `defineData`
29
+ * (would change `get()`'s shipped output type and entangle HMR — an edit to
30
+ * `enemies.data.json` would have to re-notify every OTHER asset that
31
+ * references it), and a global `resolveRef(addressString)` (needs a runtime
32
+ * stem→handle registry that `src/data/assets.ts` — side-effect-free,
33
+ * config-load-time, schemas-only by its own module doc — must not become).
34
+ */
35
+
36
+ import { z } from 'zod';
37
+ import type { DataHandle } from './data-asset';
38
+ import { DATA_REF_PATTERN } from './data-check-core';
39
+
40
+ /** An asset-stem-tagged `file#key` string — `` `${Stem}#${string}` ``. */
41
+ export type DataRef<Stem extends string = string> = `${Stem}#${string}`;
42
+
43
+ /** Prefix/key-path grammar a ref must match, parameterized by target stem (mirrors `DATA_REF_PATTERN` in `data-check-core.ts`, minus the alternation — this one is anchored to ONE target). */
44
+ function refPattern(target: string): RegExp {
45
+ return new RegExp(`^${target}#[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)*$`);
46
+ }
47
+
48
+ /**
49
+ * A Zod schema for a data-asset FIELD that references another asset by
50
+ * `"<target>#<key>(.<field>)*"`. Use it in a `.schema.ts`:
51
+ *
52
+ * ```ts
53
+ * export const EnemyRowSchema = z.object({
54
+ * name: z.string(),
55
+ * drop: dataRef('items'), // -> "items#potion"
56
+ * });
57
+ * ```
58
+ *
59
+ * The emitted JSON Schema (`toDataJsonSchema`) carries both a precise
60
+ * `pattern` (VS Code validates the target-stem prefix for free) and
61
+ * `"x-vgai-ref": target` (the editor's Data panel picker keys off this).
62
+ * Detection by `data-check-core.ts`'s conventional-string calibration still
63
+ * applies at the VALUE level (a `dataRef` field's actual string still has to
64
+ * look like `target#key` to resolve) — this only makes the field's INTENT
65
+ * declared in the schema, closing the §9.4 "renamed target file silently
66
+ * un-checks its refs" hole for anything that adopts it (see
67
+ * `collectDeclaredRefFields`/`findMissingRefTargets` in `data-check-core.ts`).
68
+ */
69
+ export function dataRef<Stem extends string>(target: Stem): z.ZodType<DataRef<Stem>> {
70
+ return z
71
+ .string()
72
+ .regex(refPattern(target), {
73
+ message:
74
+ `must be a "${target}#<key>" reference (docs/DATA-TOOLS-DESIGN.md §2.2) — ` +
75
+ `expected the target asset stem "${target}", e.g. "${target}#some-key".`,
76
+ })
77
+ .meta({ 'x-vgai-ref': target }) as z.ZodType<DataRef<Stem>>;
78
+ }
79
+
80
+ /** First failing key-path segment, or `null` if the whole path resolves — same walk `data-check-core.ts`'s `firstUnresolvedSegment` does over parsed JSON, here over a live handle's value. */
81
+ function firstMissingSegment(root: unknown, keyPath: readonly string[]): string | null {
82
+ let node: unknown = root;
83
+ for (const segment of keyPath) {
84
+ if (node === null || typeof node !== 'object' || Array.isArray(node) || !(segment in node)) {
85
+ return segment;
86
+ }
87
+ node = (node as Record<string, unknown>)[segment];
88
+ }
89
+ return null;
90
+ }
91
+
92
+ /**
93
+ * Resolve a `"target#key(.field)*"` ref against the named target HANDLE,
94
+ * read live (`target.get()` at call time — HMR-correct, no caching across
95
+ * frames, same doctrine as any other data read).
96
+ *
97
+ * `ref`'s stem prefix should name `target`'s own asset — when `target` was
98
+ * built with a `sourcePath` (every `defineData` call populates it), a
99
+ * mismatch throws a teaching error instead of silently walking the wrong
100
+ * handle's data. Without a `sourcePath` (a hand-rolled `DataHandle`, or an
101
+ * older one built before this field existed) the mismatch check is skipped —
102
+ * resolution still proceeds against `target`, since the caller named it
103
+ * explicitly and that's the actual contract.
104
+ *
105
+ * Throws a teaching error naming the ref and the first key-path segment that
106
+ * doesn't resolve (a deleted row, a typo'd key) — never returns `undefined`
107
+ * silently, matching `parseDataJson`'s "errors teach" doctrine (§6.5).
108
+ */
109
+ export function getRef<T>(target: DataHandle<Record<string, T>>, ref: string): T {
110
+ const m = DATA_REF_PATTERN.exec(ref);
111
+ if (!m) {
112
+ throw new Error(
113
+ `getRef: "${ref}" is not a "file#key" reference (docs/DATA-TOOLS-DESIGN.md §2.2) — ` +
114
+ 'expected a string shaped like "some-file#some-key".',
115
+ );
116
+ }
117
+ const refStem = m[1] as string;
118
+ const keyPathStr = m[2] as string;
119
+ const targetStem = target.sourcePath
120
+ ?.split('\\')
121
+ .join('/')
122
+ .split('/')
123
+ .pop()
124
+ ?.replace(/\.data\.json$/, '');
125
+ if (targetStem !== undefined && targetStem !== refStem) {
126
+ throw new Error(
127
+ `getRef: ref "${ref}" names target asset "${refStem}", but the handle passed in is ` +
128
+ `"${targetStem}" (${target.sourcePath}). Pass the handle ` +
129
+ `"${refStem}#..." actually names — getRef(${refStem}, ...), not getRef(${targetStem}, ...).`,
130
+ );
131
+ }
132
+ const keyPath = keyPathStr.split('.');
133
+ const root = target.get();
134
+ const missing = firstMissingSegment(root, keyPath);
135
+ if (missing !== null) {
136
+ throw new Error(
137
+ `getRef: dangling ref "${ref}" — "${missing}" does not exist` +
138
+ (targetStem ? ` in ${targetStem}.data.json` : '') +
139
+ '. Fix the key or remove the ref (refs are "file#key" strings — docs/DATA-TOOLS-DESIGN.md §2.2).',
140
+ );
141
+ }
142
+ let node: unknown = root;
143
+ for (const segment of keyPath) node = (node as Record<string, unknown>)[segment];
144
+ return node as T;
145
+ }