@thunderclap-engine/engine 0.0.0-stage → 1.1.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 (566) hide show
  1. package/CHANGELOG.md +390 -0
  2. package/LICENSE +21 -0
  3. package/README.md +333 -2
  4. package/dist/analytics/analytics.d.ts +80 -0
  5. package/dist/analytics/analytics.js +129 -0
  6. package/dist/analytics/index.d.ts +1 -0
  7. package/dist/analytics/index.js +1 -0
  8. package/dist/anim/aim.d.ts +43 -0
  9. package/dist/anim/aim.js +157 -0
  10. package/dist/anim/clip.d.ts +98 -0
  11. package/dist/anim/clip.js +282 -0
  12. package/dist/anim/compress.d.ts +65 -0
  13. package/dist/anim/compress.js +339 -0
  14. package/dist/anim/foot-ik.d.ts +74 -0
  15. package/dist/anim/foot-ik.js +241 -0
  16. package/dist/anim/graph.d.ts +153 -0
  17. package/dist/anim/graph.js +532 -0
  18. package/dist/anim/ik.d.ts +105 -0
  19. package/dist/anim/ik.js +435 -0
  20. package/dist/anim/index.d.ts +36 -0
  21. package/dist/anim/index.js +21 -0
  22. package/dist/anim/match.d.ts +66 -0
  23. package/dist/anim/match.js +153 -0
  24. package/dist/anim/mixer.d.ts +113 -0
  25. package/dist/anim/mixer.js +314 -0
  26. package/dist/anim/morph.d.ts +41 -0
  27. package/dist/anim/morph.js +94 -0
  28. package/dist/anim/pose.d.ts +74 -0
  29. package/dist/anim/pose.js +254 -0
  30. package/dist/anim/quat.d.ts +44 -0
  31. package/dist/anim/quat.js +187 -0
  32. package/dist/anim/retarget.d.ts +97 -0
  33. package/dist/anim/retarget.js +366 -0
  34. package/dist/anim/root-motion.d.ts +44 -0
  35. package/dist/anim/root-motion.js +224 -0
  36. package/dist/anim/skin-pose.d.ts +39 -0
  37. package/dist/anim/skin-pose.js +53 -0
  38. package/dist/anim/socket.d.ts +47 -0
  39. package/dist/anim/socket.js +84 -0
  40. package/dist/anim/spring-chain.d.ts +73 -0
  41. package/dist/anim/spring-chain.js +294 -0
  42. package/dist/assets/atlas.d.ts +90 -0
  43. package/dist/assets/atlas.js +212 -0
  44. package/dist/assets/baked.d.ts +33 -0
  45. package/dist/assets/baked.js +38 -0
  46. package/dist/assets/bundle.d.ts +88 -0
  47. package/dist/assets/bundle.js +464 -0
  48. package/dist/assets/cache.d.ts +56 -0
  49. package/dist/assets/cache.js +123 -0
  50. package/dist/assets/gltf-load.d.ts +252 -0
  51. package/dist/assets/gltf-load.js +661 -0
  52. package/dist/assets/gltf-skin.d.ts +36 -0
  53. package/dist/assets/gltf-skin.js +109 -0
  54. package/dist/assets/gltf.d.ts +706 -0
  55. package/dist/assets/gltf.js +1376 -0
  56. package/dist/assets/index.d.ts +20 -0
  57. package/dist/assets/index.js +10 -0
  58. package/dist/assets/ktx2.d.ts +71 -0
  59. package/dist/assets/ktx2.js +213 -0
  60. package/dist/assets/manifest.d.ts +79 -0
  61. package/dist/assets/manifest.js +7 -0
  62. package/dist/assets/meshopt.d.ts +23 -0
  63. package/dist/assets/meshopt.js +403 -0
  64. package/dist/audio/audio.d.ts +733 -0
  65. package/dist/audio/audio.js +2013 -0
  66. package/dist/audio/dsp.d.ts +61 -0
  67. package/dist/audio/dsp.js +159 -0
  68. package/dist/audio/duck.d.ts +44 -0
  69. package/dist/audio/duck.js +101 -0
  70. package/dist/audio/envelope.d.ts +53 -0
  71. package/dist/audio/envelope.js +106 -0
  72. package/dist/audio/index.d.ts +13 -0
  73. package/dist/audio/index.js +14 -0
  74. package/dist/audio/music.d.ts +113 -0
  75. package/dist/audio/music.js +548 -0
  76. package/dist/audio/occlusion.d.ts +55 -0
  77. package/dist/audio/occlusion.js +61 -0
  78. package/dist/audio/persist.d.ts +23 -0
  79. package/dist/audio/persist.js +27 -0
  80. package/dist/audio/recipes.d.ts +55 -0
  81. package/dist/audio/recipes.js +227 -0
  82. package/dist/audio/send.d.ts +41 -0
  83. package/dist/audio/send.js +118 -0
  84. package/dist/audio/sprites.d.ts +59 -0
  85. package/dist/audio/sprites.js +43 -0
  86. package/dist/audio/synth.d.ts +103 -0
  87. package/dist/audio/synth.js +197 -0
  88. package/dist/audio/variations.d.ts +25 -0
  89. package/dist/audio/variations.js +55 -0
  90. package/dist/audio/zones.d.ts +100 -0
  91. package/dist/audio/zones.js +167 -0
  92. package/dist/core/detached-surface.d.ts +44 -0
  93. package/dist/core/detached-surface.js +104 -0
  94. package/dist/core/events.d.ts +24 -0
  95. package/dist/core/events.js +43 -0
  96. package/dist/core/game.d.ts +409 -0
  97. package/dist/core/game.js +530 -0
  98. package/dist/core/hash.d.ts +24 -0
  99. package/dist/core/hash.js +49 -0
  100. package/dist/core/index.d.ts +17 -0
  101. package/dist/core/index.js +9 -0
  102. package/dist/core/loop.d.ts +113 -0
  103. package/dist/core/loop.js +185 -0
  104. package/dist/core/math.d.ts +58 -0
  105. package/dist/core/math.js +210 -0
  106. package/dist/core/noise.d.ts +40 -0
  107. package/dist/core/noise.js +247 -0
  108. package/dist/core/pool.d.ts +42 -0
  109. package/dist/core/pool.js +85 -0
  110. package/dist/core/random.d.ts +61 -0
  111. package/dist/core/random.js +199 -0
  112. package/dist/core/scene.d.ts +79 -0
  113. package/dist/core/scene.js +195 -0
  114. package/dist/core/timer.d.ts +66 -0
  115. package/dist/core/timer.js +286 -0
  116. package/dist/fx/billboard-wgsl.d.ts +29 -0
  117. package/dist/fx/billboard-wgsl.js +158 -0
  118. package/dist/fx/billboard.d.ts +249 -0
  119. package/dist/fx/billboard.js +702 -0
  120. package/dist/fx/debug-draw.d.ts +127 -0
  121. package/dist/fx/debug-draw.js +523 -0
  122. package/dist/fx/debug-wgsl.d.ts +7 -0
  123. package/dist/fx/debug-wgsl.js +32 -0
  124. package/dist/fx/decals-wgsl.d.ts +15 -0
  125. package/dist/fx/decals-wgsl.js +173 -0
  126. package/dist/fx/decals.d.ts +216 -0
  127. package/dist/fx/decals.js +607 -0
  128. package/dist/fx/effect.d.ts +129 -0
  129. package/dist/fx/effect.js +349 -0
  130. package/dist/fx/effects/hit-spark.json +48 -0
  131. package/dist/fx/effects/index.d.ts +8 -0
  132. package/dist/fx/effects/index.js +9 -0
  133. package/dist/fx/effects/magic-aura.json +47 -0
  134. package/dist/fx/effects/smoke-puff.json +34 -0
  135. package/dist/fx/emit-surface.d.ts +40 -0
  136. package/dist/fx/emit-surface.js +124 -0
  137. package/dist/fx/flicker.d.ts +30 -0
  138. package/dist/fx/flicker.js +42 -0
  139. package/dist/fx/index.d.ts +31 -0
  140. package/dist/fx/index.js +20 -0
  141. package/dist/fx/particles-wgsl.d.ts +57 -0
  142. package/dist/fx/particles-wgsl.js +828 -0
  143. package/dist/fx/particles.d.ts +566 -0
  144. package/dist/fx/particles.js +1533 -0
  145. package/dist/fx/random.d.ts +15 -0
  146. package/dist/fx/random.js +20 -0
  147. package/dist/fx/sky-wgsl.d.ts +23 -0
  148. package/dist/fx/sky-wgsl.js +127 -0
  149. package/dist/fx/sky.d.ts +96 -0
  150. package/dist/fx/sky.js +175 -0
  151. package/dist/fx/text-atlas.d.ts +143 -0
  152. package/dist/fx/text-atlas.js +327 -0
  153. package/dist/fx/trail-wgsl.d.ts +11 -0
  154. package/dist/fx/trail-wgsl.js +42 -0
  155. package/dist/fx/trail.d.ts +194 -0
  156. package/dist/fx/trail.js +555 -0
  157. package/dist/fx/water-wgsl.d.ts +34 -0
  158. package/dist/fx/water-wgsl.js +197 -0
  159. package/dist/fx/water.d.ts +176 -0
  160. package/dist/fx/water.js +371 -0
  161. package/dist/geom/collide/bvh.d.ts +151 -0
  162. package/dist/geom/collide/bvh.js +493 -0
  163. package/dist/geom/collide/debug.d.ts +14 -0
  164. package/dist/geom/collide/debug.js +74 -0
  165. package/dist/geom/collide/grid.d.ts +26 -0
  166. package/dist/geom/collide/grid.js +91 -0
  167. package/dist/geom/collide/index.d.ts +8 -0
  168. package/dist/geom/collide/index.js +8 -0
  169. package/dist/geom/collide/queries.d.ts +70 -0
  170. package/dist/geom/collide/queries.js +583 -0
  171. package/dist/geom/collide/serialize.d.ts +14 -0
  172. package/dist/geom/collide/serialize.js +145 -0
  173. package/dist/geom/collide/shapes.d.ts +161 -0
  174. package/dist/geom/collide/shapes.js +686 -0
  175. package/dist/geom/collide/slide.d.ts +66 -0
  176. package/dist/geom/collide/slide.js +375 -0
  177. package/dist/geom/collide/tile-slide.d.ts +88 -0
  178. package/dist/geom/collide/tile-slide.js +255 -0
  179. package/dist/geom/geometry.d.ts +95 -0
  180. package/dist/geom/geometry.js +322 -0
  181. package/dist/geom/heightfield.d.ts +72 -0
  182. package/dist/geom/heightfield.js +295 -0
  183. package/dist/geom/hull.d.ts +27 -0
  184. package/dist/geom/hull.js +279 -0
  185. package/dist/geom/index.d.ts +35 -0
  186. package/dist/geom/index.js +23 -0
  187. package/dist/geom/iso.d.ts +74 -0
  188. package/dist/geom/iso.js +89 -0
  189. package/dist/geom/lod.d.ts +29 -0
  190. package/dist/geom/lod.js +27 -0
  191. package/dist/geom/ops.d.ts +47 -0
  192. package/dist/geom/ops.js +285 -0
  193. package/dist/geom/primitives.d.ts +97 -0
  194. package/dist/geom/primitives.js +359 -0
  195. package/dist/geom/shapes.d.ts +43 -0
  196. package/dist/geom/shapes.js +88 -0
  197. package/dist/geom/simplify.d.ts +38 -0
  198. package/dist/geom/simplify.js +519 -0
  199. package/dist/geom/split.d.ts +37 -0
  200. package/dist/geom/split.js +413 -0
  201. package/dist/geom/sweep.d.ts +83 -0
  202. package/dist/geom/sweep.js +534 -0
  203. package/dist/geom/tangents.d.ts +16 -0
  204. package/dist/geom/tangents.js +124 -0
  205. package/dist/geom/triangulate.d.ts +19 -0
  206. package/dist/geom/triangulate.js +147 -0
  207. package/dist/host/default.d.ts +10 -0
  208. package/dist/host/default.js +10 -0
  209. package/dist/host/index.d.ts +4 -0
  210. package/dist/host/index.js +3 -0
  211. package/dist/host/types.d.ts +144 -0
  212. package/dist/host/types.js +1 -0
  213. package/dist/host/web-links.d.ts +38 -0
  214. package/dist/host/web-links.js +110 -0
  215. package/dist/host/web.d.ts +30 -0
  216. package/dist/host/web.js +216 -0
  217. package/dist/host/xr.d.ts +24 -0
  218. package/dist/host/xr.js +59 -0
  219. package/dist/i18n/i18n.d.ts +59 -0
  220. package/dist/i18n/i18n.js +241 -0
  221. package/dist/i18n/index.d.ts +3 -0
  222. package/dist/i18n/index.js +3 -0
  223. package/dist/i18n/message.d.ts +72 -0
  224. package/dist/i18n/message.js +369 -0
  225. package/dist/i18n/negotiate.d.ts +17 -0
  226. package/dist/i18n/negotiate.js +58 -0
  227. package/dist/index.d.ts +7 -0
  228. package/dist/index.js +1 -0
  229. package/dist/input/bindings.d.ts +31 -0
  230. package/dist/input/bindings.js +141 -0
  231. package/dist/input/clock.d.ts +44 -0
  232. package/dist/input/clock.js +49 -0
  233. package/dist/input/follow.d.ts +133 -0
  234. package/dist/input/follow.js +218 -0
  235. package/dist/input/gestures.d.ts +281 -0
  236. package/dist/input/gestures.js +662 -0
  237. package/dist/input/glyphs.d.ts +35 -0
  238. package/dist/input/glyphs.js +216 -0
  239. package/dist/input/gyro.d.ts +85 -0
  240. package/dist/input/gyro.js +140 -0
  241. package/dist/input/index.d.ts +19 -0
  242. package/dist/input/index.js +16 -0
  243. package/dist/input/input.d.ts +543 -0
  244. package/dist/input/input.js +1492 -0
  245. package/dist/input/look.d.ts +327 -0
  246. package/dist/input/look.js +681 -0
  247. package/dist/input/magnify.d.ts +177 -0
  248. package/dist/input/magnify.js +131 -0
  249. package/dist/input/pointer-dispatch.d.ts +138 -0
  250. package/dist/input/pointer-dispatch.js +180 -0
  251. package/dist/input/pointer-router.d.ts +204 -0
  252. package/dist/input/pointer-router.js +533 -0
  253. package/dist/input/pointer-sources.d.ts +164 -0
  254. package/dist/input/pointer-sources.js +306 -0
  255. package/dist/input/rays.d.ts +138 -0
  256. package/dist/input/rays.js +615 -0
  257. package/dist/input/record.d.ts +209 -0
  258. package/dist/input/record.js +601 -0
  259. package/dist/input/touch-zones.d.ts +147 -0
  260. package/dist/input/touch-zones.js +300 -0
  261. package/dist/input/types.d.ts +158 -0
  262. package/dist/input/types.js +1 -0
  263. package/dist/input/xr-source.d.ts +53 -0
  264. package/dist/input/xr-source.js +164 -0
  265. package/dist/nav/astar.d.ts +45 -0
  266. package/dist/nav/astar.js +182 -0
  267. package/dist/nav/corridor.d.ts +40 -0
  268. package/dist/nav/corridor.js +95 -0
  269. package/dist/nav/crowd.d.ts +94 -0
  270. package/dist/nav/crowd.js +624 -0
  271. package/dist/nav/flow.d.ts +61 -0
  272. package/dist/nav/flow.js +193 -0
  273. package/dist/nav/grid.d.ts +108 -0
  274. package/dist/nav/grid.js +210 -0
  275. package/dist/nav/heap.d.ts +22 -0
  276. package/dist/nav/heap.js +92 -0
  277. package/dist/nav/index.d.ts +37 -0
  278. package/dist/nav/index.js +19 -0
  279. package/dist/nav/mesh/areas.d.ts +44 -0
  280. package/dist/nav/mesh/areas.js +98 -0
  281. package/dist/nav/mesh/bake-options.d.ts +33 -0
  282. package/dist/nav/mesh/bake-options.js +76 -0
  283. package/dist/nav/mesh/contour.d.ts +22 -0
  284. package/dist/nav/mesh/contour.js +323 -0
  285. package/dist/nav/mesh/flow3.d.ts +35 -0
  286. package/dist/nav/mesh/flow3.js +229 -0
  287. package/dist/nav/mesh/links.d.ts +38 -0
  288. package/dist/nav/mesh/links.js +72 -0
  289. package/dist/nav/mesh/mesh-path.d.ts +152 -0
  290. package/dist/nav/mesh/mesh-path.js +643 -0
  291. package/dist/nav/mesh/mesh-reach.d.ts +78 -0
  292. package/dist/nav/mesh/mesh-reach.js +450 -0
  293. package/dist/nav/mesh/navmesh.d.ts +117 -0
  294. package/dist/nav/mesh/navmesh.js +647 -0
  295. package/dist/nav/mesh/polymesh.d.ts +24 -0
  296. package/dist/nav/mesh/polymesh.js +384 -0
  297. package/dist/nav/mesh/regions.d.ts +12 -0
  298. package/dist/nav/mesh/regions.js +367 -0
  299. package/dist/nav/mesh/serialize.d.ts +13 -0
  300. package/dist/nav/mesh/serialize.js +197 -0
  301. package/dist/nav/mesh/voxelize.d.ts +111 -0
  302. package/dist/nav/mesh/voxelize.js +552 -0
  303. package/dist/nav/obstacles.d.ts +75 -0
  304. package/dist/nav/obstacles.js +294 -0
  305. package/dist/nav/path.d.ts +59 -0
  306. package/dist/nav/path.js +177 -0
  307. package/dist/nav/query-queue.d.ts +46 -0
  308. package/dist/nav/query-queue.js +308 -0
  309. package/dist/nav/reach.d.ts +53 -0
  310. package/dist/nav/reach.js +148 -0
  311. package/dist/nav/steer.d.ts +36 -0
  312. package/dist/nav/steer.js +78 -0
  313. package/dist/platform/boot.d.ts +28 -0
  314. package/dist/platform/boot.js +43 -0
  315. package/dist/platform/device-mode.d.ts +40 -0
  316. package/dist/platform/device-mode.js +104 -0
  317. package/dist/platform/device.d.ts +31 -0
  318. package/dist/platform/device.js +91 -0
  319. package/dist/platform/environment.d.ts +42 -0
  320. package/dist/platform/environment.js +82 -0
  321. package/dist/platform/gpu.d.ts +40 -0
  322. package/dist/platform/gpu.js +57 -0
  323. package/dist/platform/index.d.ts +18 -0
  324. package/dist/platform/index.js +10 -0
  325. package/dist/platform/letterbox.d.ts +43 -0
  326. package/dist/platform/letterbox.js +57 -0
  327. package/dist/platform/links.d.ts +20 -0
  328. package/dist/platform/links.js +43 -0
  329. package/dist/platform/screens.d.ts +36 -0
  330. package/dist/platform/screens.js +138 -0
  331. package/dist/platform/surface.d.ts +72 -0
  332. package/dist/platform/surface.js +157 -0
  333. package/dist/platform/xr-fake.d.ts +168 -0
  334. package/dist/platform/xr-fake.js +434 -0
  335. package/dist/platform/xr-surface.d.ts +120 -0
  336. package/dist/platform/xr-surface.js +214 -0
  337. package/dist/platform/xr-types.d.ts +262 -0
  338. package/dist/post/ao.d.ts +12 -0
  339. package/dist/post/ao.js +136 -0
  340. package/dist/post/blend.d.ts +27 -0
  341. package/dist/post/blend.js +129 -0
  342. package/dist/post/depth-pass.d.ts +43 -0
  343. package/dist/post/depth-pass.js +118 -0
  344. package/dist/post/dof.d.ts +1 -0
  345. package/dist/post/dof.js +66 -0
  346. package/dist/post/exposure.d.ts +80 -0
  347. package/dist/post/exposure.js +322 -0
  348. package/dist/post/index.d.ts +12 -0
  349. package/dist/post/index.js +11 -0
  350. package/dist/post/lens-dirt.d.ts +13 -0
  351. package/dist/post/lens-dirt.js +91 -0
  352. package/dist/post/lut.d.ts +19 -0
  353. package/dist/post/lut.js +50 -0
  354. package/dist/post/motion-blur.d.ts +9 -0
  355. package/dist/post/motion-blur.js +78 -0
  356. package/dist/post/post-stack.d.ts +302 -0
  357. package/dist/post/post-stack.js +1137 -0
  358. package/dist/post/settings.d.ts +485 -0
  359. package/dist/post/settings.js +416 -0
  360. package/dist/post/shaders.d.ts +25 -0
  361. package/dist/post/shaders.js +410 -0
  362. package/dist/post/ssr.d.ts +16 -0
  363. package/dist/post/ssr.js +155 -0
  364. package/dist/post/taa.d.ts +74 -0
  365. package/dist/post/taa.js +235 -0
  366. package/dist/post/white-balance.d.ts +25 -0
  367. package/dist/post/white-balance.js +98 -0
  368. package/dist/render/bindings.d.ts +98 -0
  369. package/dist/render/bindings.js +281 -0
  370. package/dist/render/blend.d.ts +13 -0
  371. package/dist/render/blend.js +26 -0
  372. package/dist/render/camera-2d.d.ts +72 -0
  373. package/dist/render/camera-2d.js +92 -0
  374. package/dist/render/camera.d.ts +302 -0
  375. package/dist/render/camera.js +671 -0
  376. package/dist/render/color.d.ts +16 -0
  377. package/dist/render/color.js +41 -0
  378. package/dist/render/compressed.d.ts +104 -0
  379. package/dist/render/compressed.js +248 -0
  380. package/dist/render/diagnostics.d.ts +15 -0
  381. package/dist/render/diagnostics.js +43 -0
  382. package/dist/render/dynamic-resolution.d.ts +70 -0
  383. package/dist/render/dynamic-resolution.js +126 -0
  384. package/dist/render/fake-gpu.d.ts +204 -0
  385. package/dist/render/fake-gpu.js +426 -0
  386. package/dist/render/flipbook.d.ts +56 -0
  387. package/dist/render/flipbook.js +87 -0
  388. package/dist/render/frame.d.ts +278 -0
  389. package/dist/render/frame.js +174 -0
  390. package/dist/render/fullscreen.d.ts +54 -0
  391. package/dist/render/fullscreen.js +91 -0
  392. package/dist/render/gpu-timer.d.ts +73 -0
  393. package/dist/render/gpu-timer.js +186 -0
  394. package/dist/render/index.d.ts +53 -0
  395. package/dist/render/index.js +29 -0
  396. package/dist/render/instance-list.d.ts +185 -0
  397. package/dist/render/instance-list.js +547 -0
  398. package/dist/render/lights.d.ts +181 -0
  399. package/dist/render/lights.js +233 -0
  400. package/dist/render/lod.d.ts +54 -0
  401. package/dist/render/lod.js +52 -0
  402. package/dist/render/material.d.ts +165 -0
  403. package/dist/render/material.js +292 -0
  404. package/dist/render/mesh.d.ts +284 -0
  405. package/dist/render/mesh.js +472 -0
  406. package/dist/render/mipmap.d.ts +16 -0
  407. package/dist/render/mipmap.js +121 -0
  408. package/dist/render/parallax.d.ts +50 -0
  409. package/dist/render/parallax.js +47 -0
  410. package/dist/render/pbr-wgsl.d.ts +31 -0
  411. package/dist/render/pbr-wgsl.js +119 -0
  412. package/dist/render/ping-pong.d.ts +42 -0
  413. package/dist/render/ping-pong.js +74 -0
  414. package/dist/render/renderer.d.ts +741 -0
  415. package/dist/render/renderer.js +2486 -0
  416. package/dist/render/scene-pipelines.d.ts +44 -0
  417. package/dist/render/scene-pipelines.js +92 -0
  418. package/dist/render/scene-target.d.ts +170 -0
  419. package/dist/render/scene-target.js +450 -0
  420. package/dist/render/shadow.d.ts +74 -0
  421. package/dist/render/shadow.js +208 -0
  422. package/dist/render/skin.d.ts +112 -0
  423. package/dist/render/skin.js +240 -0
  424. package/dist/render/snapshot.d.ts +36 -0
  425. package/dist/render/snapshot.js +34 -0
  426. package/dist/render/standard.d.ts +162 -0
  427. package/dist/render/standard.js +263 -0
  428. package/dist/render/texture.d.ts +142 -0
  429. package/dist/render/texture.js +228 -0
  430. package/dist/render/tile-layer.d.ts +110 -0
  431. package/dist/render/tile-layer.js +304 -0
  432. package/dist/render/transform.d.ts +115 -0
  433. package/dist/render/transform.js +318 -0
  434. package/dist/render/wgsl.d.ts +131 -0
  435. package/dist/render/wgsl.js +528 -0
  436. package/dist/save/codec.d.ts +49 -0
  437. package/dist/save/codec.js +169 -0
  438. package/dist/save/index.d.ts +8 -0
  439. package/dist/save/index.js +8 -0
  440. package/dist/save/journal.d.ts +24 -0
  441. package/dist/save/journal.js +102 -0
  442. package/dist/save/migrate.d.ts +15 -0
  443. package/dist/save/migrate.js +37 -0
  444. package/dist/save/schema.d.ts +72 -0
  445. package/dist/save/schema.js +154 -0
  446. package/dist/save/settings.d.ts +28 -0
  447. package/dist/save/settings.js +59 -0
  448. package/dist/save/slots.d.ts +56 -0
  449. package/dist/save/slots.js +200 -0
  450. package/dist/save/storage.d.ts +35 -0
  451. package/dist/save/storage.js +62 -0
  452. package/dist/save/store.d.ts +114 -0
  453. package/dist/save/store.js +269 -0
  454. package/dist/testing/fake-host.d.ts +103 -0
  455. package/dist/testing/fake-host.js +163 -0
  456. package/dist/testing/fixed-clock.d.ts +25 -0
  457. package/dist/testing/fixed-clock.js +30 -0
  458. package/dist/testing/index.d.ts +4 -0
  459. package/dist/testing/index.js +5 -0
  460. package/dist/testing/test-game.d.ts +76 -0
  461. package/dist/testing/test-game.js +92 -0
  462. package/dist/tween/ease.d.ts +77 -0
  463. package/dist/tween/ease.js +192 -0
  464. package/dist/tween/index.d.ts +8 -0
  465. package/dist/tween/index.js +7 -0
  466. package/dist/tween/timeline.d.ts +78 -0
  467. package/dist/tween/timeline.js +269 -0
  468. package/dist/tween/tween.d.ts +168 -0
  469. package/dist/tween/tween.js +320 -0
  470. package/dist/ui/anchor.d.ts +206 -0
  471. package/dist/ui/anchor.js +307 -0
  472. package/dist/ui/caption.d.ts +122 -0
  473. package/dist/ui/caption.js +286 -0
  474. package/dist/ui/cursor.d.ts +105 -0
  475. package/dist/ui/cursor.js +261 -0
  476. package/dist/ui/dom.d.ts +30 -0
  477. package/dist/ui/dom.js +92 -0
  478. package/dist/ui/floats.d.ts +86 -0
  479. package/dist/ui/floats.js +260 -0
  480. package/dist/ui/hud.d.ts +198 -0
  481. package/dist/ui/hud.js +431 -0
  482. package/dist/ui/index.d.ts +37 -0
  483. package/dist/ui/index.js +34 -0
  484. package/dist/ui/inventory-card.d.ts +52 -0
  485. package/dist/ui/inventory-card.js +173 -0
  486. package/dist/ui/inventory-context.d.ts +29 -0
  487. package/dist/ui/inventory-context.js +125 -0
  488. package/dist/ui/inventory-drag.d.ts +63 -0
  489. package/dist/ui/inventory-drag.js +394 -0
  490. package/dist/ui/inventory-grid.d.ts +66 -0
  491. package/dist/ui/inventory-grid.js +625 -0
  492. package/dist/ui/inventory-radial.d.ts +39 -0
  493. package/dist/ui/inventory-radial.js +168 -0
  494. package/dist/ui/inventory.d.ts +128 -0
  495. package/dist/ui/inventory.js +154 -0
  496. package/dist/ui/layout.d.ts +356 -0
  497. package/dist/ui/layout.js +856 -0
  498. package/dist/ui/link.d.ts +64 -0
  499. package/dist/ui/link.js +155 -0
  500. package/dist/ui/loading.d.ts +40 -0
  501. package/dist/ui/loading.js +157 -0
  502. package/dist/ui/loupe.d.ts +74 -0
  503. package/dist/ui/loupe.js +164 -0
  504. package/dist/ui/menu-nav.d.ts +33 -0
  505. package/dist/ui/menu-nav.js +28 -0
  506. package/dist/ui/minimap-canvas.d.ts +145 -0
  507. package/dist/ui/minimap-canvas.js +460 -0
  508. package/dist/ui/notify.d.ts +40 -0
  509. package/dist/ui/notify.js +141 -0
  510. package/dist/ui/orb.d.ts +53 -0
  511. package/dist/ui/orb.js +304 -0
  512. package/dist/ui/overlay.d.ts +213 -0
  513. package/dist/ui/overlay.js +394 -0
  514. package/dist/ui/padnav.d.ts +53 -0
  515. package/dist/ui/padnav.js +146 -0
  516. package/dist/ui/perf.d.ts +130 -0
  517. package/dist/ui/perf.js +329 -0
  518. package/dist/ui/rotate-card.d.ts +54 -0
  519. package/dist/ui/rotate-card.js +97 -0
  520. package/dist/ui/stack.d.ts +128 -0
  521. package/dist/ui/stack.js +312 -0
  522. package/dist/ui/styles.d.ts +13 -0
  523. package/dist/ui/styles.js +200 -0
  524. package/dist/ui/text-scale.d.ts +67 -0
  525. package/dist/ui/text-scale.js +102 -0
  526. package/dist/ui/theme.d.ts +70 -0
  527. package/dist/ui/theme.js +98 -0
  528. package/dist/ui/toast.d.ts +23 -0
  529. package/dist/ui/toast.js +46 -0
  530. package/dist/ui/tooltip.d.ts +89 -0
  531. package/dist/ui/tooltip.js +333 -0
  532. package/dist/ui/widgets-2.d.ts +134 -0
  533. package/dist/ui/widgets-2.js +399 -0
  534. package/dist/ui/widgets-3.d.ts +91 -0
  535. package/dist/ui/widgets-3.js +212 -0
  536. package/dist/ui/widgets.d.ts +34 -0
  537. package/dist/ui/widgets.js +50 -0
  538. package/dist/ui/world-panel/index.d.ts +5 -0
  539. package/dist/ui/world-panel/index.js +5 -0
  540. package/dist/ui/world-panel/layout.d.ts +38 -0
  541. package/dist/ui/world-panel/layout.js +68 -0
  542. package/dist/ui/world-panel/paint.d.ts +96 -0
  543. package/dist/ui/world-panel/paint.js +136 -0
  544. package/dist/ui/world-panel/panel.d.ts +235 -0
  545. package/dist/ui/world-panel/panel.js +762 -0
  546. package/dist/ui/world-panel/wgsl.d.ts +10 -0
  547. package/dist/ui/world-panel/wgsl.js +52 -0
  548. package/dist/ui/world-panel/widgets.d.ts +207 -0
  549. package/dist/ui/world-panel/widgets.js +569 -0
  550. package/dist/voxel/chunks.d.ts +77 -0
  551. package/dist/voxel/chunks.js +149 -0
  552. package/dist/voxel/grid.d.ts +84 -0
  553. package/dist/voxel/grid.js +223 -0
  554. package/dist/voxel/index.d.ts +22 -0
  555. package/dist/voxel/index.js +7 -0
  556. package/dist/voxel/mesher-worker.d.ts +14 -0
  557. package/dist/voxel/mesher-worker.js +47 -0
  558. package/dist/voxel/mesher.d.ts +73 -0
  559. package/dist/voxel/mesher.js +306 -0
  560. package/dist/voxel/ray.d.ts +32 -0
  561. package/dist/voxel/ray.js +73 -0
  562. package/dist/voxel/wgsl.d.ts +16 -0
  563. package/dist/voxel/wgsl.js +28 -0
  564. package/dist/voxel/worker-client.d.ts +79 -0
  565. package/dist/voxel/worker-client.js +122 -0
  566. package/package.json +177 -3
@@ -0,0 +1,601 @@
1
+ /**
2
+ * Input recording and replay (ws/input-replay). A recorder sits beside an `Input` through its
3
+ * feed hook (`Input.onFeed`) and writes down, tick by tick, every feed call and the gamepad
4
+ * snapshot `update()` read. A playback feeds the same calls back into an `Input` before each
5
+ * `update()` and hands it the recorded pads, so an identical game sees identical `pressed`,
6
+ * `held`, `released` and `value` per tick. Neither changes how `Input` evaluates bindings.
7
+ *
8
+ * The recording is plain JSON: `{ version: 3, ticks: [...] }`, deltas only. A tick with events
9
+ * is `{ t, k?, b?, p?, w?, r?, d?, g?, ptr?, cx?, cs?, ui? }`; a run of ticks with none is
10
+ * `{ t, n }`.
11
+ * Version 2 (ws/input-5) adds the `ptr` lane (every pointer the dispatcher saw, so touch zones,
12
+ * gestures and a second thumb replay) and the observational `cx` and `cs`. Version 3
13
+ * (ws/input-7) stamps each `ptr` entry with its time, so a replayed tap, long-press or
14
+ * double-tap classifies as it did live. Versions 1 and 2 still parse and play. A recording may
15
+ * carry `tickMs`, its tick spacing (ws/input-9), which a playback given a tick `clock` advances
16
+ * it by per fed tick, so a replay at any `speed` keeps game time. The `ui` lane (ws/input-12)
17
+ * holds the overlay controls that fired on a tick, by stable id (`Input.control`); a playback
18
+ * replays them through `Input.replayControl` and an older reader skips them.
19
+ */
20
+ import { wallClock } from './clock.js';
21
+ /** The linked gestures' clock, else the linked look's, else the wall clock. */
22
+ function linkedClock(input) {
23
+ const g = input.gestures;
24
+ if (g)
25
+ return g.now;
26
+ const look = input.look;
27
+ if (look)
28
+ return () => look.clock.now();
29
+ return wallClock.now;
30
+ }
31
+ /** True when neither the linked gestures nor the linked look has a clock of its own. */
32
+ function onWallClock(input) {
33
+ const g = input.gestures;
34
+ if (g)
35
+ return g.clock === wallClock;
36
+ const look = input.look;
37
+ return !look || look.clock === wallClock;
38
+ }
39
+ const PHASES = ['down', 'move', 'up', 'cancel', 'leave'];
40
+ /** Called when a recording does not have the expected shape. */
41
+ export class InputRecordingError extends Error {
42
+ constructor(message) {
43
+ super(message);
44
+ this.name = 'InputRecordingError';
45
+ }
46
+ }
47
+ /** Total ticks a recording covers. */
48
+ export function recordingLength(rec) {
49
+ const last = rec.ticks[rec.ticks.length - 1];
50
+ if (!last)
51
+ return 0;
52
+ return last.t + ('n' in last ? last.n : 1);
53
+ }
54
+ function isRun(tick) {
55
+ return 'n' in tick;
56
+ }
57
+ // ---------------------------------------------------------------- recorder
58
+ /**
59
+ * Record everything `input` is fed. The recorder installs a feed hook and closes one tick per
60
+ * `input.update()`; `stop()` removes it. `input.recorder` points at it meanwhile.
61
+ */
62
+ export function createInputRecorder(input, opts = {}) {
63
+ const capturePads = opts.pads !== false;
64
+ const recording = { version: 3, ticks: [] };
65
+ const clock = opts.now ?? linkedClock(input);
66
+ const start = clock();
67
+ /** The spacing is measured on the recorder's clock unless that is the wall clock. */
68
+ const measure = opts.now !== undefined || !onWallClock(input);
69
+ /** ms since `start`, `age` ms ago, to 0.01 ms. */
70
+ const stamp = (age) => Math.round((clock() - age - start) * 100) / 100;
71
+ /** Pointers down (by id), for turning a blur into cancels. */
72
+ const live = new Map();
73
+ let t = 0;
74
+ /** The tick being built, or null while nothing happened on it. */
75
+ let cur = null;
76
+ /** The last pad snapshot written, for the delta comparison. */
77
+ let lastPads = [];
78
+ let padsWritten = false;
79
+ const open = () => {
80
+ if (!cur)
81
+ cur = { t };
82
+ return cur;
83
+ };
84
+ const key = (code, down) => {
85
+ const c = open();
86
+ if (c.k)
87
+ c.k.push([code, down]);
88
+ else
89
+ c.k = [[code, down]];
90
+ if (down && c.p)
91
+ c.d = 1;
92
+ };
93
+ const button = (b, down) => {
94
+ const c = open();
95
+ if (c.b)
96
+ c.b.push([b, down]);
97
+ else
98
+ c.b = [[b, down]];
99
+ };
100
+ const hook = {
101
+ keyDown: (code) => key(code, 1),
102
+ keyUp: (code) => key(code, 0),
103
+ buttonDown: (b) => button(b, 1),
104
+ buttonUp: (b) => button(b, 0),
105
+ wheel: (dx, dy) => {
106
+ const c = open();
107
+ if (c.w) {
108
+ c.w[0] += dx;
109
+ c.w[1] += dy;
110
+ }
111
+ else
112
+ c.w = [dx, dy];
113
+ },
114
+ pointerAt: (x, y, type) => {
115
+ const c = open();
116
+ c.p = type === 'mouse' ? [x, y] : [x, y, type];
117
+ if (c.d)
118
+ delete c.d;
119
+ },
120
+ releaseAll: () => {
121
+ open().r = 1;
122
+ },
123
+ rumble: (strong, weak, ms, pad) => {
124
+ const c = open();
125
+ const e = pad === undefined ? [strong, weak, ms] : [strong, weak, ms, pad];
126
+ if (c.rumble)
127
+ c.rumble.push(e);
128
+ else
129
+ c.rumble = [e];
130
+ },
131
+ pointer: (phase, p) => {
132
+ const c = open();
133
+ const ph = PHASES.indexOf(phase);
134
+ const e = [
135
+ ph,
136
+ p.id,
137
+ p.device,
138
+ p.clientX,
139
+ p.clientY,
140
+ p.button,
141
+ p.primary ? 1 : 0,
142
+ stamp(p.age),
143
+ ];
144
+ if (!c.ptr)
145
+ c.ptr = [];
146
+ const lane = c.ptr;
147
+ const last = lane[lane.length - 1];
148
+ if (ph === 1 && last && last[0] === 1 && last[1] === p.id)
149
+ lane[lane.length - 1] = e;
150
+ else
151
+ lane.push(e);
152
+ if (ph === 0 || (ph === 1 && live.has(p.id)))
153
+ live.set(p.id, e);
154
+ else if (ph === 2 || ph === 3)
155
+ live.delete(p.id);
156
+ },
157
+ cancelPointers: () => {
158
+ if (live.size === 0)
159
+ return;
160
+ const c = open();
161
+ if (!c.ptr)
162
+ c.ptr = [];
163
+ const lane = c.ptr;
164
+ const at = stamp(0);
165
+ for (const e of live.values())
166
+ lane.push([3, e[1], e[2], e[3], e[4], e[5], e[6], at]);
167
+ live.clear();
168
+ },
169
+ context: (name, pushed) => {
170
+ const c = open();
171
+ if (!c.cx)
172
+ c.cx = [];
173
+ c.cx.push([name, pushed ? 1 : 0]);
174
+ },
175
+ consume: (action) => {
176
+ const c = open();
177
+ if (!c.cs)
178
+ c.cs = [];
179
+ c.cs.push(action);
180
+ },
181
+ control: (id) => {
182
+ const c = open();
183
+ if (!c.ui)
184
+ c.ui = [];
185
+ c.ui.push(id);
186
+ },
187
+ gamepads: (pads) => {
188
+ if (capturePads && !samePads(lastPads, pads, padsWritten)) {
189
+ lastPads = snapshotPads(pads);
190
+ padsWritten = true;
191
+ open().g = lastPads;
192
+ }
193
+ rec.tick();
194
+ return pads;
195
+ },
196
+ };
197
+ const rec = {
198
+ tick() {
199
+ if (cur) {
200
+ recording.ticks.push(cur);
201
+ cur = null;
202
+ }
203
+ else {
204
+ const last = recording.ticks[recording.ticks.length - 1];
205
+ if (last && isRun(last) && last.t + last.n === t)
206
+ last.n++;
207
+ else
208
+ recording.ticks.push({ t, n: 1 });
209
+ }
210
+ t++;
211
+ const ms = measure ? (clock() - start) / t : input.tickMs;
212
+ if (ms > 0 && Number.isFinite(ms))
213
+ recording.tickMs = ms;
214
+ },
215
+ stop() {
216
+ remove();
217
+ if (input.recorder === rec)
218
+ input.recorder = null;
219
+ return recording;
220
+ },
221
+ get recording() {
222
+ return recording;
223
+ },
224
+ get ticks() {
225
+ return t;
226
+ },
227
+ };
228
+ const remove = input.onFeed(hook);
229
+ input.recorder = rec;
230
+ return rec;
231
+ }
232
+ /** Button value as recorded: `pressed` counts as 1, as `Input.evaluate` reads it. */
233
+ function buttonValue(b) {
234
+ return b.pressed ? Math.max(1, b.value) : b.value;
235
+ }
236
+ /**
237
+ * True when the live pads equal the snapshot. Before any snapshot is written the implied state
238
+ * is "no pad connected", so a page whose `navigator.getGamepads()` is four empty slots records
239
+ * nothing. Allocation-free.
240
+ */
241
+ function samePads(snap, pads, written) {
242
+ if (!written) {
243
+ for (const p of pads)
244
+ if (p && p.connected !== false)
245
+ return false;
246
+ return true;
247
+ }
248
+ if (snap.length !== pads.length)
249
+ return false;
250
+ for (let i = 0; i < pads.length; i++) {
251
+ const p = pads[i];
252
+ const s = snap[i];
253
+ const live = p && p.connected !== false ? p : null;
254
+ if (!live || !s) {
255
+ if (live || s)
256
+ return false;
257
+ continue;
258
+ }
259
+ if (s.buttons.length !== live.buttons.length || s.axes.length !== live.axes.length)
260
+ return false;
261
+ for (let j = 0; j < live.buttons.length; j++) {
262
+ if (s.buttons[j] !== buttonValue(live.buttons[j]))
263
+ return false;
264
+ }
265
+ for (let j = 0; j < live.axes.length; j++)
266
+ if (s.axes[j] !== live.axes[j])
267
+ return false;
268
+ }
269
+ return true;
270
+ }
271
+ function snapshotPads(pads) {
272
+ const out = [];
273
+ for (const p of pads) {
274
+ if (!p || p.connected === false)
275
+ out.push(null);
276
+ else
277
+ out.push({ buttons: p.buttons.map(buttonValue), axes: [...p.axes] });
278
+ }
279
+ return out;
280
+ }
281
+ // ---------------------------------------------------------------- playback
282
+ /**
283
+ * Replay `recording` into `input`. Call `step()` before each `input.update()`; the input's
284
+ * `getGamepads` result is replaced by the recorded snapshot while the playback is installed.
285
+ * `input.playback` points at it until `detach()`.
286
+ */
287
+ export function createInputPlayback(input, recording, opts = {}) {
288
+ const ticks = recording.ticks;
289
+ const length = recordingLength(recording);
290
+ let tick = 0;
291
+ /** Index into `ticks` of the entry covering `tick`. */
292
+ let index = 0;
293
+ let pads = [];
294
+ let speed = Math.max(1, Math.floor(opts.speed ?? 1));
295
+ /** Replayed pointers still down, cancelled on `seek`. */
296
+ const live = new Map();
297
+ const driven = opts.clock ?? null;
298
+ const clock = opts.now ?? (driven ? () => driven.now() : linkedClock(input));
299
+ const tickMs = positive(opts.tickMs) ?? positive(recording.tickMs) ?? input.tickMs;
300
+ /**
301
+ * Anchor at the first `step()` (ws/input-10) unless the clock is the wall clock, whose readings
302
+ * between steps follow the replay's frame rate rather than its ticks.
303
+ */
304
+ const anchorAtStep = opts.now !== undefined || driven !== null || !onWallClock(input);
305
+ /**
306
+ * The clock reading that recorded time 0 maps to. Off the wall clock it is set at the first
307
+ * `step()` (and the first after a `seek`): that reading less the fed tick's recorded start
308
+ * (`tick × tickMs`), so the first event keeps its recorded age however late the replay starts.
309
+ * On the wall clock, and wherever that anchor would put the first timed entry after the
310
+ * moment it is fed, the first timed entry sets it so that entry happens as it is fed (age 0),
311
+ * as before ws/input-10. `null` until then.
312
+ */
313
+ let base = null;
314
+ /** Set at creation and by `seek`: the next `step()` anchors `base`. */
315
+ let fresh = true;
316
+ /** Set with `fresh`: the next timed entry may re-anchor `base` (see above). */
317
+ let firstTimed = true;
318
+ const replayPointer = (e) => {
319
+ // Version 3 entries happen at their recorded offset from tick 0; older ones (and the
320
+ // cancels `seek` makes) when their tick is fed, so their timing is the replay's tick spacing.
321
+ const time = e[7];
322
+ let age = 0;
323
+ if (time !== undefined) {
324
+ const now = clock();
325
+ // An event cannot happen after it is handled: a step anchor that would say so (a
326
+ // recording made with the clock advanced before the events, or a frozen replay clock)
327
+ // gives way to the entry itself.
328
+ if (base === null || (firstTimed && now < base + time))
329
+ base = now - time;
330
+ firstTimed = false;
331
+ age = now - (base + time);
332
+ }
333
+ input.replayPointer(PHASES[e[0]], e[1], e[2], e[3], e[4], e[5], e[6] === 1, age);
334
+ if (e[0] === 0 || (e[0] === 1 && live.has(e[1])))
335
+ live.set(e[1], e);
336
+ else if (e[0] === 2 || e[0] === 3)
337
+ live.delete(e[1]);
338
+ };
339
+ const feedTick = () => {
340
+ // Advance the entry cursor to the one covering this tick.
341
+ while (index < ticks.length) {
342
+ const e = ticks[index];
343
+ if (tick < e.t + (isRun(e) ? e.n : 1))
344
+ break;
345
+ index++;
346
+ }
347
+ const e = ticks[index];
348
+ tick++;
349
+ if (!e || isRun(e) || e.t !== tick - 1)
350
+ return;
351
+ if (e.r)
352
+ input.releaseAll();
353
+ // Only `keyDown` and `pointerAt` set `lastDevice`, so their relative order is all that is
354
+ // kept: the pointer goes first when a key came down after it (`d`), last otherwise.
355
+ if (e.d && e.p)
356
+ input.pointerAt(e.p[0], e.p[1], e.p[2] ?? 'mouse');
357
+ if (e.k) {
358
+ for (const [code, down] of e.k) {
359
+ if (down)
360
+ input.keyDown(code);
361
+ else
362
+ input.keyUp(code);
363
+ }
364
+ }
365
+ // The pointer moves before the buttons (ws/input-8), as a DOM pointer event sets the
366
+ // position before its button: an orbit look's drag then starts where the press was, not at
367
+ // the previous position.
368
+ if (e.p && !e.d)
369
+ input.pointerAt(e.p[0], e.p[1], e.p[2] ?? 'mouse');
370
+ if (e.b) {
371
+ for (const [button, down] of e.b) {
372
+ if (down)
373
+ input.buttonDown(button);
374
+ else
375
+ input.buttonUp(button);
376
+ }
377
+ }
378
+ if (e.w)
379
+ input.wheel(e.w[0], e.w[1]);
380
+ if (e.ptr)
381
+ for (const p of e.ptr)
382
+ replayPointer(p);
383
+ if (e.ui)
384
+ for (const id of e.ui)
385
+ input.replayControl(id);
386
+ if (e.g)
387
+ pads = e.g.map(padFromSnapshot);
388
+ };
389
+ const hook = {
390
+ keyDown: noop,
391
+ keyUp: noop,
392
+ buttonDown: noop,
393
+ buttonUp: noop,
394
+ wheel: noop,
395
+ pointerAt: noop,
396
+ releaseAll: noop,
397
+ padSource: () => pads,
398
+ gamepads: () => pads,
399
+ };
400
+ /** Feed one tick, then advance the driven clock past it, as a live fixed step does. */
401
+ const feedAndAdvance = () => {
402
+ feedTick();
403
+ driven?.advance(tickMs);
404
+ };
405
+ const pb = {
406
+ step() {
407
+ if (tick >= length)
408
+ return false;
409
+ if (fresh) {
410
+ fresh = false;
411
+ if (anchorAtStep)
412
+ base = clock() - tick * tickMs;
413
+ }
414
+ feedAndAdvance();
415
+ for (let i = 1; i < speed && tick < length; i++) {
416
+ input.update();
417
+ feedAndAdvance();
418
+ }
419
+ return true;
420
+ },
421
+ get done() {
422
+ return tick >= length;
423
+ },
424
+ get tick() {
425
+ return tick;
426
+ },
427
+ get length() {
428
+ return length;
429
+ },
430
+ seek(to) {
431
+ for (const e of [...live.values()])
432
+ replayPointer([3, e[1], e[2], e[3], e[4], e[5], e[6]]);
433
+ input.releaseAll();
434
+ tick = Math.max(0, Math.min(length, Math.floor(to)));
435
+ index = 0;
436
+ base = null;
437
+ fresh = true;
438
+ firstTimed = true;
439
+ // The pads in force at `to` are the last snapshot at or before it.
440
+ pads = [];
441
+ for (const e of ticks) {
442
+ if (e.t >= tick)
443
+ break;
444
+ if (!isRun(e) && e.g)
445
+ pads = e.g.map(padFromSnapshot);
446
+ }
447
+ },
448
+ get speed() {
449
+ return speed;
450
+ },
451
+ set speed(v) {
452
+ speed = Math.max(1, Math.floor(v));
453
+ },
454
+ clock: driven,
455
+ tickMs,
456
+ detach() {
457
+ remove();
458
+ if (input.playback === pb)
459
+ input.playback = null;
460
+ },
461
+ };
462
+ const remove = input.onFeed(hook);
463
+ input.playback = pb;
464
+ return pb;
465
+ }
466
+ function noop() { }
467
+ function positive(v) {
468
+ return v !== undefined && v > 0 && Number.isFinite(v) ? v : undefined;
469
+ }
470
+ function padFromSnapshot(s) {
471
+ if (!s)
472
+ return DISCONNECTED;
473
+ return {
474
+ connected: true,
475
+ buttons: s.buttons.map((v) => ({ pressed: v >= 1, value: v })),
476
+ axes: s.axes,
477
+ };
478
+ }
479
+ const DISCONNECTED = { connected: false, buttons: [], axes: [] };
480
+ // ---------------------------------------------------------------- JSON
481
+ /** The recording as a JSON string. */
482
+ export function serializeRecording(rec) {
483
+ return JSON.stringify(rec);
484
+ }
485
+ /**
486
+ * Parse and validate a recording (a JSON string or an already parsed value). Throws
487
+ * `InputRecordingError` on a wrong version or a malformed tick.
488
+ */
489
+ export function parseRecording(source) {
490
+ let v;
491
+ if (typeof source === 'string') {
492
+ try {
493
+ v = JSON.parse(source);
494
+ }
495
+ catch (err) {
496
+ throw new InputRecordingError(`not JSON: ${err instanceof Error ? err.message : String(err)}`);
497
+ }
498
+ }
499
+ else
500
+ v = source;
501
+ if (!isObject(v))
502
+ throw new InputRecordingError('recording is not an object');
503
+ const version = v.version;
504
+ if (version !== 1 && version !== 2 && version !== 3)
505
+ throw new InputRecordingError(`unsupported version ${String(v.version)}`);
506
+ if (!Array.isArray(v.ticks))
507
+ throw new InputRecordingError('ticks is not an array');
508
+ if (v.tickMs !== undefined &&
509
+ !(typeof v.tickMs === 'number' && v.tickMs > 0 && Number.isFinite(v.tickMs))) {
510
+ throw new InputRecordingError('bad tickMs');
511
+ }
512
+ let next = 0;
513
+ v.ticks.forEach((e, i) => {
514
+ if (!isObject(e) || typeof e.t !== 'number' || e.t !== next) {
515
+ throw new InputRecordingError(`tick ${i}: expected t ${next}`);
516
+ }
517
+ if ('n' in e) {
518
+ if (typeof e.n !== 'number' || e.n < 1 || !Number.isInteger(e.n)) {
519
+ throw new InputRecordingError(`tick ${i}: bad run count`);
520
+ }
521
+ next += e.n;
522
+ return;
523
+ }
524
+ next++;
525
+ if (e.k !== undefined && !isPairs(e.k, 'string'))
526
+ throw bad(i, 'k');
527
+ if (e.b !== undefined && !isPairs(e.b, 'number'))
528
+ throw bad(i, 'b');
529
+ if (e.p !== undefined && !isPointer(e.p))
530
+ throw bad(i, 'p');
531
+ if (e.w !== undefined && !isNumbers(e.w, 2))
532
+ throw bad(i, 'w');
533
+ if (e.r !== undefined && e.r !== 1)
534
+ throw bad(i, 'r');
535
+ if (e.d !== undefined && e.d !== 1)
536
+ throw bad(i, 'd');
537
+ if (e.g !== undefined && !(Array.isArray(e.g) && e.g.every(isPadSnapshot)))
538
+ throw bad(i, 'g');
539
+ if (e.rumble !== undefined && !(Array.isArray(e.rumble) && e.rumble.every(isRumble))) {
540
+ throw bad(i, 'rumble');
541
+ }
542
+ if (e.ui !== undefined && !(Array.isArray(e.ui) && e.ui.every((u) => typeof u === 'string'))) {
543
+ throw bad(i, 'ui');
544
+ }
545
+ if (version === 1)
546
+ return;
547
+ const timed = version === 3;
548
+ if (e.ptr !== undefined &&
549
+ !(Array.isArray(e.ptr) && e.ptr.every((p) => isPointerEntry(p, timed)))) {
550
+ throw bad(i, 'ptr');
551
+ }
552
+ if (e.cx !== undefined && !isPairs(e.cx, 'string'))
553
+ throw bad(i, 'cx');
554
+ if (e.cs !== undefined && !(Array.isArray(e.cs) && e.cs.every((a) => typeof a === 'string'))) {
555
+ throw bad(i, 'cs');
556
+ }
557
+ });
558
+ return v;
559
+ }
560
+ function bad(i, field) {
561
+ return new InputRecordingError(`tick ${i}: bad ${field}`);
562
+ }
563
+ function isObject(v) {
564
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
565
+ }
566
+ function isNumbers(v, n) {
567
+ return (Array.isArray(v) &&
568
+ (n === undefined || v.length === n) &&
569
+ v.every((x) => typeof x === 'number' && Number.isFinite(x)));
570
+ }
571
+ function isPairs(v, kind) {
572
+ return (Array.isArray(v) &&
573
+ v.every((e) => Array.isArray(e) && e.length === 2 && typeof e[0] === kind && (e[1] === 0 || e[1] === 1)));
574
+ }
575
+ function isPointer(v) {
576
+ if (!Array.isArray(v) || v.length < 2 || v.length > 3)
577
+ return false;
578
+ if (!isNumbers(v.slice(0, 2)))
579
+ return false;
580
+ return v.length === 2 || v[2] === 'mouse' || v[2] === 'touch' || v[2] === 'pen';
581
+ }
582
+ /** A `ptr` entry: 7 fields in version 2, 8 (with a finite `time`) in version 3. */
583
+ function isPointerEntry(v, timed) {
584
+ return (Array.isArray(v) &&
585
+ v.length === (timed ? 8 : 7) &&
586
+ (!timed || (typeof v[7] === 'number' && Number.isFinite(v[7]))) &&
587
+ Number.isInteger(v[0]) &&
588
+ v[0] >= 0 &&
589
+ v[0] <= 4 &&
590
+ (v[2] === 'mouse' || v[2] === 'touch' || v[2] === 'pen') &&
591
+ isNumbers([v[1], v[3], v[4], v[5]]) &&
592
+ (v[6] === 0 || v[6] === 1));
593
+ }
594
+ function isRumble(v) {
595
+ return Array.isArray(v) && (v.length === 3 || v.length === 4) && isNumbers(v);
596
+ }
597
+ function isPadSnapshot(v) {
598
+ if (v === null)
599
+ return true;
600
+ return isObject(v) && isNumbers(v.buttons) && isNumbers(v.axes);
601
+ }