@downdraft/engine 0.0.0 → 0.1.1

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 (908) hide show
  1. package/README.md +33 -0
  2. package/app/src/index.ts +10 -0
  3. package/app/src/renderer/bootstrap.ts +271 -0
  4. package/app/src/renderer/downdraft-base.css +93 -0
  5. package/app/src/renderer/feature-log.ts +200 -0
  6. package/app/src/renderer/game-module.ts +923 -0
  7. package/app/src/renderer/hooks.ts +88 -0
  8. package/app/src/renderer/hot-reload.ts +178 -0
  9. package/app/src/renderer/import-cache.ts +88 -0
  10. package/app/src/renderer/index.ts +206 -0
  11. package/app/src/renderer/mcp-harness.ts +144 -0
  12. package/app/src/renderer/save-store-factory.ts +239 -0
  13. package/app/src/renderer/sim-bridge.ts +183 -0
  14. package/app/src/renderer/standard-automation-tools.ts +771 -0
  15. package/app/src/shared/feature-log.ts +71 -0
  16. package/app/src/shared/gpu-info.ts +82 -0
  17. package/app/src/shared/import-cache-store.ts +142 -0
  18. package/app/src/shared/index.ts +6 -0
  19. package/app/src/shared/mcp-discovery.ts +47 -0
  20. package/app/src/shared/mcp-proxy.ts +82 -0
  21. package/app/src/shared/types.ts +324 -0
  22. package/asset-bake/src/bake-audio.ts +119 -0
  23. package/asset-bake/src/bake-gltf.ts +172 -0
  24. package/asset-bake/src/bake.ts +78 -0
  25. package/asset-bake/src/cache.ts +188 -0
  26. package/asset-bake/src/config.ts +186 -0
  27. package/asset-bake/src/index.ts +36 -0
  28. package/core/src/animation/animation-event.ts +41 -0
  29. package/core/src/animation/bone-mask.ts +122 -0
  30. package/core/src/animation/clip.ts +252 -0
  31. package/core/src/animation/index.ts +22 -0
  32. package/core/src/animation/mixamo.ts +113 -0
  33. package/core/src/animation/morph-target.ts +69 -0
  34. package/core/src/animation/player.ts +697 -0
  35. package/core/src/animation/retarget.ts +158 -0
  36. package/core/src/animation/skeleton-animator.ts +1399 -0
  37. package/core/src/animation/skeleton.ts +214 -0
  38. package/core/src/animation/state-machine.ts +280 -0
  39. package/core/src/assets/blob-store.ts +66 -0
  40. package/core/src/assets/cache.ts +186 -0
  41. package/core/src/assets/cubemap-converter.ts +155 -0
  42. package/core/src/assets/environment-manager.ts +121 -0
  43. package/core/src/assets/import-cache.ts +65 -0
  44. package/core/src/assets/import-settings.ts +72 -0
  45. package/core/src/assets/importer.ts +108 -0
  46. package/core/src/assets/index.ts +74 -0
  47. package/core/src/assets/irradiance-generator.ts +198 -0
  48. package/core/src/assets/loader-audio.ts +86 -0
  49. package/core/src/assets/loader-cubemap.ts +211 -0
  50. package/core/src/assets/loader-dds.ts +236 -0
  51. package/core/src/assets/loader-hdr.ts +474 -0
  52. package/core/src/assets/loader-mesh.ts +143 -0
  53. package/core/src/assets/loader-shader.ts +73 -0
  54. package/core/src/assets/loader-texture.ts +349 -0
  55. package/core/src/assets/lod.ts +198 -0
  56. package/core/src/assets/manager.ts +480 -0
  57. package/core/src/assets/manifest.ts +81 -0
  58. package/core/src/assets/material-bridge.ts +186 -0
  59. package/core/src/assets/model-importer.ts +72 -0
  60. package/core/src/assets/model-normalizer.ts +248 -0
  61. package/core/src/assets/model-to-gpu.ts +70 -0
  62. package/core/src/assets/model-to-mesh.ts +237 -0
  63. package/core/src/assets/prefilter-generator.ts +250 -0
  64. package/core/src/audio/engine.ts +177 -0
  65. package/core/src/audio/interface.ts +130 -0
  66. package/core/src/audio/listener.ts +32 -0
  67. package/core/src/audio/mixer.ts +141 -0
  68. package/core/src/audio/registry.ts +52 -0
  69. package/core/src/audio/sab.ts +87 -0
  70. package/core/src/audio/source.ts +89 -0
  71. package/core/src/change-detection/atomics.ts +1 -0
  72. package/core/src/change-detection/tracker.ts +47 -0
  73. package/core/src/debug-draw/lines.ts +64 -0
  74. package/core/src/debug-draw/points.ts +17 -0
  75. package/core/src/debug-draw/queue.ts +124 -0
  76. package/core/src/debug-draw/text.ts +25 -0
  77. package/core/src/ecs/archetype.ts +323 -0
  78. package/core/src/ecs/component.ts +188 -0
  79. package/core/src/ecs/entity.ts +25 -0
  80. package/core/src/ecs/events.ts +93 -0
  81. package/core/src/ecs/hierarchy.ts +124 -0
  82. package/core/src/ecs/hmr-swap-registry.ts +22 -0
  83. package/core/src/ecs/index.ts +25 -0
  84. package/core/src/ecs/query.ts +141 -0
  85. package/core/src/ecs/resource.ts +8 -0
  86. package/core/src/ecs/schedule.ts +181 -0
  87. package/core/src/ecs/system-params.ts +99 -0
  88. package/core/src/ecs/system.ts +42 -0
  89. package/core/src/ecs/world.ts +348 -0
  90. package/core/src/index.ts +352 -0
  91. package/core/src/input/context.ts +73 -0
  92. package/core/src/input/dom-handler.ts +380 -0
  93. package/core/src/input/local-player-manager.ts +218 -0
  94. package/core/src/input/mapping.ts +40 -0
  95. package/core/src/input/multi-sab-bridge.ts +276 -0
  96. package/core/src/input/multi-state.ts +54 -0
  97. package/core/src/input/sab-bridge.ts +71 -0
  98. package/core/src/input/state.ts +132 -0
  99. package/core/src/input/ui-router.ts +87 -0
  100. package/core/src/library/host.ts +317 -0
  101. package/core/src/library/index.ts +16 -0
  102. package/core/src/library/library.ts +292 -0
  103. package/core/src/material/compiler.ts +80 -0
  104. package/core/src/material/graph-bridge.ts +172 -0
  105. package/core/src/material/index.ts +9 -0
  106. package/core/src/material/library.ts +442 -0
  107. package/core/src/material/material.ts +156 -0
  108. package/core/src/material/variants.ts +61 -0
  109. package/core/src/math/mat4.ts +202 -0
  110. package/core/src/math/perlin-noise-2d.ts +77 -0
  111. package/core/src/math/perlin-noise-3d.ts +110 -0
  112. package/core/src/math/quat.ts +33 -0
  113. package/core/src/math/rng.ts +29 -0
  114. package/core/src/math/trig.ts +47 -0
  115. package/core/src/math/value-noise.ts +67 -0
  116. package/core/src/mesh/builder.ts +177 -0
  117. package/core/src/mesh/csg.ts +312 -0
  118. package/core/src/mesh/greased-line.ts +145 -0
  119. package/core/src/mesh/mesh.ts +17 -0
  120. package/core/src/mesh/parametric.ts +501 -0
  121. package/core/src/mesh/skinning.ts +67 -0
  122. package/core/src/mesh/vertex-layout.ts +91 -0
  123. package/core/src/module/cross-thread.ts +163 -0
  124. package/core/src/module/diagnostics.ts +123 -0
  125. package/core/src/module/host.ts +451 -0
  126. package/core/src/module/index.ts +22 -0
  127. package/core/src/module/module.ts +109 -0
  128. package/core/src/module/registry.ts +94 -0
  129. package/core/src/module/renderer-module.ts +247 -0
  130. package/core/src/module/ts-loader.ts +26 -0
  131. package/core/src/particles/compute-pass.ts +378 -0
  132. package/core/src/particles/emitter.ts +156 -0
  133. package/core/src/particles/index.ts +11 -0
  134. package/core/src/particles/particle-data.ts +47 -0
  135. package/core/src/particles/render-pass.ts +365 -0
  136. package/core/src/particles/simulator.ts +264 -0
  137. package/core/src/particles/system.ts +193 -0
  138. package/core/src/physics/body.ts +59 -0
  139. package/core/src/physics/ccd-heuristic.ts +55 -0
  140. package/core/src/physics/character.ts +282 -0
  141. package/core/src/physics/collider.ts +55 -0
  142. package/core/src/physics/collision-system.ts +91 -0
  143. package/core/src/physics/events.ts +133 -0
  144. package/core/src/physics/index.ts +34 -0
  145. package/core/src/physics/interface.ts +473 -0
  146. package/core/src/physics/interpolation-buffer.ts +192 -0
  147. package/core/src/physics/lifecycle.ts +87 -0
  148. package/core/src/physics/load-shedder.ts +164 -0
  149. package/core/src/physics/physics-accumulator.ts +101 -0
  150. package/core/src/physics/physics-system.ts +240 -0
  151. package/core/src/physics/ragdoll-presets.ts +272 -0
  152. package/core/src/physics/ragdoll-system.ts +220 -0
  153. package/core/src/physics/ragdoll.ts +182 -0
  154. package/core/src/physics/raycast.ts +143 -0
  155. package/core/src/physics/realm-manager.ts +499 -0
  156. package/core/src/physics/realm-worker-pool.ts +191 -0
  157. package/core/src/physics/realm-worker.ts +102 -0
  158. package/core/src/physics/realm.ts +189 -0
  159. package/core/src/physics/registry.ts +52 -0
  160. package/core/src/physics/safety.ts +247 -0
  161. package/core/src/physics/snapshot-manager.ts +141 -0
  162. package/core/src/physics/worker-protocol.ts +30 -0
  163. package/core/src/platform/bun-preload.ts +169 -0
  164. package/core/src/platform/css-stub.ts +4 -0
  165. package/core/src/platform/glob-polyfill.ts +124 -0
  166. package/core/src/platform/hidpi.ts +57 -0
  167. package/core/src/platform/render-surface.ts +77 -0
  168. package/core/src/platform/rpc.ts +98 -0
  169. package/core/src/platform/runtime.ts +132 -0
  170. package/core/src/plugin/context.ts +364 -0
  171. package/core/src/plugin/diagnostics.ts +61 -0
  172. package/core/src/plugin/discovery.ts +186 -0
  173. package/core/src/plugin/extension-loaders.ts +172 -0
  174. package/core/src/plugin/host.ts +659 -0
  175. package/core/src/plugin/index.ts +106 -0
  176. package/core/src/plugin/loader-asset.ts +124 -0
  177. package/core/src/plugin/loader-quickjs.ts +84 -0
  178. package/core/src/plugin/loader-wasm.ts +411 -0
  179. package/core/src/plugin/loader-worker.ts +261 -0
  180. package/core/src/plugin/manifest.ts +653 -0
  181. package/core/src/plugin/material-registry.ts +65 -0
  182. package/core/src/plugin/mcp-tools.ts +165 -0
  183. package/core/src/plugin/permissions.ts +175 -0
  184. package/core/src/plugin/quickjs-bridge.ts +294 -0
  185. package/core/src/plugin/registry.ts +107 -0
  186. package/core/src/plugin/sandbox-shim.ts +86 -0
  187. package/core/src/plugin/sandbox-worker.ts +215 -0
  188. package/core/src/plugin/wasm-abi.ts +152 -0
  189. package/core/src/plugin/wasm-worker.ts +229 -0
  190. package/core/src/plugin/workshop.ts +169 -0
  191. package/core/src/profiling/event-loop.ts +180 -0
  192. package/core/src/profiling/index.ts +69 -0
  193. package/core/src/profiling/iops/idb-patch.ts +242 -0
  194. package/core/src/profiling/iops/opfs-patch.ts +276 -0
  195. package/core/src/profiling/profiling-sab.ts +839 -0
  196. package/core/src/profiling/task-latency.ts +134 -0
  197. package/core/src/profiling/thread-metrics.ts +126 -0
  198. package/core/src/profiling/trace-event-writer.ts +205 -0
  199. package/core/src/profiling/warnings.ts +423 -0
  200. package/core/src/profiling/worker-prelude.ts +376 -0
  201. package/core/src/render/bind-group.ts +38 -0
  202. package/core/src/render/bindless/bindless-struct.ts +42 -0
  203. package/core/src/render/bindless/bindless.wgsl.ts +167 -0
  204. package/core/src/render/bindless/frame-bindings.ts +176 -0
  205. package/core/src/render/bindless/index.ts +10 -0
  206. package/core/src/render/bindless/material-manager.ts +257 -0
  207. package/core/src/render/bindless/texture-registry.ts +609 -0
  208. package/core/src/render/buffer.ts +82 -0
  209. package/core/src/render/camera-2d.ts +217 -0
  210. package/core/src/render/camera-controller.ts +440 -0
  211. package/core/src/render/camera.ts +409 -0
  212. package/core/src/render/canvas-resize-watcher.ts +46 -0
  213. package/core/src/render/compute-kernel.ts +172 -0
  214. package/core/src/render/constants.ts +2 -0
  215. package/core/src/render/device.ts +111 -0
  216. package/core/src/render/frame-graph.ts +768 -0
  217. package/core/src/render/frustum.ts +185 -0
  218. package/core/src/render/fullscreen-vs.ts +25 -0
  219. package/core/src/render/g-buffer.ts +186 -0
  220. package/core/src/render/game-renderer.ts +1452 -0
  221. package/core/src/render/gpu-driven/cull-pass.ts +394 -0
  222. package/core/src/render/gpu-driven/hzb.ts +215 -0
  223. package/core/src/render/gpu-driven/index.ts +7 -0
  224. package/core/src/render/gpu-driven/indirect-draw-pass.ts +324 -0
  225. package/core/src/render/gpu-driven/instance-buffer.ts +178 -0
  226. package/core/src/render/gpu-driven/mesh-table.ts +175 -0
  227. package/core/src/render/gpu-driven/passes/hzb-build-pass.ts +47 -0
  228. package/core/src/render/gpu-utils.ts +96 -0
  229. package/core/src/render/hdr.ts +88 -0
  230. package/core/src/render/hot-reload.ts +295 -0
  231. package/core/src/render/ibl-bind-group.ts +266 -0
  232. package/core/src/render/ibl.ts +180 -0
  233. package/core/src/render/index.ts +163 -0
  234. package/core/src/render/input-manager.ts +259 -0
  235. package/core/src/render/lighting/area-light.ts +196 -0
  236. package/core/src/render/lighting/cluster-grid.ts +288 -0
  237. package/core/src/render/lighting/cluster-types.ts +193 -0
  238. package/core/src/render/lighting/ies-parser.ts +162 -0
  239. package/core/src/render/lighting.ts +454 -0
  240. package/core/src/render/material-types/depth.wgsl +44 -0
  241. package/core/src/render/material-types/line.wgsl +50 -0
  242. package/core/src/render/material-types/matcap.wgsl +51 -0
  243. package/core/src/render/material-types/normal.wgsl +41 -0
  244. package/core/src/render/material-types/physical.wgsl +152 -0
  245. package/core/src/render/material-types/sprite.wgsl +46 -0
  246. package/core/src/render/material-types/sss.wgsl +79 -0
  247. package/core/src/render/material-types/toon.wgsl +79 -0
  248. package/core/src/render/passes/README.md +121 -0
  249. package/core/src/render/passes/atmosphere.ts +152 -0
  250. package/core/src/render/passes/cluster-lighting-pass.ts +476 -0
  251. package/core/src/render/passes/csm.ts +408 -0
  252. package/core/src/render/passes/cubemap-capture.ts +114 -0
  253. package/core/src/render/passes/debug-viz.ts +278 -0
  254. package/core/src/render/passes/debug.ts +538 -0
  255. package/core/src/render/passes/decal-mesh.ts +111 -0
  256. package/core/src/render/passes/decal-pass.ts +377 -0
  257. package/core/src/render/passes/deferred-lighting.ts +434 -0
  258. package/core/src/render/passes/depth-prepass.ts +163 -0
  259. package/core/src/render/passes/dome-360.ts +83 -0
  260. package/core/src/render/passes/fluid-render.ts +137 -0
  261. package/core/src/render/passes/gi-types.ts +118 -0
  262. package/core/src/render/passes/graph-compute.ts +300 -0
  263. package/core/src/render/passes/greased-line-pass.ts +232 -0
  264. package/core/src/render/passes/morph-target.ts +40 -0
  265. package/core/src/render/passes/opaque.ts +1028 -0
  266. package/core/src/render/passes/point-light-shadow.ts +266 -0
  267. package/core/src/render/passes/procedural-texture.ts +185 -0
  268. package/core/src/render/passes/reflection-probe.ts +140 -0
  269. package/core/src/render/passes/rsm-pass.ts +248 -0
  270. package/core/src/render/passes/sdf-text.ts +155 -0
  271. package/core/src/render/passes/shadow-map.ts +163 -0
  272. package/core/src/render/passes/shadow.ts +220 -0
  273. package/core/src/render/passes/skinning-vs.ts +121 -0
  274. package/core/src/render/passes/skinning.ts +326 -0
  275. package/core/src/render/passes/sky-dome.ts +404 -0
  276. package/core/src/render/passes/skybox.ts +162 -0
  277. package/core/src/render/passes/spot-light-shadow.ts +273 -0
  278. package/core/src/render/passes/terrain.ts +326 -0
  279. package/core/src/render/passes/transparent.ts +353 -0
  280. package/core/src/render/passes/underwater-fog.ts +185 -0
  281. package/core/src/render/passes/video-texture.ts +79 -0
  282. package/core/src/render/passes/volumetric-pass.ts +312 -0
  283. package/core/src/render/passes/volumetric-types.ts +171 -0
  284. package/core/src/render/passes/water.ts +753 -0
  285. package/core/src/render/pbr.ts +296 -0
  286. package/core/src/render/pipeline.ts +52 -0
  287. package/core/src/render/render-pass.ts +30 -0
  288. package/core/src/render/renderer-input-bus.ts +220 -0
  289. package/core/src/render/renderer-module-host.ts +623 -0
  290. package/core/src/render/resource-tracker.ts +67 -0
  291. package/core/src/render/sab-canvas-overlay.ts +122 -0
  292. package/core/src/render/shader-validator.ts +200 -0
  293. package/core/src/render/shaders/debug/debug-line.wgsl +27 -0
  294. package/core/src/render/shaders/debug/debug-point.wgsl +30 -0
  295. package/core/src/render/shaders/debug/debug-text.wgsl +42 -0
  296. package/core/src/render/shaders/debug-viz/aabb.wgsl +20 -0
  297. package/core/src/render/shaders/debug-viz/depth.wgsl +29 -0
  298. package/core/src/render/shaders/debug-viz/lod.wgsl +38 -0
  299. package/core/src/render/shaders/debug-viz/normals.wgsl +30 -0
  300. package/core/src/render/shaders/debug-viz/overdraw.wgsl +21 -0
  301. package/core/src/render/shaders/debug-viz/tangents.wgsl +29 -0
  302. package/core/src/render/shaders/debug-viz/wireframe.wgsl +33 -0
  303. package/core/src/render/shaders/shadow-chunks.ts +135 -0
  304. package/core/src/render/skybox.ts +146 -0
  305. package/core/src/render/splitscreen.ts +85 -0
  306. package/core/src/render/surface.ts +78 -0
  307. package/core/src/render/tonemap.ts +180 -0
  308. package/core/src/render/tracked-render-pass.ts +158 -0
  309. package/core/src/render/viewport.ts +109 -0
  310. package/core/src/render/wgsl-hmr.ts +70 -0
  311. package/core/src/sab/core-input-channel.ts +23 -0
  312. package/core/src/sab/define.ts +239 -0
  313. package/core/src/sab/errors.ts +76 -0
  314. package/core/src/sab/game-input.ts +343 -0
  315. package/core/src/sab/gamepad-devices.ts +259 -0
  316. package/core/src/sab/grid-buffer.ts +117 -0
  317. package/core/src/sab/input.ts +55 -0
  318. package/core/src/sab/layout.ts +219 -0
  319. package/core/src/sab/multi-input-channel.ts +50 -0
  320. package/core/src/sab/record-buffer.ts +155 -0
  321. package/core/src/sab/sab-polyfill.ts +56 -0
  322. package/core/src/sab/sim-channel.ts +453 -0
  323. package/core/src/sab/slot-buffer.ts +190 -0
  324. package/core/src/sab/types.ts +158 -0
  325. package/core/src/safety/bounds.ts +76 -0
  326. package/core/src/safety/json.ts +80 -0
  327. package/core/src/safety/path.ts +167 -0
  328. package/core/src/save/binary-format.ts +117 -0
  329. package/core/src/save/game-save-system.ts +161 -0
  330. package/core/src/save/grid-save-system.ts +158 -0
  331. package/core/src/save/migrate.ts +44 -0
  332. package/core/src/save/migration-registry.ts +94 -0
  333. package/core/src/save/persist-types.ts +208 -0
  334. package/core/src/save/schema.ts +46 -0
  335. package/core/src/save/serializer.ts +180 -0
  336. package/core/src/scene/builder.ts +65 -0
  337. package/core/src/scene/camera.ts +142 -0
  338. package/core/src/scene/checkpoint.ts +109 -0
  339. package/core/src/scene/game-loop.ts +198 -0
  340. package/core/src/scene/index.ts +24 -0
  341. package/core/src/scene/layer.ts +6 -0
  342. package/core/src/scene/prefab.ts +145 -0
  343. package/core/src/scene/scene-manager.ts +157 -0
  344. package/core/src/scene/scene.ts +192 -0
  345. package/core/src/scene/sky.ts +256 -0
  346. package/core/src/scene/spatial-grid.ts +176 -0
  347. package/core/src/scene/streaming.ts +304 -0
  348. package/core/src/scene/vegetation.ts +163 -0
  349. package/core/src/scene/world.ts +89 -0
  350. package/core/src/scripting/binding.ts +129 -0
  351. package/core/src/scripting/hot-reload.ts +144 -0
  352. package/core/src/scripting/script.ts +99 -0
  353. package/core/src/sim/hot-reload-pipeline.ts +49 -0
  354. package/core/src/sim/sim-state-helper.ts +47 -0
  355. package/core/src/sim/transient-state-registry.ts +77 -0
  356. package/core/src/sim/types.ts +113 -0
  357. package/core/src/sim/worker-loop.ts +222 -0
  358. package/core/src/stores/game-store.ts +158 -0
  359. package/core/src/stores/hot-reload-store.ts +44 -0
  360. package/core/src/telemetry/collector.ts +410 -0
  361. package/core/src/telemetry/gc-controller.ts +453 -0
  362. package/core/src/telemetry/gc-profiler.ts +126 -0
  363. package/core/src/telemetry/gc-tracker.ts +69 -0
  364. package/core/src/telemetry/gpu-profiler.ts +703 -0
  365. package/core/src/telemetry/gpu-resource-tracker.ts +285 -0
  366. package/core/src/telemetry/gpu-timer-pool.ts +234 -0
  367. package/core/src/telemetry/gpu-timer.ts +123 -0
  368. package/core/src/telemetry/gpu-timestamp-gate.ts +21 -0
  369. package/core/src/telemetry/reporter.ts +62 -0
  370. package/core/src/types/engine-types.ts +129 -0
  371. package/core/src/ui-font-scale.ts +112 -0
  372. package/core/src/util/broad-phase-grid.ts +82 -0
  373. package/core/src/util/feature-log.ts +220 -0
  374. package/core/src/util/index.ts +17 -0
  375. package/core/src/util/logger.ts +604 -0
  376. package/core/src/webgpu-destroy-augmentation.d.ts +25 -0
  377. package/core/src/worker/base-worker-host.ts +183 -0
  378. package/core/src/worker/buffer-sync.ts +550 -0
  379. package/core/src/worker/crash-recovery.ts +201 -0
  380. package/core/src/worker/entity-sim-worker-host.ts +190 -0
  381. package/core/src/worker/instrumented-worker-host.ts +171 -0
  382. package/core/src/worker/rpc.ts +253 -0
  383. package/core/src/worker/sim-worker-base.ts +913 -0
  384. package/core/src/worker/sim-worker-host.ts +358 -0
  385. package/core/src/worker/task-pool.ts +256 -0
  386. package/core/src/worker/task-worker.ts +83 -0
  387. package/libraries/asset-browser/src/index.ts +11 -0
  388. package/libraries/asset-browser/src/software-thumbnails.ts +949 -0
  389. package/libraries/audio-kira/README.md +17 -0
  390. package/libraries/audio-kira/native/Cargo.toml +14 -0
  391. package/libraries/audio-kira/native/src/engine.rs +27 -0
  392. package/libraries/audio-kira/native/src/lib.rs +185 -0
  393. package/libraries/audio-kira/native/src/mixer.rs +11 -0
  394. package/libraries/audio-kira/native/src/source.rs +80 -0
  395. package/libraries/audio-kira/src/backend.ts +469 -0
  396. package/libraries/audio-kira/src/index.ts +8 -0
  397. package/libraries/audio-kira/src/library.ts +82 -0
  398. package/libraries/blitz-ui/native/Cargo.toml +33 -0
  399. package/libraries/blitz-ui/native/assets/DejaVuSans.woff2 +0 -0
  400. package/libraries/blitz-ui/native/src/bridge.rs +100 -0
  401. package/libraries/blitz-ui/native/src/fonts.rs +20 -0
  402. package/libraries/blitz-ui/native/src/input.rs +80 -0
  403. package/libraries/blitz-ui/native/src/lib.rs +96 -0
  404. package/libraries/blitz-ui/native/src/shell.rs +301 -0
  405. package/libraries/blitz-ui/native-osr/Cargo.toml +24 -0
  406. package/libraries/blitz-ui/native-osr/src/events.rs +237 -0
  407. package/libraries/blitz-ui/native-osr/src/lib.rs +846 -0
  408. package/libraries/blitz-ui/native-osr/src/mutate.rs +385 -0
  409. package/libraries/blitz-ui/native-osr/src/resources.rs +45 -0
  410. package/libraries/blitz-ui/native-osr-spike.ts +70 -0
  411. package/libraries/blitz-ui/src/index.ts +15 -0
  412. package/libraries/blitz-ui/src/native-module.ts +221 -0
  413. package/libraries/blitz-ui/src/native-osr-ffi.ts +423 -0
  414. package/libraries/blitz-ui/src/router.ts +101 -0
  415. package/libraries/blitz-ui/src/shaders/ui-blit.wgsl.ts +35 -0
  416. package/libraries/blitz-ui/src/ui-blit-pass.ts +116 -0
  417. package/libraries/character/README.md +25 -0
  418. package/libraries/character/src/character-animator.ts +374 -0
  419. package/libraries/character/src/index.ts +24 -0
  420. package/libraries/character/src/loader.ts +375 -0
  421. package/libraries/character/src/locomotion.ts +124 -0
  422. package/libraries/character/src/preview.ts +287 -0
  423. package/libraries/devtools/README.md +51 -0
  424. package/libraries/devtools/native/Cargo.toml +12 -0
  425. package/libraries/devtools/native/src/lib.rs +1646 -0
  426. package/libraries/devtools/native/src/panels/console.rs +338 -0
  427. package/libraries/devtools/native/src/panels/dom_tree.rs +47 -0
  428. package/libraries/devtools/native/src/panels/generic.rs +317 -0
  429. package/libraries/devtools/native/src/panels/gpu.rs +107 -0
  430. package/libraries/devtools/native/src/panels/input.rs +88 -0
  431. package/libraries/devtools/native/src/panels/mod.rs +154 -0
  432. package/libraries/devtools/native/src/panels/perf_metrics.rs +91 -0
  433. package/libraries/devtools/native/src/panels/perf_recorder.rs +158 -0
  434. package/libraries/devtools/native/src/panels/scene.rs +72 -0
  435. package/libraries/devtools/native/src/state.rs +394 -0
  436. package/libraries/devtools/src/cdp-bridge.ts +349 -0
  437. package/libraries/devtools/src/collectors.ts +346 -0
  438. package/libraries/devtools/src/egui-ffi.ts +804 -0
  439. package/libraries/devtools/src/egui-renderer.ts +407 -0
  440. package/libraries/devtools/src/host.ts +363 -0
  441. package/libraries/devtools/src/index.ts +40 -0
  442. package/libraries/devtools/src/mirror.ts +794 -0
  443. package/libraries/devtools/src/native-providers.ts +744 -0
  444. package/libraries/devtools/src/verify.ts +167 -0
  445. package/libraries/devtools/src/web/browser.ts +102 -0
  446. package/libraries/devtools/src/web/host.ts +212 -0
  447. package/libraries/devtools/src/web/mirror.ts +430 -0
  448. package/libraries/devtools/src/web/server.ts +198 -0
  449. package/libraries/entities/README.md +17 -0
  450. package/libraries/entities/src/index.ts +4 -0
  451. package/libraries/entities/src/library.ts +64 -0
  452. package/libraries/entities/src/model-renderer.ts +1345 -0
  453. package/libraries/entities/src/shaders/model.wgsl +375 -0
  454. package/libraries/gamepad/src/feed-input.ts +83 -0
  455. package/libraries/gamepad/src/filters.ts +49 -0
  456. package/libraries/gamepad/src/glyphs.ts +93 -0
  457. package/libraries/gamepad/src/hub.ts +206 -0
  458. package/libraries/gamepad/src/index.ts +22 -0
  459. package/libraries/gamepad/src/library.ts +68 -0
  460. package/libraries/gamepad/src/source-sab.ts +70 -0
  461. package/libraries/gamepad/src/sysfs-enrich.ts +138 -0
  462. package/libraries/gaussian-splats/README.md +25 -0
  463. package/libraries/gaussian-splats/src/gpu-sort.ts +595 -0
  464. package/libraries/gaussian-splats/src/index.ts +31 -0
  465. package/libraries/gaussian-splats/src/library.ts +60 -0
  466. package/libraries/gaussian-splats/src/parser.ts +382 -0
  467. package/libraries/gaussian-splats/src/renderer.ts +427 -0
  468. package/libraries/gaussian-splats/src/sh-eval.ts +211 -0
  469. package/libraries/gaussian-splats/src/sorter.ts +110 -0
  470. package/libraries/gaussian-splats/src/tile-raster.ts +473 -0
  471. package/libraries/gpu-kernels/README.md +154 -0
  472. package/libraries/gpu-kernels/src/index.ts +11 -0
  473. package/libraries/gpu-kernels/src/kernel.ts +696 -0
  474. package/libraries/gpu-kernels/src/transpile.ts +958 -0
  475. package/libraries/html-ui-kit/src/behaviors.ts +250 -0
  476. package/libraries/html-ui-kit/src/components.ts +309 -0
  477. package/libraries/html-ui-kit/src/index.ts +30 -0
  478. package/libraries/html-ui-kit/src/nav/nav-controller.ts +238 -0
  479. package/libraries/html-ui-kit/src/nav/nav-input.ts +145 -0
  480. package/libraries/html-ui-kit/src/nav/osk.ts +153 -0
  481. package/libraries/html-ui-kit/src/nav/router.ts +167 -0
  482. package/libraries/html-ui-kit/src/nav/vcursor.ts +203 -0
  483. package/libraries/html-ui-kit/src/ten-foot.ts +182 -0
  484. package/libraries/html-ui-kit/src/theme.ts +238 -0
  485. package/libraries/lighting/README.md +20 -0
  486. package/libraries/lighting/src/index.ts +5 -0
  487. package/libraries/lighting/src/library.ts +66 -0
  488. package/libraries/lighting/src/light-system.ts +452 -0
  489. package/libraries/lighting/src/lighting-system.ts +68 -0
  490. package/libraries/lighting/src/shaders/light-debug.wgsl +30 -0
  491. package/libraries/marching-cubes/README.md +25 -0
  492. package/libraries/marching-cubes/src/chunked-field.ts +177 -0
  493. package/libraries/marching-cubes/src/deformation.ts +63 -0
  494. package/libraries/marching-cubes/src/generator.ts +407 -0
  495. package/libraries/marching-cubes/src/index.ts +32 -0
  496. package/libraries/marching-cubes/src/library.ts +80 -0
  497. package/libraries/marching-cubes/src/lod.ts +122 -0
  498. package/libraries/marching-cubes/src/marching-tetrahedra.ts +252 -0
  499. package/libraries/marching-cubes/src/sab.ts +45 -0
  500. package/libraries/marching-cubes/src/streaming-config.ts +48 -0
  501. package/libraries/marching-cubes/src/streaming-manager.ts +686 -0
  502. package/libraries/marching-cubes/src/tables.ts +323 -0
  503. package/libraries/marching-cubes/src/types.ts +18 -0
  504. package/libraries/models/README.md +25 -0
  505. package/libraries/models/src/bake-node-transforms.ts +171 -0
  506. package/libraries/models/src/codecs/basisu-codec.ts +180 -0
  507. package/libraries/models/src/codecs/draco-codec.ts +372 -0
  508. package/libraries/models/src/codecs/draco3dgltf.d.ts +40 -0
  509. package/libraries/models/src/codecs/index.ts +22 -0
  510. package/libraries/models/src/codecs/meshopt-codec.ts +91 -0
  511. package/libraries/models/src/codecs/registry.ts +221 -0
  512. package/libraries/models/src/dae.ts +753 -0
  513. package/libraries/models/src/default-part-selection.ts +56 -0
  514. package/libraries/models/src/dxf.ts +200 -0
  515. package/libraries/models/src/fbx/index.ts +457 -0
  516. package/libraries/models/src/fbx/interpreter/animation.ts +431 -0
  517. package/libraries/models/src/fbx/interpreter/blend-shapes.ts +323 -0
  518. package/libraries/models/src/fbx/interpreter/connections.ts +166 -0
  519. package/libraries/models/src/fbx/interpreter/diagnostics.ts +65 -0
  520. package/libraries/models/src/fbx/interpreter/geometry.ts +535 -0
  521. package/libraries/models/src/fbx/interpreter/global-settings.ts +92 -0
  522. package/libraries/models/src/fbx/interpreter/materials.ts +265 -0
  523. package/libraries/models/src/fbx/interpreter/nodes.ts +197 -0
  524. package/libraries/models/src/fbx/interpreter/skeleton.ts +476 -0
  525. package/libraries/models/src/fbx/parsers/binary-parser.ts +244 -0
  526. package/libraries/models/src/fbx/types.ts +119 -0
  527. package/libraries/models/src/gltf-extensions.ts +196 -0
  528. package/libraries/models/src/gltf.ts +935 -0
  529. package/libraries/models/src/index.ts +87 -0
  530. package/libraries/models/src/library.ts +75 -0
  531. package/libraries/models/src/loader.ts +265 -0
  532. package/libraries/models/src/material-adapter.ts +108 -0
  533. package/libraries/models/src/mini-xml.ts +174 -0
  534. package/libraries/models/src/normalize.ts +216 -0
  535. package/libraries/models/src/obj.ts +264 -0
  536. package/libraries/models/src/off.ts +95 -0
  537. package/libraries/models/src/ply.ts +348 -0
  538. package/libraries/models/src/pose-sampler.ts +219 -0
  539. package/libraries/models/src/sidecar/blender-extras.ts +37 -0
  540. package/libraries/models/src/sidecar/ddmeta.ts +114 -0
  541. package/libraries/models/src/sidecar/godot-import.ts +86 -0
  542. package/libraries/models/src/sidecar/resolver.ts +145 -0
  543. package/libraries/models/src/sidecar/types.ts +11 -0
  544. package/libraries/models/src/sidecar/unity-meta.ts +61 -0
  545. package/libraries/models/src/skeleton-synthesis.ts +132 -0
  546. package/libraries/models/src/stl.ts +149 -0
  547. package/libraries/models/src/threeds.ts +363 -0
  548. package/libraries/models/src/threemf.ts +201 -0
  549. package/libraries/models/src/types.ts +188 -0
  550. package/libraries/models/src/vtk.ts +218 -0
  551. package/libraries/models/test-fixtures/fbx/LICENSE-notice.txt +24 -0
  552. package/libraries/models/test-fixtures/fbx/README.md +46 -0
  553. package/libraries/models/test-fixtures/fbx/m01_cube_phong.fbx +0 -0
  554. package/libraries/models/test-fixtures/fbx/m02_geo_ngons.fbx +0 -0
  555. package/libraries/models/test-fixtures/fbx/m03_normals.fbx +0 -0
  556. package/libraries/models/test-fixtures/fbx/m04_material_properties.fbx +0 -0
  557. package/libraries/models/test-fixtures/fbx/m05_external_diffuse.png +0 -0
  558. package/libraries/models/test-fixtures/fbx/m05_textures.fbx +0 -0
  559. package/libraries/models/test-fixtures/fbx/m06_uv_transform.fbx +0 -0
  560. package/libraries/models/test-fixtures/fbx/m07_multimaterial.fbx +0 -0
  561. package/libraries/models/test-fixtures/fbx/m08_transforms.fbx +0 -0
  562. package/libraries/models/test-fixtures/fbx/m09_skinning.fbx +0 -0
  563. package/libraries/models/test-fixtures/fbx/m10_morph.fbx +0 -0
  564. package/libraries/models/test-fixtures/fbx/m11_node_anim.fbx +0 -0
  565. package/libraries/models/test-fixtures/fbx/m12_skeletal_anim.fbx +0 -0
  566. package/libraries/models/test-fixtures/fbx/m13_morph_anim.fbx +0 -0
  567. package/libraries/models/test-fixtures/fbx/m14_multiclip.fbx +0 -0
  568. package/libraries/models/test-fixtures/fbx/m15_camera_lights.fbx +0 -0
  569. package/libraries/models/test-fixtures/fbx/m16_axis_yup.fbx +0 -0
  570. package/libraries/models/test-fixtures/fbx/m16_axis_zup.fbx +0 -0
  571. package/libraries/models/test-fixtures/fbx/m16_units_254.fbx +0 -0
  572. package/libraries/navmesh/README.md +23 -0
  573. package/libraries/navmesh/src/crowd-system.ts +240 -0
  574. package/libraries/navmesh/src/debug-viz.ts +74 -0
  575. package/libraries/navmesh/src/index.ts +15 -0
  576. package/libraries/navmesh/src/library.ts +64 -0
  577. package/libraries/navmesh/src/navmesh-generator.ts +407 -0
  578. package/libraries/navmesh/src/navmesh.ts +159 -0
  579. package/libraries/navmesh/src/pathfinder.ts +252 -0
  580. package/libraries/navmesh/src/types.ts +63 -0
  581. package/libraries/networking/README.md +25 -0
  582. package/libraries/networking/src/authority.ts +121 -0
  583. package/libraries/networking/src/connection.ts +139 -0
  584. package/libraries/networking/src/discovery.ts +373 -0
  585. package/libraries/networking/src/enhanced-replication.ts +355 -0
  586. package/libraries/networking/src/epic-adapter.ts +129 -0
  587. package/libraries/networking/src/index.ts +45 -0
  588. package/libraries/networking/src/library.ts +69 -0
  589. package/libraries/networking/src/lobby.ts +108 -0
  590. package/libraries/networking/src/platform-adapter.ts +163 -0
  591. package/libraries/networking/src/rcs-adapter.ts +127 -0
  592. package/libraries/networking/src/remote-input.ts +188 -0
  593. package/libraries/networking/src/replication.ts +327 -0
  594. package/libraries/networking/src/rpc.ts +188 -0
  595. package/libraries/networking/src/session.ts +173 -0
  596. package/libraries/networking/src/transport.ts +201 -0
  597. package/libraries/networking/src/webrtc.ts +323 -0
  598. package/libraries/pathfinding-2d/README.md +15 -0
  599. package/libraries/pathfinding-2d/src/astar-grid.ts +312 -0
  600. package/libraries/pathfinding-2d/src/index.ts +11 -0
  601. package/libraries/persistence/README.md +25 -0
  602. package/libraries/persistence/src/autosave-manager.ts +112 -0
  603. package/libraries/persistence/src/binary-record-store.ts +244 -0
  604. package/libraries/persistence/src/browser.ts +51 -0
  605. package/libraries/persistence/src/file-save-store.ts +553 -0
  606. package/libraries/persistence/src/hash-utils.ts +59 -0
  607. package/libraries/persistence/src/index.ts +57 -0
  608. package/libraries/persistence/src/library.ts +74 -0
  609. package/libraries/persistence/src/mock-opfs.ts +141 -0
  610. package/libraries/persistence/src/node-fs-directory-handle.ts +161 -0
  611. package/libraries/persistence/src/opfs-save-store.ts +745 -0
  612. package/libraries/persistence/src/save-worker-proxy.ts +127 -0
  613. package/libraries/persistence/src/save-worker.ts +99 -0
  614. package/libraries/persistence/src/xxh3-ts.d.ts +10 -0
  615. package/libraries/physics-native/README.md +21 -0
  616. package/libraries/physics-native/native/Cargo.toml +11 -0
  617. package/libraries/physics-native/native/src/body.rs +403 -0
  618. package/libraries/physics-native/native/src/character.rs +226 -0
  619. package/libraries/physics-native/native/src/collider.rs +299 -0
  620. package/libraries/physics-native/native/src/joint.rs +81 -0
  621. package/libraries/physics-native/native/src/lib.rs +830 -0
  622. package/libraries/physics-native/native/src/query.rs +261 -0
  623. package/libraries/physics-native/native/src/realm.rs +33 -0
  624. package/libraries/physics-native/native/src/step.rs +54 -0
  625. package/libraries/physics-native/native/src/world.rs +148 -0
  626. package/libraries/physics-native/src/backend.ts +1046 -0
  627. package/libraries/physics-native/src/broadphase.ts +101 -0
  628. package/libraries/physics-native/src/ffi-spike-worker.ts +71 -0
  629. package/libraries/physics-native/src/index.ts +11 -0
  630. package/libraries/physics-native/src/library.ts +79 -0
  631. package/libraries/physics-native/src/narrowphase-shapes.ts +420 -0
  632. package/libraries/physics-native/src/narrowphase.ts +123 -0
  633. package/libraries/physics-native/src/solver.ts +141 -0
  634. package/libraries/physics-native/src/types.ts +76 -0
  635. package/libraries/physics-rapier/README.md +21 -0
  636. package/libraries/physics-rapier/bench/ffi-bench.ts +79 -0
  637. package/libraries/physics-rapier/bench/wasm-baseline.ts +90 -0
  638. package/libraries/physics-rapier/src/api.ts +452 -0
  639. package/libraries/physics-rapier/src/auto-backend.ts +59 -0
  640. package/libraries/physics-rapier/src/backend.ts +1207 -0
  641. package/libraries/physics-rapier/src/bulk-ops.ts +68 -0
  642. package/libraries/physics-rapier/src/ffi-backend.ts +21 -0
  643. package/libraries/physics-rapier/src/ffi-lib.ts +597 -0
  644. package/libraries/physics-rapier/src/index.ts +12 -0
  645. package/libraries/physics-rapier/src/library.ts +107 -0
  646. package/libraries/physics-rapier/src/rapier-backend.ts +1052 -0
  647. package/libraries/physics-rapier/src/realm-worker-script.ts +237 -0
  648. package/libraries/postfx/README.md +17 -0
  649. package/libraries/postfx/src/index.ts +19 -0
  650. package/libraries/postfx/src/library.ts +337 -0
  651. package/libraries/postfx/src/post-process-stack.ts +1752 -0
  652. package/libraries/postfx/src/shaders/post-process/afterimage.wgsl +14 -0
  653. package/libraries/postfx/src/shaders/post-process/ascii.wgsl +24 -0
  654. package/libraries/postfx/src/shaders/post-process/blit.wgsl +12 -0
  655. package/libraries/postfx/src/shaders/post-process/bloom-blur.wgsl +21 -0
  656. package/libraries/postfx/src/shaders/post-process/bloom-bright.wgsl +15 -0
  657. package/libraries/postfx/src/shaders/post-process/bloom-composite.wgsl +14 -0
  658. package/libraries/postfx/src/shaders/post-process/bloom-downsample.wgsl +60 -0
  659. package/libraries/postfx/src/shaders/post-process/bloom-soft.wgsl +46 -0
  660. package/libraries/postfx/src/shaders/post-process/bloom-upsample.wgsl +51 -0
  661. package/libraries/postfx/src/shaders/post-process/channel-mixer.wgsl +36 -0
  662. package/libraries/postfx/src/shaders/post-process/chromatic-aberration.wgsl +37 -0
  663. package/libraries/postfx/src/shaders/post-process/dithering.wgsl +64 -0
  664. package/libraries/postfx/src/shaders/post-process/dof.wgsl +131 -0
  665. package/libraries/postfx/src/shaders/post-process/edges.wgsl +45 -0
  666. package/libraries/postfx/src/shaders/post-process/fullscreen-vs.wgsl +15 -0
  667. package/libraries/postfx/src/shaders/post-process/fxaa.wgsl +102 -0
  668. package/libraries/postfx/src/shaders/post-process/gaussian-blur.wgsl +37 -0
  669. package/libraries/postfx/src/shaders/post-process/glow-blur.wgsl +33 -0
  670. package/libraries/postfx/src/shaders/post-process/glow-composite.wgsl +25 -0
  671. package/libraries/postfx/src/shaders/post-process/grain.wgsl +37 -0
  672. package/libraries/postfx/src/shaders/post-process/halftone.wgsl +80 -0
  673. package/libraries/postfx/src/shaders/post-process/highlight-blur.wgsl +33 -0
  674. package/libraries/postfx/src/shaders/post-process/highlight-composite.wgsl +32 -0
  675. package/libraries/postfx/src/shaders/post-process/lens-distortion.wgsl +43 -0
  676. package/libraries/postfx/src/shaders/post-process/lens-flare.wgsl +68 -0
  677. package/libraries/postfx/src/shaders/post-process/lut.wgsl +30 -0
  678. package/libraries/postfx/src/shaders/post-process/motion-blur.wgsl +55 -0
  679. package/libraries/postfx/src/shaders/post-process/occluder-chunk.wgsl +28 -0
  680. package/libraries/postfx/src/shaders/post-process/outline.wgsl +51 -0
  681. package/libraries/postfx/src/shaders/post-process/pixelation.wgsl +47 -0
  682. package/libraries/postfx/src/shaders/post-process/sharpen.wgsl +32 -0
  683. package/libraries/postfx/src/shaders/post-process/sobel.wgsl +26 -0
  684. package/libraries/postfx/src/shaders/post-process/split-tone.wgsl +36 -0
  685. package/libraries/postfx/src/shaders/post-process/ssao-blur.wgsl +38 -0
  686. package/libraries/postfx/src/shaders/post-process/ssao-composite.wgsl +25 -0
  687. package/libraries/postfx/src/shaders/post-process/ssao.wgsl +147 -0
  688. package/libraries/postfx/src/shaders/post-process/ssr.wgsl +155 -0
  689. package/libraries/postfx/src/shaders/post-process/taa.wgsl +98 -0
  690. package/libraries/postfx/src/shaders/post-process/tonemap.wgsl +40 -0
  691. package/libraries/postfx/src/shaders/post-process/watercolor.wgsl +82 -0
  692. package/libraries/postfx/src/shaders/post-process/white-balance.wgsl +41 -0
  693. package/libraries/recast/README.md +21 -0
  694. package/libraries/recast/src/backend.ts +150 -0
  695. package/libraries/recast/src/crowd-system.ts +352 -0
  696. package/libraries/recast/src/index.ts +12 -0
  697. package/libraries/recast/src/library.ts +91 -0
  698. package/libraries/recast/src/types.ts +86 -0
  699. package/libraries/sand/README.md +25 -0
  700. package/libraries/sand/src/cell.ts +43 -0
  701. package/libraries/sand/src/fields.ts +29 -0
  702. package/libraries/sand/src/fluid-grid.ts +261 -0
  703. package/libraries/sand/src/grid-dims.ts +74 -0
  704. package/libraries/sand/src/grid-sim-buffer.ts +271 -0
  705. package/libraries/sand/src/index.ts +81 -0
  706. package/libraries/sand/src/library.ts +92 -0
  707. package/libraries/sand/src/materials.ts +492 -0
  708. package/libraries/sand/src/palette.ts +93 -0
  709. package/libraries/sand/src/particles.ts +185 -0
  710. package/libraries/sand/src/render/sand-grid-pass.ts +430 -0
  711. package/libraries/sand/src/rng.ts +51 -0
  712. package/libraries/sand/src/rules/builtin-rules.ts +132 -0
  713. package/libraries/sand/src/rules/rule-compiler.ts +162 -0
  714. package/libraries/sand/src/rules/rule-engine.ts +231 -0
  715. package/libraries/sand/src/rules/rule-types.ts +87 -0
  716. package/libraries/sand/src/sand-step-pool.ts +484 -0
  717. package/libraries/sand/src/sand-step-worker.ts +97 -0
  718. package/libraries/sand/src/sand-world.ts +3227 -0
  719. package/libraries/stickman/README.md +25 -0
  720. package/libraries/stickman/src/index.ts +25 -0
  721. package/libraries/stickman/src/library.ts +61 -0
  722. package/libraries/stickman/src/proportions.ts +45 -0
  723. package/libraries/stickman/src/shader.ts +117 -0
  724. package/libraries/stickman/src/skeleton.ts +197 -0
  725. package/libraries/stickman/src/stickman-pass.ts +255 -0
  726. package/libraries/stickman/src/thick-line.ts +123 -0
  727. package/libraries/surface-nets/README.md +25 -0
  728. package/libraries/surface-nets/src/chunked-field.ts +14 -0
  729. package/libraries/surface-nets/src/deformation.ts +45 -0
  730. package/libraries/surface-nets/src/index.ts +36 -0
  731. package/libraries/surface-nets/src/library.ts +59 -0
  732. package/libraries/surface-nets/src/lod.ts +7 -0
  733. package/libraries/surface-nets/src/sab.ts +4 -0
  734. package/libraries/surface-nets/src/streaming-config.ts +5 -0
  735. package/libraries/surface-nets/src/streaming-manager.ts +15 -0
  736. package/libraries/surface-nets/src/surface-nets.ts +334 -0
  737. package/libraries/surface-nets/src/types.ts +23 -0
  738. package/libraries/water/README.md +25 -0
  739. package/libraries/water/src/buoyancy.ts +103 -0
  740. package/libraries/water/src/index.ts +43 -0
  741. package/libraries/water/src/library.ts +85 -0
  742. package/libraries/water/src/shore-damping.ts +93 -0
  743. package/libraries/water/src/water-buffer.ts +89 -0
  744. package/libraries/water/src/water-chunks.ts +13 -0
  745. package/libraries/water/src/water-physics.ts +376 -0
  746. package/libraries/water/src/water-renderer.ts +809 -0
  747. package/libraries/water/src/water-sab.ts +161 -0
  748. package/libraries/water/src/wave-sources.ts +84 -0
  749. package/libraries/weather/README.md +20 -0
  750. package/libraries/weather/src/index.ts +9 -0
  751. package/libraries/weather/src/library.ts +72 -0
  752. package/libraries/weather/src/types.ts +64 -0
  753. package/libraries/weather/src/weather-blend.ts +112 -0
  754. package/libraries/weather/src/weather-system.ts +271 -0
  755. package/libraries/weatherfx/README.md +24 -0
  756. package/libraries/weatherfx/src/cloud-provider.ts +31 -0
  757. package/libraries/weatherfx/src/cloud-system.ts +372 -0
  758. package/libraries/weatherfx/src/index.ts +9 -0
  759. package/libraries/weatherfx/src/library.ts +58 -0
  760. package/libraries/weatherfx/src/particle-system.ts +434 -0
  761. package/libraries/weatherfx/src/shaders/cloud.wgsl +111 -0
  762. package/libraries/weatherfx/src/shaders/particle-compute.wgsl +187 -0
  763. package/libraries/weatherfx/src/shaders/particle-render.wgsl +95 -0
  764. package/lint-plugin.mjs +41 -0
  765. package/mcp/src/client.ts +703 -0
  766. package/mcp/src/engine-context.ts +186 -0
  767. package/mcp/src/http-transport.ts +471 -0
  768. package/mcp/src/index.ts +13 -0
  769. package/mcp/src/prompts/add-entity.ts +42 -0
  770. package/mcp/src/prompts/create-scene.ts +44 -0
  771. package/mcp/src/prompts/debug-frame.ts +39 -0
  772. package/mcp/src/prompts/index.ts +12 -0
  773. package/mcp/src/resources/asset-list.ts +32 -0
  774. package/mcp/src/resources/checkpoint-list.ts +33 -0
  775. package/mcp/src/resources/entity-state.ts +55 -0
  776. package/mcp/src/resources/gpu-info.ts +103 -0
  777. package/mcp/src/resources/index.ts +57 -0
  778. package/mcp/src/resources/performance.ts +37 -0
  779. package/mcp/src/resources/scene-tree.ts +43 -0
  780. package/mcp/src/server.ts +375 -0
  781. package/mcp/src/tools/animation.ts +118 -0
  782. package/mcp/src/tools/asset.ts +161 -0
  783. package/mcp/src/tools/audio.ts +96 -0
  784. package/mcp/src/tools/build.ts +143 -0
  785. package/mcp/src/tools/camera.ts +167 -0
  786. package/mcp/src/tools/checkpoint.ts +100 -0
  787. package/mcp/src/tools/component.ts +199 -0
  788. package/mcp/src/tools/debug.ts +300 -0
  789. package/mcp/src/tools/entity.ts +361 -0
  790. package/mcp/src/tools/inspect.ts +210 -0
  791. package/mcp/src/tools/lighting.ts +263 -0
  792. package/mcp/src/tools/material.ts +243 -0
  793. package/mcp/src/tools/mesh.ts +239 -0
  794. package/mcp/src/tools/physics.ts +266 -0
  795. package/mcp/src/tools/scene.ts +153 -0
  796. package/mcp/src/tools/script.ts +122 -0
  797. package/mcp/src/types.ts +92 -0
  798. package/mcp/src/undo-redo.ts +77 -0
  799. package/modules/camera-controls/README.md +20 -0
  800. package/modules/camera-controls/src/index.ts +161 -0
  801. package/modules/controller-ui/src/index.ts +164 -0
  802. package/modules/devtools/README.md +25 -0
  803. package/modules/devtools/src/api.ts +461 -0
  804. package/modules/devtools/src/asset-utils.ts +105 -0
  805. package/modules/devtools/src/bind-debug-store.ts +48 -0
  806. package/modules/devtools/src/data-bridge.ts +286 -0
  807. package/modules/devtools/src/debug-overlay.ts +238 -0
  808. package/modules/devtools/src/debug-raycast.ts +328 -0
  809. package/modules/devtools/src/debug-store.ts +92 -0
  810. package/modules/devtools/src/debug-view-descriptors.ts +59 -0
  811. package/modules/devtools/src/doctor-panel.ts +182 -0
  812. package/modules/devtools/src/gizmo-module.ts +136 -0
  813. package/modules/devtools/src/graph-model.ts +509 -0
  814. package/modules/devtools/src/grid-renderer.ts +157 -0
  815. package/modules/devtools/src/height-ruler-renderer.ts +216 -0
  816. package/modules/devtools/src/index.ts +81 -0
  817. package/modules/devtools/src/init.ts +261 -0
  818. package/modules/devtools/src/label-overlay.ts +154 -0
  819. package/modules/devtools/src/material-stats-panel.ts +188 -0
  820. package/modules/devtools/src/profiling-bridge.ts +377 -0
  821. package/modules/devtools/src/profiling-hooks.ts +98 -0
  822. package/modules/devtools/src/renderer-adapter.ts +76 -0
  823. package/modules/devtools/src/scene-inspector.ts +637 -0
  824. package/modules/devtools/src/scene-store.ts +320 -0
  825. package/modules/devtools/src/scene-sync.ts +116 -0
  826. package/modules/devtools/src/shaders/transform-gizmo.wgsl +38 -0
  827. package/modules/devtools/src/sim-stats-panel.ts +272 -0
  828. package/modules/devtools/src/sim-stats-provider.ts +105 -0
  829. package/modules/devtools/src/skeleton-renderer.ts +351 -0
  830. package/modules/devtools/src/transform-gizmo.ts +928 -0
  831. package/modules/devtools/src/types.ts +290 -0
  832. package/modules/devtools/src/worker-expose.ts +67 -0
  833. package/modules/devtools/src/worker-sync.ts +137 -0
  834. package/modules/editor/src/commands/component.ts +156 -0
  835. package/modules/editor/src/commands/entity.ts +287 -0
  836. package/modules/editor/src/commands/hierarchy.ts +83 -0
  837. package/modules/editor/src/commands/index.ts +61 -0
  838. package/modules/editor/src/commands/prefab.ts +163 -0
  839. package/modules/editor/src/commands/registry.ts +331 -0
  840. package/modules/editor/src/commands/scene-io.ts +211 -0
  841. package/modules/editor/src/commands/selection.ts +73 -0
  842. package/modules/editor/src/commands/transform.ts +91 -0
  843. package/modules/editor/src/ddscene.ts +267 -0
  844. package/modules/editor/src/document.ts +123 -0
  845. package/modules/editor/src/editor-context.ts +172 -0
  846. package/modules/editor/src/index.ts +41 -0
  847. package/modules/editor/src/mcp.ts +103 -0
  848. package/modules/editor/src/module.ts +148 -0
  849. package/modules/editor/src/selection.ts +70 -0
  850. package/modules/editor/src/shell.ts +456 -0
  851. package/modules/editor/src/viewport.ts +199 -0
  852. package/modules/html-ui/src/composite.ts +135 -0
  853. package/modules/html-ui/src/create-html-ui.ts +188 -0
  854. package/modules/html-ui/src/doc-backend.ts +343 -0
  855. package/modules/html-ui/src/host.ts +646 -0
  856. package/modules/html-ui/src/index.ts +13 -0
  857. package/modules/html-ui/src/jsx-dev-runtime.ts +12 -0
  858. package/modules/html-ui/src/jsx-runtime.ts +126 -0
  859. package/modules/html-ui/src/protocol.ts +88 -0
  860. package/modules/html-ui/src/ui-worker.ts +16 -0
  861. package/modules/mcp/README.md +18 -0
  862. package/modules/mcp/src/index.ts +27 -0
  863. package/modules/movement-2d/README.md +19 -0
  864. package/modules/movement-2d/src/grid-character.ts +455 -0
  865. package/modules/movement-2d/src/index.ts +45 -0
  866. package/modules/movement-3d/README.md +21 -0
  867. package/modules/movement-3d/src/character-motor.ts +230 -0
  868. package/modules/movement-3d/src/index.ts +46 -0
  869. package/modules/native-osr/src/index.ts +22 -0
  870. package/modules/native-osr/src/input-router.ts +401 -0
  871. package/modules/native-osr/src/native-osr-manager.ts +247 -0
  872. package/modules/native-osr/src/native-texture-source.ts +86 -0
  873. package/modules/native-osr/src/types.ts +112 -0
  874. package/modules/native-osr/src/world-space-ui-pass.ts +351 -0
  875. package/modules/sailing/README.md +18 -0
  876. package/modules/sailing/src/index.ts +51 -0
  877. package/modules/terrain/README.md +18 -0
  878. package/modules/terrain/src/index.ts +78 -0
  879. package/modules/vitals/README.md +17 -0
  880. package/modules/vitals/src/index.ts +43 -0
  881. package/modules/vitals/src/vitals.ts +265 -0
  882. package/modules/xr/README.md +25 -0
  883. package/modules/xr/src/camera-rig.ts +146 -0
  884. package/modules/xr/src/debug.ts +59 -0
  885. package/modules/xr/src/frame-loop.ts +197 -0
  886. package/modules/xr/src/index.ts +16 -0
  887. package/modules/xr/src/input.ts +208 -0
  888. package/modules/xr/src/layer.ts +140 -0
  889. package/modules/xr/src/session.ts +156 -0
  890. package/modules/xr/src/sim-module.ts +23 -0
  891. package/modules/xr/src/types.ts +32 -0
  892. package/modules/xr/src/webxr.d.ts +182 -0
  893. package/modules/xr/src/xr-module.ts +179 -0
  894. package/package.json +232 -3
  895. package/shader-graph/src/chunks.ts +349 -0
  896. package/shader-graph/src/compiler.ts +732 -0
  897. package/shader-graph/src/compute-compiler.ts +453 -0
  898. package/shader-graph/src/compute-graph.ts +112 -0
  899. package/shader-graph/src/compute-profiles.ts +54 -0
  900. package/shader-graph/src/graph.ts +52 -0
  901. package/shader-graph/src/index.ts +53 -0
  902. package/shader-graph/src/profiles.ts +407 -0
  903. package/shader-graph/src/validator.ts +48 -0
  904. package/shader-graph/src/wgsl-binding-validator.ts +143 -0
  905. package/shader-graph/src/wgsl-struct-validator.ts +245 -0
  906. package/shader-graph/src/wgsl-struct.ts +397 -0
  907. package/test/src/index.ts +7 -0
  908. package/test/src/vision-test.ts +369 -0
@@ -0,0 +1,703 @@
1
+ // ============================================================================
2
+ // GameClient — client for a running game's in-process MCP automation endpoint.
3
+ //
4
+ // A running game (draft dev / draft test / launchGame) exposes a JSON-RPC
5
+ // over HTTP endpoint on 127.0.0.1 (McpHttpTransport) and advertises its port
6
+ // via ~/.downdraft/port/<pid>. This module is the single implementation of
7
+ // the client side of that wire — previously triplicated across
8
+ // scripts/mcp-call.mjs, .devin/mcp-stdio-bridge.mjs, and tests/e2e/harness.ts.
9
+ //
10
+ // import { GameClient, launchGame } from "@downdraft/engine/mcp/client";
11
+ //
12
+ // const client = await GameClient.connect(); // PID-file discovery
13
+ // const tools = await client.listTools();
14
+ // const state = await client.callJson("get_world_state");
15
+ // await client.screenshot("shot.png");
16
+ //
17
+ // // Or launch + connect + kill in one:
18
+ // const game = await launchGame({ game: "to-the-ocean" });
19
+ // await game.client.callText("get_player_state");
20
+ // await game.kill();
21
+ //
22
+ // Node- and Bun-compatible: only node: APIs + fetch, no Bun.* globals.
23
+ // ============================================================================
24
+
25
+ import { spawn, type ChildProcess } from "node:child_process";
26
+ import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
27
+ import { createServer } from "node:net";
28
+ import { homedir } from "node:os";
29
+ import { basename, dirname, join, resolve } from "node:path";
30
+ import type { MCPToolDef, MCPToolResult } from "./types";
31
+
32
+ export type { MCPToolDef, MCPToolResult } from "./types";
33
+
34
+ const DEFAULT_TIMEOUT_MS = 120_000;
35
+
36
+ export class McpClientError extends Error {}
37
+
38
+ // ---------------------------------------------------------------------------
39
+ // Instance discovery — ~/.downdraft/port/<pid> PID files
40
+ // ---------------------------------------------------------------------------
41
+
42
+ /** Directory holding one PID file per running game instance. Each file is
43
+ * named `<pid>` and contains the bound MCP HTTP port; a sibling
44
+ * `<pid>.token` holds the bearer token when the instance requires auth. */
45
+ export function mcpPortDir(): string {
46
+ return join(homedir(), ".downdraft", "port");
47
+ }
48
+
49
+ export interface GameInstance {
50
+ pid: number;
51
+ port: number;
52
+ /** Bearer token from `<pid>.token`, when the instance wrote one. */
53
+ token?: string;
54
+ /** PID-file mtime — newest instance wins when no selector is given. */
55
+ mtimeMs: number;
56
+ /** The instance's appId when it can be recovered (Linux /proc only). */
57
+ appId?: string;
58
+ }
59
+
60
+ export interface InstanceSelector {
61
+ /** Match instances whose --user-data-dir basename equals this appId
62
+ * (Linux-only; ignored elsewhere). */
63
+ appId?: string;
64
+ /** Match exactly this PID. */
65
+ pid?: number;
66
+ }
67
+
68
+ function isAlive(pid: number): boolean {
69
+ try {
70
+ process.kill(pid, 0);
71
+ return true;
72
+ } catch (e) {
73
+ return (e as NodeJS.ErrnoException).code === "EPERM";
74
+ }
75
+ }
76
+
77
+ /** Best-effort appId recovery: read /proc/<pid>/cmdline and return the
78
+ * basename of --user-data-dir=<path>. Returns undefined on non-Linux or
79
+ * when the arg is absent. */
80
+ function readAppId(pid: number): string | undefined {
81
+ if (process.platform !== "linux") return undefined;
82
+ try {
83
+ const raw = readFileSync(`/proc/${pid}/cmdline`, "utf8");
84
+ const m = /--user-data-dir=(\S+)/.exec(raw.replace(/\0+$/g, "").replace(/\0/g, " "));
85
+ return m ? basename(m[1]) : undefined;
86
+ } catch {
87
+ return undefined;
88
+ }
89
+ }
90
+
91
+ /** List all live game instances, newest-first. Dead PID files are pruned
92
+ * as a side effect. */
93
+ export function listGameInstances(sel: InstanceSelector = {}): GameInstance[] {
94
+ let entries: string[];
95
+ try {
96
+ entries = readdirSync(mcpPortDir());
97
+ } catch {
98
+ return [];
99
+ }
100
+ const out: GameInstance[] = [];
101
+ for (let _i = 0, _it = entries, _n = _it.length; _i < _n; _i++) { const name = _it[_i];
102
+ if (!/^\d+$/.test(name)) continue;
103
+ const pid = Number(name);
104
+ if (!isAlive(pid)) {
105
+ try { unlinkSync(join(mcpPortDir(), name)); } catch { /* gone */ }
106
+ continue;
107
+ }
108
+ if (sel.pid !== undefined && pid !== sel.pid) continue;
109
+ const appId = readAppId(pid);
110
+ if (sel.appId !== undefined && appId !== undefined && appId !== sel.appId) continue;
111
+ if (sel.appId !== undefined && appId === undefined && process.platform === "linux") continue;
112
+
113
+ let port: number;
114
+ try {
115
+ const raw = readFileSync(join(mcpPortDir(), name), "utf8").trim();
116
+ if (!/^\d+$/.test(raw)) continue;
117
+ port = Number(raw);
118
+ } catch {
119
+ continue;
120
+ }
121
+ let token: string | undefined;
122
+ try {
123
+ token = readFileSync(join(mcpPortDir(), `${name}.token`), "utf8").trim() || undefined;
124
+ } catch { /* no token file — auth not required */ }
125
+ let mtimeMs = 0;
126
+ try {
127
+ mtimeMs = statSync(join(mcpPortDir(), name)).mtimeMs;
128
+ } catch { /* treat as oldest */ }
129
+ out.push({ pid, port, token, mtimeMs, appId });
130
+ }
131
+ out.sort((a, b) => b.mtimeMs - a.mtimeMs);
132
+ return out;
133
+ }
134
+
135
+ /** Pick the newest live instance matching the selector, or null. */
136
+ export function discoverGameInstance(sel: InstanceSelector = {}): GameInstance | null {
137
+ return listGameInstances(sel)[0] ?? null;
138
+ }
139
+
140
+ // ---------------------------------------------------------------------------
141
+ // GameClient
142
+ // ---------------------------------------------------------------------------
143
+
144
+ export interface GameClientOptions {
145
+ /** Narrow discovery to a specific game's appId. */
146
+ appId?: string;
147
+ /** Connect to a specific PID. */
148
+ pid?: number;
149
+ /** Explicit endpoint URL (e.g. http://localhost:9976/mcp) — skips
150
+ * PID-file discovery entirely. */
151
+ url?: string;
152
+ /** Bearer token; auto-read from <pid>.token on discovery. */
153
+ token?: string;
154
+ /** Per-request timeout in ms (default 120s). */
155
+ timeoutMs?: number;
156
+ }
157
+
158
+ export interface CallOptions {
159
+ timeoutMs?: number;
160
+ retries?: number;
161
+ backoffMs?: number;
162
+ }
163
+
164
+ interface JsonRpcResponse {
165
+ result?: unknown;
166
+ error?: { code: number; message: string };
167
+ }
168
+
169
+ /** Minimal process handle for liveness checks during waitForReady —
170
+ * satisfied by node:child_process ChildProcess and Bun's Subprocess. */
171
+ export interface ProcessProbe {
172
+ exitCode: number | null;
173
+ killed?: boolean;
174
+ }
175
+
176
+ function sleep(ms: number): Promise<void> {
177
+ return new Promise((r) => setTimeout(r, ms));
178
+ }
179
+
180
+ export class GameClient {
181
+ readonly url: string;
182
+ readonly pid: number | undefined;
183
+ private token: string | undefined;
184
+ private sessionId: string | null = null;
185
+ private reqId = 0;
186
+ private defaultTimeout: number;
187
+
188
+ private constructor(url: string, token: string | undefined, pid: number | undefined, timeoutMs: number) {
189
+ this.url = url;
190
+ this.token = token;
191
+ this.pid = pid;
192
+ this.defaultTimeout = timeoutMs;
193
+ }
194
+
195
+ /**
196
+ * Connect to a running game instance. With no selector, attaches to the
197
+ * newest live instance in ~/.downdraft/port/. Performs the `initialize`
198
+ * handshake before returning.
199
+ */
200
+ static async connect(opts: GameClientOptions = {}): Promise<GameClient> {
201
+ // Env fallbacks: DOWNDRAFT_MCP_URL/MCP_HTTP_URL for explicit targets,
202
+ // MCP_APP_ID/MCP_PID for discovery selectors — the same selectors the
203
+ // old stdio bridge honored, so existing configs keep working.
204
+ const envPid = Number(process.env.MCP_PID);
205
+ const appId = opts.appId ?? process.env.MCP_APP_ID;
206
+ let pid = opts.pid ?? (Number.isFinite(envPid) && envPid > 0 ? envPid : undefined);
207
+ let url = opts.url ?? process.env.DOWNDRAFT_MCP_URL ?? process.env.MCP_HTTP_URL;
208
+ let token = opts.token ?? process.env.DOWNDRAFT_MCP_TOKEN ?? process.env.MCP_TOKEN;
209
+ if (!url) {
210
+ const inst = discoverGameInstance({ appId, pid });
211
+ if (!inst) {
212
+ const filter = appId
213
+ ? ` with appId "${appId}"`
214
+ : pid !== undefined
215
+ ? ` with PID ${pid}`
216
+ : "";
217
+ throw new McpClientError(
218
+ `No running downdraft game instance found${filter} in ${mcpPortDir()}. ` +
219
+ `Start a game first (e.g. \`draft dev\`), or pass url / set DOWNDRAFT_MCP_URL.`,
220
+ );
221
+ }
222
+ url = `http://localhost:${inst.port}/mcp`;
223
+ token ??= inst.token;
224
+ pid = inst.pid;
225
+ }
226
+ const client = new GameClient(url, token, pid, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
227
+ await client.rpc("initialize", {
228
+ protocolVersion: "2024-11-05",
229
+ capabilities: {},
230
+ clientInfo: { name: "downdraft-game-client", version: "0.1.0" },
231
+ }, 10_000);
232
+ return client;
233
+ }
234
+
235
+ private headers(): Record<string, string> {
236
+ const h: Record<string, string> = {
237
+ "Content-Type": "application/json",
238
+ // Deliberately no text/event-stream — the transport then answers
239
+ // with plain JSON instead of SSE framing.
240
+ "Accept": "application/json",
241
+ };
242
+ if (this.sessionId) h["Mcp-Session-Id"] = this.sessionId;
243
+ if (this.token) h["X-Downdraft-Token"] = this.token;
244
+ return h;
245
+ }
246
+
247
+ private async rpc(method: string, params: Record<string, unknown> = {}, timeoutMs?: number): Promise<unknown> {
248
+ const res = await fetch(this.url, {
249
+ method: "POST",
250
+ headers: this.headers(),
251
+ body: JSON.stringify({ jsonrpc: "2.0", id: ++this.reqId, method, params }),
252
+ signal: AbortSignal.timeout(timeoutMs ?? this.defaultTimeout),
253
+ });
254
+ const sid = res.headers.get("Mcp-Session-Id");
255
+ if (sid) this.sessionId = sid;
256
+ const text = await res.text();
257
+ if (!res.ok) throw new McpClientError(`MCP HTTP ${res.status}: ${text.slice(0, 500)}`);
258
+ let json: JsonRpcResponse;
259
+ try {
260
+ json = JSON.parse(text);
261
+ } catch {
262
+ throw new McpClientError(`Non-JSON response: ${text.slice(0, 500)}`);
263
+ }
264
+ if (json.error) throw new McpClientError(`MCP error ${json.error.code}: ${json.error.message}`);
265
+ // Proxy mode wraps handler errors in result.error — surface those too.
266
+ const result = json.result as { error?: { code: number; message: string } } | undefined;
267
+ if (result?.error) throw new McpClientError(`MCP error ${result.error.code}: ${result.error.message}`);
268
+ return json.result;
269
+ }
270
+
271
+ /** Raw JSON-RPC method call — for methods without a typed helper
272
+ * (resources/read, prompts/get) and the stdio bridge's forwarding. */
273
+ async request(method: string, params: Record<string, unknown> = {}, timeoutMs?: number): Promise<unknown> {
274
+ return this.rpc(method, params, timeoutMs);
275
+ }
276
+
277
+ /** tools/list — the tool defs the game registered. */
278
+ async listTools(): Promise<MCPToolDef[]> {
279
+ const result = (await this.rpc("tools/list", {}, 10_000)) as { tools?: MCPToolDef[] };
280
+ return result.tools ?? [];
281
+ }
282
+
283
+ /** tools/call — returns the raw {content, isError} envelope. */
284
+ async call(name: string, args: Record<string, unknown> = {}, opts: CallOptions = {}): Promise<MCPToolResult> {
285
+ return (await this.rpc("tools/call", { name, arguments: args }, opts.timeoutMs)) as MCPToolResult;
286
+ }
287
+
288
+ private textOrThrow(result: MCPToolResult): string {
289
+ const text = (result.content ?? [])
290
+ .filter((c): c is { type: "text"; text: string } => c.type === "text")
291
+ .map((c) => c.text)
292
+ .join("\n");
293
+ if (result.isError) throw new McpClientError(`MCP tool returned an error: ${text}`);
294
+ return text;
295
+ }
296
+
297
+ /** tools/call → concatenated text content; throws when isError. */
298
+ async callText(name: string, args: Record<string, unknown> = {}, opts: CallOptions = {}): Promise<string> {
299
+ return this.textOrThrow(await this.call(name, args, opts));
300
+ }
301
+
302
+ /** tools/call → JSON.parse of the text content; throws on isError or
303
+ * non-JSON output. */
304
+ async callJson<T = unknown>(name: string, args: Record<string, unknown> = {}, opts: CallOptions = {}): Promise<T> {
305
+ const text = this.textOrThrow(await this.call(name, args, opts));
306
+ try {
307
+ return JSON.parse(text) as T;
308
+ } catch (e) {
309
+ throw new McpClientError(`MCP tool returned non-JSON text: ${(e as Error).message} | ${text.slice(0, 200)}`);
310
+ }
311
+ }
312
+
313
+ /** Retry on transport/connection errors only — tool-level isError
314
+ * results are thrown immediately. */
315
+ async callWithRetry(name: string, args: Record<string, unknown> = {}, opts: CallOptions = {}): Promise<MCPToolResult> {
316
+ const maxRetries = opts.retries ?? 3;
317
+ const backoffMs = opts.backoffMs ?? 500;
318
+ let lastError: Error | null = null;
319
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
320
+ try {
321
+ const result = await this.call(name, args, opts);
322
+ if (result.isError) {
323
+ throw new McpClientError(`MCP tool returned an error: ${result.content?.[0] && "text" in result.content[0] ? result.content[0].text : ""}`);
324
+ }
325
+ return result;
326
+ } catch (e) {
327
+ lastError = e as Error;
328
+ const msg = lastError.message;
329
+ const isTransportError =
330
+ msg.includes("MCP HTTP") ||
331
+ msg.includes("fetch failed") ||
332
+ msg.includes("aborted") ||
333
+ msg.includes("ECONNREFUSED") ||
334
+ msg.includes("MCP error");
335
+ if (!isTransportError || attempt === maxRetries) throw lastError;
336
+ await sleep(backoffMs * (attempt + 1));
337
+ }
338
+ }
339
+ throw lastError ?? new McpClientError("callWithRetry exhausted retries");
340
+ }
341
+
342
+ /** capture_screenshot → write the image block to `path` as PNG. Returns
343
+ * the dimensions from the tool's text metadata. */
344
+ async screenshot(path: string, args: Record<string, unknown> = {}): Promise<{ width: number; height: number }> {
345
+ const result = await this.call("capture_screenshot", { fullPage: true, ...args });
346
+ const text = this.textOrThrow(result);
347
+ let meta: { width?: number; height?: number } = {};
348
+ try { meta = JSON.parse(text); } catch { /* older tools may not emit meta */ }
349
+ const image = result.content.find((c) => c.type === "image") as
350
+ | { type: "image"; data: string; mimeType: string }
351
+ | undefined;
352
+ if (!image?.data) throw new McpClientError("capture_screenshot returned no image data");
353
+ mkdirSync(dirname(resolve(path)), { recursive: true });
354
+ writeFileSync(path, Buffer.from(image.data, "base64"));
355
+ return { width: meta.width ?? 0, height: meta.height ?? 0 };
356
+ }
357
+
358
+ /**
359
+ * Wait until the instance is serving MCP and has registered tools:
360
+ * poll GET /mcp/health, then initialize + tools/list until non-empty.
361
+ * `proc` (optional) enables fail-fast when a launched game dies early.
362
+ * A final capture_screenshot probe warns (non-fatal) when WebGPU isn't
363
+ * producing frames yet — mirrors the e2e harness's readiness check.
364
+ */
365
+ async waitForReady(timeoutMs = 90_000, opts: { proc?: ProcessProbe } = {}): Promise<void> {
366
+ const healthUrl = this.url.replace(/\/mcp\/?$/, "/mcp/health");
367
+ const deadline = Date.now() + timeoutMs;
368
+ let lastErr = "";
369
+ const alive = () => !opts.proc || (opts.proc.exitCode === null && !opts.proc.killed);
370
+ const failIfDead = (stage: string) => {
371
+ if (!alive()) throw new McpClientError(`Game process exited before ${stage} became ready`);
372
+ };
373
+
374
+ while (Date.now() < deadline) {
375
+ failIfDead("MCP health endpoint");
376
+ try {
377
+ const res = await fetch(healthUrl, {
378
+ headers: this.token ? { "X-Downdraft-Token": this.token } : {},
379
+ signal: AbortSignal.timeout(5_000),
380
+ });
381
+ if (res.ok) break;
382
+ lastErr = `HTTP ${res.status}`;
383
+ } catch (e) {
384
+ lastErr = (e as Error).message;
385
+ }
386
+ await sleep(250);
387
+ }
388
+ if (Date.now() >= deadline) {
389
+ throw new McpClientError(`MCP health endpoint did not become ready at ${healthUrl}: ${lastErr}`);
390
+ }
391
+
392
+ while (Date.now() < deadline) {
393
+ failIfDead("MCP tools");
394
+ try {
395
+ const tools = await this.listTools();
396
+ if (tools.length > 0) break;
397
+ lastErr = "tools list empty";
398
+ } catch (e) {
399
+ lastErr = (e as Error).message;
400
+ }
401
+ await sleep(1_000);
402
+ }
403
+ if (Date.now() >= deadline) {
404
+ throw new McpClientError(`MCP tools did not become available at ${this.url}: ${lastErr}`);
405
+ }
406
+
407
+ // Best-effort readiness probe: a valid screenshot implies WebGPU is
408
+ // initialized. Warn but don't fail — some games can't screenshot in
409
+ // their initial state.
410
+ const probeDeadline = Math.min(Date.now() + 30_000, deadline + 30_000);
411
+ let lastProbeErr = "";
412
+ while (Date.now() < probeDeadline) {
413
+ failIfDead("readiness probe");
414
+ try {
415
+ const result = await this.call("capture_screenshot", { fullPage: false }, { timeoutMs: 10_000 });
416
+ if (!result.isError && result.content?.some((c) => c.type === "image" && c.data)) return;
417
+ lastProbeErr = result.isError
418
+ ? `capture_screenshot error: ${result.content?.[0] && "text" in result.content[0] ? result.content[0].text : ""}`
419
+ : "capture_screenshot returned no image data";
420
+ } catch (e) {
421
+ lastProbeErr = (e as Error).message;
422
+ }
423
+ await sleep(1_000);
424
+ }
425
+ process.stderr.write(`[GameClient] readiness probe failed (non-fatal): ${lastProbeErr}\n`);
426
+ }
427
+
428
+ // ── Harness-compat aliases (the old tests/e2e McpClient interface) ──
429
+ callTool(name: string, args: Record<string, unknown> = {}, opts: CallOptions = {}): Promise<MCPToolResult> {
430
+ return this.call(name, args, opts);
431
+ }
432
+ callToolWithRetry(name: string, args: Record<string, unknown> = {}, opts: CallOptions = {}): Promise<MCPToolResult> {
433
+ return this.callWithRetry(name, args, opts);
434
+ }
435
+ close(): void {
436
+ // Stateless HTTP — nothing to tear down.
437
+ }
438
+ }
439
+
440
+ // ---------------------------------------------------------------------------
441
+ // launchGame — spawn a game, wait for MCP, connect
442
+ // ---------------------------------------------------------------------------
443
+
444
+ export interface LaunchGameOptions {
445
+ /** Game name resolved to games/<name>/ or examples/<name>/ under cwd. */
446
+ game?: string;
447
+ /** Explicit entry file (default: <game>/src/native-entry.ts). */
448
+ entry?: string;
449
+ /** Working directory for the spawned process (default: process.cwd() —
450
+ * the monorepo root or a standalone game dir, where bunfig.toml's
451
+ * preload registers the ?raw/.wgsl/.css loaders). */
452
+ cwd?: string;
453
+ /** MCP_PORT pin; default is an OS-assigned free port. */
454
+ port?: number;
455
+ /** DOWNDRAFT_DETERMINISTIC=1 (fixed seed, paused render loop). */
456
+ deterministic?: boolean;
457
+ /** DOWNDRAFT_GPU value. Default: parent env, else "swiftshader". */
458
+ gpu?: "auto" | "hardware" | "swiftshader";
459
+ /** DOWNDRAFT_HEADED=1 — show the window instead of headless. */
460
+ headed?: boolean;
461
+ /** Extra env vars, applied last. */
462
+ env?: Record<string, string>;
463
+ /** Extra console-output patterns to ignore for getConsoleErrors(). */
464
+ ignoreErrorPatterns?: RegExp[];
465
+ /** Readiness budget in ms (default 90s). */
466
+ timeoutMs?: number;
467
+ /** Tee child stdout/stderr to this process's (default false). */
468
+ mirrorOutput?: boolean;
469
+ }
470
+
471
+ export interface LaunchedGame {
472
+ client: GameClient;
473
+ process: ChildProcess;
474
+ pid: number;
475
+ port: number;
476
+ /** The instance's bearer token (may be undefined when the launch raced
477
+ * the pid-file write; tools still work unless auth is required). */
478
+ token?: string;
479
+ /** JS-error-looking lines captured from the child's console output. */
480
+ getConsoleErrors(): string[];
481
+ /** SIGTERM the process group + /proc descendants, SIGKILL after 5s. */
482
+ kill(): Promise<void>;
483
+ }
484
+
485
+ /** Find a free loopback TCP port (OS-assigned). */
486
+ export function findFreePort(): Promise<number> {
487
+ return new Promise((resolvePort, reject) => {
488
+ const srv = createServer();
489
+ srv.listen(0, "127.0.0.1", () => {
490
+ const addr = srv.address();
491
+ const port = typeof addr === "object" && addr ? addr.port : 0;
492
+ srv.close(() => (port ? resolvePort(port) : reject(new Error("no port assigned"))));
493
+ });
494
+ srv.on("error", reject);
495
+ });
496
+ }
497
+
498
+ const DEFAULT_ERROR_PATTERNS = [
499
+ /Uncaught/i,
500
+ /TypeError:/,
501
+ /ReferenceError:/,
502
+ /SyntaxError:/,
503
+ /RangeError:/,
504
+ /WrongDocumentError:/,
505
+ /is not a function/,
506
+ /is not defined/,
507
+ /cannot read propert/i,
508
+ /REJECTED action/i,
509
+ /GPU process exited unexpectedly/i,
510
+ /WebGPU.*not available/i,
511
+ /adapter request failed/i,
512
+ /\[.*WorkerHost.*\]\s*[Ww]orker error:/i,
513
+ ];
514
+
515
+ const DEFAULT_IGNORE_PATTERNS = [
516
+ /ERROR:components\/services\/storage/,
517
+ /ERROR:storage\/browser/,
518
+ /Gtk-Message/,
519
+ /deprecated.*session\.loadExtension/,
520
+ /SandboxOriginDatabase/,
521
+ /Failed to load module.*xapp-gtk3/,
522
+ /Failed to delete the database/,
523
+ /Could not open the quota database/,
524
+ /WebSocket connection.*failed/,
525
+ /gc.*does not exist/,
526
+ /Physics re-initialized after panic/i,
527
+ /Slow (tick|physics)/,
528
+ ];
529
+
530
+ function isRealError(line: string, extraIgnorePatterns: RegExp[] = []): boolean {
531
+ const stripped = line.replace(/\x1b\[[0-9;]*m/g, "").replace(/\x1b\[[0-9;]*/g, "");
532
+ if (!DEFAULT_ERROR_PATTERNS.some((p) => p.test(stripped))) return false;
533
+ if (DEFAULT_IGNORE_PATTERNS.some((p) => p.test(stripped))) return false;
534
+ return !extraIgnorePatterns.some((p) => p.test(stripped));
535
+ }
536
+
537
+ /** Collect all descendant PIDs of `rootPid` by walking /proc/<pid>/stat on
538
+ * Linux. Backup for helpers that called setsid and escaped the process
539
+ * group — the group signal alone would miss them. */
540
+ function collectDescendants(rootPid: number): number[] {
541
+ const childrenOf = new Map<number, number[]>();
542
+ try {
543
+ for (const entry of readdirSync("/proc")) {
544
+ if (!/^\d+$/.test(entry)) continue;
545
+ const pid = Number(entry);
546
+ if (pid === rootPid) continue;
547
+ try {
548
+ const stat = readFileSync(`/proc/${entry}/stat`, "utf8");
549
+ const rparen = stat.lastIndexOf(")");
550
+ if (rparen < 0) continue;
551
+ const ppid = Number(stat.slice(rparen + 2).split(" ")[1]);
552
+ if (ppid === rootPid || childrenOf.has(ppid)) {
553
+ const list = childrenOf.get(ppid) ?? [];
554
+ list.push(pid);
555
+ childrenOf.set(ppid, list);
556
+ }
557
+ } catch {
558
+ // Process exited between readdir and read — ignore.
559
+ }
560
+ }
561
+ } catch {
562
+ return []; // /proc unavailable (non-Linux)
563
+ }
564
+ const result: number[] = [];
565
+ const queue = [rootPid];
566
+ while (queue.length) {
567
+ const cur = queue.shift()!;
568
+ (childrenOf.get(cur) ?? []).forEach((k) => {
569
+ result.push(k);
570
+ queue.push(k);
571
+ });
572
+ }
573
+ return result;
574
+ }
575
+
576
+ /**
577
+ * Launch a game on the native runtime (`bun <entry>`), wait for its MCP
578
+ * endpoint to serve tools, and return a connected GameClient plus a kill()
579
+ * that tears down the whole process tree (detached group kill + /proc
580
+ * descendant sweep — the game must not outlive the caller).
581
+ */
582
+ export async function launchGame(opts: LaunchGameOptions = {}): Promise<LaunchedGame> {
583
+ const cwd = opts.cwd ?? process.cwd();
584
+ const game = opts.game ?? "to-the-ocean";
585
+ const entry = opts.entry
586
+ ? resolve(cwd, opts.entry)
587
+ : [
588
+ resolve(cwd, "games", game, "src", "native-entry.ts"),
589
+ resolve(cwd, "examples", game, "src", "native-entry.ts"),
590
+ resolve(cwd, "src", "native-entry.ts"),
591
+ ].find((p) => existsSync(p)) ?? resolve(cwd, "games", game, "src", "native-entry.ts");
592
+ if (!existsSync(entry)) {
593
+ throw new McpClientError(`Game entry not found: ${entry} (pass --entry or game:)`);
594
+ }
595
+ const port = opts.port ?? (await findFreePort());
596
+
597
+ const env: Record<string, string> = {
598
+ ...process.env,
599
+ MCP_PORT: String(port),
600
+ MCP_TIMEOUT_MS: String(DEFAULT_TIMEOUT_MS),
601
+ DOWNDRAFT_GPU: opts.gpu ?? process.env.DOWNDRAFT_GPU ?? "swiftshader",
602
+ ...(opts.deterministic ? { DOWNDRAFT_DETERMINISTIC: "1" } : {}),
603
+ ...(opts.headed ? { DOWNDRAFT_HEADED: "1" } : {}),
604
+ ...opts.env,
605
+ };
606
+ const proc = spawn("bun", [entry], {
607
+ cwd,
608
+ env,
609
+ stdio: ["ignore", "pipe", "pipe"],
610
+ // New session → child is a process-group leader, so kill(-pid)
611
+ // reaches helpers that get re-parented to init.
612
+ detached: true,
613
+ });
614
+ const exited = new Promise<number | null>((res) => proc.once("exit", (code) => res(code)));
615
+
616
+ // Capture console output lines to detect JS errors.
617
+ const consoleErrors: string[] = [];
618
+ const watchStream = (stream: NodeJS.ReadableStream | null, mirror: (s: string) => void) => {
619
+ if (!stream) return;
620
+ let buf = "";
621
+ stream.on("data", (chunk: Buffer) => {
622
+ const text = chunk.toString();
623
+ buf += text;
624
+ if (opts.mirrorOutput) mirror(text);
625
+ const lines = buf.split("\n");
626
+ buf = lines.pop() ?? "";
627
+ lines.forEach((line) => {
628
+ if (isRealError(line, opts.ignoreErrorPatterns)) {
629
+ consoleErrors.push(line.replace(/\x1b\[[0-9;]*m/g, "").trim());
630
+ }
631
+ });
632
+ });
633
+ };
634
+ watchStream(proc.stdout, (s) => process.stdout.write(s));
635
+ watchStream(proc.stderr, (s) => process.stderr.write(s));
636
+
637
+ const kill = async () => {
638
+ const pid = proc.pid;
639
+ const signalAll = (sig: NodeJS.Signals) => {
640
+ if (pid) {
641
+ try { process.kill(-pid, sig); } catch { /* group already gone */ }
642
+ [pid, ...collectDescendants(pid)].forEach((p) => {
643
+ try { process.kill(p, sig); } catch { /* already dead */ }
644
+ });
645
+ } else {
646
+ try { proc.kill(sig); } catch { /* already dead */ }
647
+ }
648
+ };
649
+ signalAll("SIGTERM");
650
+ try {
651
+ await Promise.race([
652
+ exited,
653
+ new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 5_000)),
654
+ ]);
655
+ } catch {
656
+ signalAll("SIGKILL");
657
+ try { await exited; } catch { /* gone */ }
658
+ }
659
+ };
660
+
661
+ // The token file (when required) is written synchronously at server
662
+ // bind — poll briefly so callers don't race it.
663
+ let token: string | undefined;
664
+ {
665
+ const tokenFile = join(mcpPortDir(), `${proc.pid}.token`);
666
+ const deadline = Date.now() + 15_000;
667
+ while (Date.now() < deadline && proc.exitCode === null) {
668
+ if (existsSync(tokenFile)) {
669
+ try { token = readFileSync(tokenFile, "utf8").trim() || undefined; } catch { /* retry */ }
670
+ break;
671
+ }
672
+ // No token file → auth not required; don't wait for a file that
673
+ // will never appear. But it also may just not be written yet —
674
+ // the transport always writes one, so if the pid file exists
675
+ // but the token doesn't, auth is genuinely off.
676
+ if (existsSync(join(mcpPortDir(), String(proc.pid)))) break;
677
+ await sleep(100);
678
+ }
679
+ }
680
+
681
+ const client = await GameClient.connect({
682
+ url: `http://localhost:${port}/mcp`,
683
+ token,
684
+ timeoutMs: opts.timeoutMs,
685
+ }).catch(async (e) => { await kill(); throw e; });
686
+
687
+ try {
688
+ await client.waitForReady(opts.timeoutMs ?? 90_000, { proc });
689
+ } catch (e) {
690
+ await kill();
691
+ throw e;
692
+ }
693
+
694
+ return {
695
+ client,
696
+ process: proc,
697
+ pid: proc.pid ?? 0,
698
+ port,
699
+ token,
700
+ getConsoleErrors: () => [...consoleErrors],
701
+ kill,
702
+ };
703
+ }