@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,56 @@
1
+ import type { Host } from '../host/types.js';
2
+ import type { Migrations } from './migrate.js';
3
+ import type { Schema } from './schema.js';
4
+ import type { StorageLike } from './storage.js';
5
+ import { type SaveStore, type SlotMeta } from './store.js';
6
+ export interface SlotInfo {
7
+ /** 1-based slot number. */
8
+ slot: number;
9
+ label: string;
10
+ /** `savedAt` of the data in storage (ms). */
11
+ savedAt: number;
12
+ /** Version of the data in storage (before any migration `open` would run). */
13
+ version: number;
14
+ playMs?: number;
15
+ thumbnail?: string;
16
+ /** Length of the stored JSON text (UTF-16 code units). */
17
+ size: number;
18
+ }
19
+ export interface SlotManagerOptions<T> {
20
+ game: string;
21
+ version: number;
22
+ migrations?: Migrations;
23
+ defaults: () => T;
24
+ schema: Schema<T> | ((value: unknown) => value is T);
25
+ /** Number of slots, `1..slots`. Default 3. */
26
+ slots?: number;
27
+ host?: Pick<Host, 'storage'>;
28
+ storage?: StorageLike | null;
29
+ /** Fills `label`, `playMs` and `thumbnail` for the sidecar on every flush. */
30
+ meta?: (data: T) => SlotMeta;
31
+ /** Passed to each store. Default 250. */
32
+ debounceMs?: number;
33
+ autoFlush?: boolean;
34
+ now?: () => number;
35
+ }
36
+ export interface SlotManager<T> {
37
+ /** Number of slots. */
38
+ readonly slots: number;
39
+ /** Slots that hold data, in slot order, from the sidecars; no save data is parsed. */
40
+ list(): SlotInfo[];
41
+ /** The store for slot `n`; the same instance while it stays open. Throws outside `1..slots`. */
42
+ open(slot: number): SaveStore<T>;
43
+ /** Copies data and sidecar from one slot to another, flushing `from` first. False if `from` is empty. */
44
+ copy(from: number, to: number): boolean;
45
+ /** Removes data, sidecar and backup. An open store for the slot is reset to defaults. */
46
+ remove(slot: number): void;
47
+ /**
48
+ * Changes the label in the sidecar (writing one if the slot predates sidecars) and keeps it
49
+ * through later flushes of an open store unless `meta` returns its own label. False if empty.
50
+ */
51
+ rename(slot: number, label: string): boolean;
52
+ /** The slot with the latest `savedAt`, or null. */
53
+ mostRecent(): SlotInfo | null;
54
+ }
55
+ export declare function slotName(slot: number): string;
56
+ export declare function createSlotManager<T>(opts: SlotManagerOptions<T>): SlotManager<T>;
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Numbered save slots with a metadata sidecar, for a load/save menu.
3
+ *
4
+ * Slot `n` (1-based) is the store `thunderclap:<game>:slot<n>`; its sidecar `<key>:meta`
5
+ * (`StoredMeta`) is written in the same flush as the data, so `list()` reads only sidecars and
6
+ * never parses save data. Slots saved before the sidecar existed are listed from the data key's
7
+ * `v` and `t`.
8
+ */
9
+ import { defaultHost } from '../host/default.js';
10
+ import { isEnvelope } from './codec.js';
11
+ import { createSaveStore, saveKey } from './store.js';
12
+ export function slotName(slot) {
13
+ return `slot${slot}`;
14
+ }
15
+ function readMeta(storage, key) {
16
+ const raw = storage.getItem(`${key}:meta`);
17
+ if (raw !== null) {
18
+ try {
19
+ const m = JSON.parse(raw);
20
+ if (typeof m === 'object' &&
21
+ m !== null &&
22
+ typeof m.v === 'number' &&
23
+ typeof m.t === 'number' &&
24
+ typeof m.size === 'number')
25
+ return m;
26
+ }
27
+ catch {
28
+ // Fall through to the data key.
29
+ }
30
+ }
31
+ const data = storage.getItem(key);
32
+ if (data === null)
33
+ return null;
34
+ try {
35
+ const env = JSON.parse(data);
36
+ if (!isEnvelope(env))
37
+ return null;
38
+ return { v: env.v, t: env.t, size: data.length };
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ export function createSlotManager(opts) {
45
+ const count = opts.slots ?? 3;
46
+ if (!Number.isInteger(count) || count < 1)
47
+ throw new Error('slots must be an integer ≥ 1');
48
+ const userMeta = opts.meta ?? (() => ({}));
49
+ /** Labels set by `rename`, so an open store's next flush keeps them. */
50
+ const labels = new Map();
51
+ const metaFor = (slot) => (data) => {
52
+ const m = userMeta(data);
53
+ const label = labels.get(slot);
54
+ return label !== undefined && m.label === undefined ? { ...m, label } : m;
55
+ };
56
+ const source = opts.storage === undefined ? (opts.host ?? defaultHost()).storage : null;
57
+ const storageNow = () => (source ? source.open() : (opts.storage ?? null));
58
+ const open = new Map();
59
+ const check = (slot) => {
60
+ if (!Number.isInteger(slot) || slot < 1 || slot > count)
61
+ throw new RangeError(`slot ${slot} is outside 1..${count}`);
62
+ return saveKey(opts.game, slotName(slot));
63
+ };
64
+ const info = (storage, slot) => {
65
+ let m;
66
+ try {
67
+ m = readMeta(storage, check(slot));
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ if (!m)
73
+ return null;
74
+ const out = {
75
+ slot,
76
+ label: m.label ?? `Slot ${slot}`,
77
+ savedAt: m.t,
78
+ version: m.v,
79
+ size: m.size,
80
+ };
81
+ if (m.playMs !== undefined)
82
+ out.playMs = m.playMs;
83
+ if (m.thumbnail !== undefined)
84
+ out.thumbnail = m.thumbnail;
85
+ return out;
86
+ };
87
+ const list = () => {
88
+ const storage = storageNow();
89
+ if (!storage)
90
+ return [];
91
+ const out = [];
92
+ for (let n = 1; n <= count; n++) {
93
+ const i = info(storage, n);
94
+ if (i)
95
+ out.push(i);
96
+ }
97
+ return out;
98
+ };
99
+ return {
100
+ slots: count,
101
+ list,
102
+ open(slot) {
103
+ const key = check(slot);
104
+ let store = open.get(slot);
105
+ if (store)
106
+ return store;
107
+ store = createSaveStore({
108
+ game: opts.game,
109
+ slot: slotName(slot),
110
+ version: opts.version,
111
+ migrations: opts.migrations,
112
+ defaults: opts.defaults,
113
+ schema: opts.schema,
114
+ debounceMs: opts.debounceMs,
115
+ host: opts.host,
116
+ storage: opts.storage,
117
+ autoFlush: opts.autoFlush,
118
+ now: opts.now,
119
+ meta: metaFor(slot),
120
+ });
121
+ if (store.key !== key)
122
+ throw new Error('slot key mismatch');
123
+ open.set(slot, store);
124
+ return store;
125
+ },
126
+ copy(from, to) {
127
+ const fromKey = check(from);
128
+ const toKey = check(to);
129
+ if (from === to)
130
+ return false;
131
+ open.get(from)?.flush();
132
+ const storage = storageNow();
133
+ if (!storage)
134
+ return false;
135
+ try {
136
+ const data = storage.getItem(fromKey);
137
+ if (data === null)
138
+ return false;
139
+ const target = open.get(to);
140
+ if (target) {
141
+ target.dispose();
142
+ open.delete(to);
143
+ }
144
+ storage.setItem(toKey, data);
145
+ labels.delete(to);
146
+ const m = storage.getItem(`${fromKey}:meta`);
147
+ if (m !== null)
148
+ storage.setItem(`${toKey}:meta`, m);
149
+ else
150
+ storage.removeItem(`${toKey}:meta`);
151
+ return true;
152
+ }
153
+ catch {
154
+ return false;
155
+ }
156
+ },
157
+ remove(slot) {
158
+ const key = check(slot);
159
+ const store = open.get(slot);
160
+ if (store)
161
+ store.clear();
162
+ labels.delete(slot);
163
+ const storage = storageNow();
164
+ if (!storage)
165
+ return;
166
+ try {
167
+ storage.removeItem(key);
168
+ storage.removeItem(`${key}:meta`);
169
+ storage.removeItem(`${key}:backup`);
170
+ }
171
+ catch {
172
+ // Nothing to do: the slot is unreadable anyway.
173
+ }
174
+ },
175
+ rename(slot, label) {
176
+ const key = check(slot);
177
+ const storage = storageNow();
178
+ if (!storage)
179
+ return false;
180
+ try {
181
+ const m = readMeta(storage, key);
182
+ if (!m)
183
+ return false;
184
+ storage.setItem(`${key}:meta`, JSON.stringify({ ...m, label }));
185
+ labels.set(slot, label);
186
+ return true;
187
+ }
188
+ catch {
189
+ return false;
190
+ }
191
+ },
192
+ mostRecent() {
193
+ let best = null;
194
+ for (const i of list())
195
+ if (!best || i.savedAt > best.savedAt)
196
+ best = i;
197
+ return best;
198
+ },
199
+ };
200
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Storage backends. Web storage can be missing, throw on access (sandboxed or
3
+ * cross-origin iframes with third-party storage blocked), throw on write (quota,
4
+ * Safari private mode), or be silently partitioned. Everything here is defensive.
5
+ * The real backend comes from the host (`Host.storage`, engine/host); the web host
6
+ * probes `localStorage` with `probeStorage`.
7
+ */
8
+ /** The subset of the Web Storage API the save module uses. */
9
+ export interface StorageLike {
10
+ getItem(key: string): string | null;
11
+ setItem(key: string, value: string): void;
12
+ removeItem(key: string): void;
13
+ readonly length: number;
14
+ key(index: number): string | null;
15
+ }
16
+ /** In-memory `StorageLike`. Used as the fallback and in tests. */
17
+ export declare class MemoryStorage implements StorageLike {
18
+ private readonly map;
19
+ get length(): number;
20
+ key(index: number): string | null;
21
+ getItem(key: string): string | null;
22
+ setItem(key: string, value: string): void;
23
+ removeItem(key: string): void;
24
+ clear(): void;
25
+ }
26
+ /**
27
+ * Returns the storage `get` yields if it works, or `null` if it is unavailable,
28
+ * throws, or cannot round-trip a value. Never throws.
29
+ *
30
+ * @param get how to obtain the storage. Merely reading `window.localStorage`
31
+ * throws a SecurityError in some iframes, so the getter itself is guarded.
32
+ */
33
+ export declare function probeStorage(get: () => StorageLike | undefined | null): StorageLike | null;
34
+ /** True if `err` looks like a storage quota error across browsers. */
35
+ export declare function isQuotaError(err: unknown): boolean;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Storage backends. Web storage can be missing, throw on access (sandboxed or
3
+ * cross-origin iframes with third-party storage blocked), throw on write (quota,
4
+ * Safari private mode), or be silently partitioned. Everything here is defensive.
5
+ * The real backend comes from the host (`Host.storage`, engine/host); the web host
6
+ * probes `localStorage` with `probeStorage`.
7
+ */
8
+ /** In-memory `StorageLike`. Used as the fallback and in tests. */
9
+ export class MemoryStorage {
10
+ map = new Map();
11
+ get length() {
12
+ return this.map.size;
13
+ }
14
+ key(index) {
15
+ return [...this.map.keys()][index] ?? null;
16
+ }
17
+ getItem(key) {
18
+ return this.map.get(key) ?? null;
19
+ }
20
+ setItem(key, value) {
21
+ this.map.set(key, String(value));
22
+ }
23
+ removeItem(key) {
24
+ this.map.delete(key);
25
+ }
26
+ clear() {
27
+ this.map.clear();
28
+ }
29
+ }
30
+ const PROBE_KEY = 'thunderclap:__probe__';
31
+ /**
32
+ * Returns the storage `get` yields if it works, or `null` if it is unavailable,
33
+ * throws, or cannot round-trip a value. Never throws.
34
+ *
35
+ * @param get how to obtain the storage. Merely reading `window.localStorage`
36
+ * throws a SecurityError in some iframes, so the getter itself is guarded.
37
+ */
38
+ export function probeStorage(get) {
39
+ try {
40
+ const storage = get();
41
+ if (!storage)
42
+ return null;
43
+ const token = String(Date.now());
44
+ storage.setItem(PROBE_KEY, token);
45
+ const ok = storage.getItem(PROBE_KEY) === token;
46
+ storage.removeItem(PROBE_KEY);
47
+ return ok ? storage : null;
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ /** True if `err` looks like a storage quota error across browsers. */
54
+ export function isQuotaError(err) {
55
+ if (!(err instanceof Error) && !(typeof err === 'object' && err !== null))
56
+ return false;
57
+ const e = err;
58
+ return (e.name === 'QuotaExceededError' ||
59
+ e.name === 'NS_ERROR_DOM_QUOTA_REACHED' ||
60
+ e.code === 22 ||
61
+ e.code === 1014);
62
+ }
@@ -0,0 +1,114 @@
1
+ import type { Host } from '../host/types.js';
2
+ import { type Migrations } from './migrate.js';
3
+ import type { Schema } from './schema.js';
4
+ import { type StorageLike } from './storage.js';
5
+ /** What a slot menu shows without loading the slot; filled by `SaveStoreOptions.meta`. */
6
+ export interface SlotMeta {
7
+ /** Shown in the slot list. Default `Slot <n>` in a slot manager. */
8
+ label?: string;
9
+ /** Play time in ms. */
10
+ playMs?: number;
11
+ /** A small image for the menu (a data URL or a game-defined id). Keep it short: it is stored. */
12
+ thumbnail?: string;
13
+ }
14
+ /** The sidecar at `<key>:meta`, written in the same flush as the data. */
15
+ export interface StoredMeta extends SlotMeta {
16
+ v: number;
17
+ t: number;
18
+ /** Length of the stored JSON text (UTF-16 code units, what web storage quotas count). */
19
+ size: number;
20
+ }
21
+ /** `thunderclap:<game>:<slot>` */
22
+ export declare function saveKey(game: string, slot: string): string;
23
+ /** Slot names that currently have data for `game` (excludes backups). */
24
+ export declare function listSlots(game: string, storage?: StorageLike | null): string[];
25
+ /**
26
+ * How the initial load went:
27
+ * - `fresh`: nothing stored; defaults used.
28
+ * - `loaded`: stored data at the current version.
29
+ * - `migrated`: stored data upgraded from an older version (written back on next flush).
30
+ * - `recovered`: stored data was unreadable (corrupt, invalid, newer build, failed migration);
31
+ * the raw value was copied to `<key>:backup` and defaults were used. See `status.error`.
32
+ */
33
+ export type LoadResult = 'fresh' | 'loaded' | 'migrated' | 'recovered';
34
+ export interface SaveStatus {
35
+ /** True when the last read/write reached real storage. False means memory only: warn the player. */
36
+ persistent: boolean;
37
+ loadResult: LoadResult;
38
+ /** Most recent problem (load, write or import), or null. */
39
+ error: string | null;
40
+ /** True while a debounced write is pending. */
41
+ dirty: boolean;
42
+ }
43
+ export interface SaveStoreOptions<T> {
44
+ /** Game id, e.g. `my-game`. Letters, digits, `-`, `_`. */
45
+ game: string;
46
+ /** Slot name. Default `main`. */
47
+ slot?: string;
48
+ /** Current data version (integer ≥ 1). */
49
+ version: number;
50
+ /** `migrations[n]` upgrades data from v`n` to v`n+1`. Must cover 1 → version. */
51
+ migrations?: Migrations;
52
+ /** Fresh data for a new player. Called whenever defaults are needed. */
53
+ defaults: () => T;
54
+ /** Runtime shape check applied after migration, on `set`, and on import. */
55
+ schema: Schema<T> | ((value: unknown) => value is T);
56
+ /** Debounce for writes, ms. Default 250. `0` writes synchronously on every `set`. */
57
+ debounceMs?: number;
58
+ /**
59
+ * Where the storage comes from: `host.storage.open()`, re-tried on each write while it is
60
+ * unavailable. Default: `defaultHost()` (the web host's `localStorage`).
61
+ */
62
+ host?: Pick<Host, 'storage'>;
63
+ /**
64
+ * A fixed backing storage instead of the host's. Pass `null` to force memory only.
65
+ * Tests pass a `MemoryStorage` or a throwing stub.
66
+ */
67
+ storage?: StorageLike | null;
68
+ /** Flush on `pagehide` / hidden `visibilitychange`. Default true when `window` exists. */
69
+ autoFlush?: boolean;
70
+ /** Clock for `savedAt`. Default `Date.now`. */
71
+ now?: () => number;
72
+ /**
73
+ * When set, every flush also writes `<key>:meta` (`StoredMeta`: version, time, size and what
74
+ * this returns) so a slot menu can list slots without loading them. A failed meta write is
75
+ * not an error for the data. Slot managers set it; plain stores leave it out.
76
+ */
77
+ meta?: (data: T) => SlotMeta;
78
+ }
79
+ export type ImportResult = {
80
+ ok: true;
81
+ migrated: boolean;
82
+ } | {
83
+ ok: false;
84
+ error: string;
85
+ };
86
+ export interface SaveStore<T> {
87
+ readonly key: string;
88
+ /** Shorthand for `status.persistent`. */
89
+ readonly persistent: boolean;
90
+ readonly status: Readonly<SaveStatus>;
91
+ /** Timestamp of the data currently held (ms), or 0 if never saved. */
92
+ readonly savedAt: number;
93
+ /** Current data. Treat as read-only; change it via `set` or `update`. */
94
+ get(): T;
95
+ /** Replace the data and schedule a write. Returns false (and records `error`) if it fails the schema. */
96
+ set(data: T): boolean;
97
+ /** Mutate a structured clone of the data (or return a replacement), validate, schedule a write. */
98
+ update(fn: (draft: T) => T | undefined): boolean;
99
+ /** Write now if dirty. Returns `status.persistent`. */
100
+ flush(): boolean;
101
+ /** Replace with defaults and write. */
102
+ reset(): void;
103
+ /** Remove the stored value (and backup); in-memory data becomes defaults. */
104
+ clear(): void;
105
+ /** Portable string for the player to copy. Includes pending changes. */
106
+ exportString(): string;
107
+ /** Validate, migrate and adopt a string from `exportString`. Writes immediately on success. */
108
+ importString(text: string): ImportResult;
109
+ /** Called after every status or data change. Returns an unsubscribe function. */
110
+ subscribe(fn: (status: Readonly<SaveStatus>) => void): () => void;
111
+ /** Flush and remove listeners. */
112
+ dispose(): void;
113
+ }
114
+ export declare function createSaveStore<T>(opts: SaveStoreOptions<T>): SaveStore<T>;