rn-gamekit 0.1.0 → 0.2.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 (601) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +95 -14
  3. package/lib/module/assets/defineAssets.js +28 -3
  4. package/lib/module/assets/defineAssets.js.map +1 -1
  5. package/lib/module/assets.js +11 -0
  6. package/lib/module/assets.js.map +1 -0
  7. package/lib/module/audio/createGameAudio.js +784 -0
  8. package/lib/module/audio/createGameAudio.js.map +1 -0
  9. package/lib/module/audio/errors.js +12 -0
  10. package/lib/module/audio/errors.js.map +1 -0
  11. package/lib/module/audio/index.js +5 -0
  12. package/lib/module/audio/index.js.map +1 -0
  13. package/lib/module/audio/resolver.js +37 -0
  14. package/lib/module/audio/resolver.js.map +1 -0
  15. package/lib/module/audio/types.js +4 -0
  16. package/lib/module/audio/types.js.map +1 -0
  17. package/lib/module/audio.js +9 -0
  18. package/lib/module/audio.js.map +1 -0
  19. package/lib/module/camera2d/bounds.js +59 -0
  20. package/lib/module/camera2d/bounds.js.map +1 -0
  21. package/lib/module/camera2d/extents.js +25 -0
  22. package/lib/module/camera2d/extents.js.map +1 -0
  23. package/lib/module/camera2d/follow.js +138 -0
  24. package/lib/module/camera2d/follow.js.map +1 -0
  25. package/lib/module/camera2d/index.js +20 -0
  26. package/lib/module/camera2d/index.js.map +1 -0
  27. package/lib/module/camera2d/interpolation.js +98 -0
  28. package/lib/module/camera2d/interpolation.js.map +1 -0
  29. package/lib/module/camera2d/shake.js +85 -0
  30. package/lib/module/camera2d/shake.js.map +1 -0
  31. package/lib/module/camera2d/transform.js +151 -0
  32. package/lib/module/camera2d/transform.js.map +1 -0
  33. package/lib/module/camera2d/types.js +4 -0
  34. package/lib/module/camera2d/types.js.map +1 -0
  35. package/lib/module/camera2d/validation.js +98 -0
  36. package/lib/module/camera2d/validation.js.map +1 -0
  37. package/lib/module/camera2d/visibility.js +138 -0
  38. package/lib/module/camera2d/visibility.js.map +1 -0
  39. package/lib/module/camera2d.js +9 -0
  40. package/lib/module/camera2d.js.map +1 -0
  41. package/lib/module/collision2d/colliders.js +266 -0
  42. package/lib/module/collision2d/colliders.js.map +1 -0
  43. package/lib/module/collision2d/debug.js +105 -0
  44. package/lib/module/collision2d/debug.js.map +1 -0
  45. package/lib/module/collision2d/filters.js +40 -0
  46. package/lib/module/collision2d/filters.js.map +1 -0
  47. package/lib/module/collision2d/index.js +12 -0
  48. package/lib/module/collision2d/index.js.map +1 -0
  49. package/lib/module/collision2d/intersections.js +67 -0
  50. package/lib/module/collision2d/intersections.js.map +1 -0
  51. package/lib/module/collision2d/manifolds.js +218 -0
  52. package/lib/module/collision2d/manifolds.js.map +1 -0
  53. package/lib/module/collision2d/segments.js +187 -0
  54. package/lib/module/collision2d/segments.js.map +1 -0
  55. package/lib/module/collision2d/spatialHash.js +167 -0
  56. package/lib/module/collision2d/spatialHash.js.map +1 -0
  57. package/lib/module/collision2d/sweeps.js +255 -0
  58. package/lib/module/collision2d/sweeps.js.map +1 -0
  59. package/lib/module/collision2d.js +9 -0
  60. package/lib/module/collision2d.js.map +1 -0
  61. package/lib/module/core/input/buttonPad.js +214 -0
  62. package/lib/module/core/input/buttonPad.js.map +1 -0
  63. package/lib/module/core/input/createInputBuffer.js +66 -14
  64. package/lib/module/core/input/createInputBuffer.js.map +1 -1
  65. package/lib/module/core/session/createGameSession.js +454 -50
  66. package/lib/module/core/session/createGameSession.js.map +1 -1
  67. package/lib/module/core/session/deepFreeze.js +92 -2
  68. package/lib/module/core/session/deepFreeze.js.map +1 -1
  69. package/lib/module/core/session/types.js +12 -0
  70. package/lib/module/core/session/types.js.map +1 -1
  71. package/lib/module/definition/defineGame.js +23 -0
  72. package/lib/module/definition/defineGame.js.map +1 -1
  73. package/lib/module/events/defineGameEvents.js +46 -0
  74. package/lib/module/events/defineGameEvents.js.map +1 -0
  75. package/lib/module/events/errors.js +16 -0
  76. package/lib/module/events/errors.js.map +1 -0
  77. package/lib/module/events/index.js +7 -0
  78. package/lib/module/events/index.js.map +1 -0
  79. package/lib/module/events/payload.js +219 -0
  80. package/lib/module/events/payload.js.map +1 -0
  81. package/lib/module/events/seed.js +33 -0
  82. package/lib/module/events/seed.js.map +1 -0
  83. package/lib/module/events/types.js +4 -0
  84. package/lib/module/events/types.js.map +1 -0
  85. package/lib/module/events.js +13 -0
  86. package/lib/module/events.js.map +1 -0
  87. package/lib/module/geometry/helpers.js +140 -0
  88. package/lib/module/geometry/helpers.js.map +1 -0
  89. package/lib/module/geometry/index.js +5 -0
  90. package/lib/module/geometry/index.js.map +1 -0
  91. package/lib/module/geometry/validation.js +104 -0
  92. package/lib/module/geometry/validation.js.map +1 -0
  93. package/lib/module/geometry.js +9 -0
  94. package/lib/module/geometry.js.map +1 -0
  95. package/lib/module/haptics/createGameHaptics.js +214 -0
  96. package/lib/module/haptics/createGameHaptics.js.map +1 -0
  97. package/lib/module/haptics/errors.js +12 -0
  98. package/lib/module/haptics/errors.js.map +1 -0
  99. package/lib/module/haptics/index.js +5 -0
  100. package/lib/module/haptics/index.js.map +1 -0
  101. package/lib/module/haptics/resolver.js +37 -0
  102. package/lib/module/haptics/resolver.js.map +1 -0
  103. package/lib/module/haptics/types.js +4 -0
  104. package/lib/module/haptics/types.js.map +1 -0
  105. package/lib/module/haptics.js +9 -0
  106. package/lib/module/haptics.js.map +1 -0
  107. package/lib/module/index.js +8 -1
  108. package/lib/module/index.js.map +1 -1
  109. package/lib/module/particles/createParticleSystem.js +481 -0
  110. package/lib/module/particles/createParticleSystem.js.map +1 -0
  111. package/lib/module/particles/defineParticleEffect.js +178 -0
  112. package/lib/module/particles/defineParticleEffect.js.map +1 -0
  113. package/lib/module/particles/errors.js +9 -0
  114. package/lib/module/particles/errors.js.map +1 -0
  115. package/lib/module/particles/index.js +8 -0
  116. package/lib/module/particles/index.js.map +1 -0
  117. package/lib/module/particles/sampling.js +121 -0
  118. package/lib/module/particles/sampling.js.map +1 -0
  119. package/lib/module/particles/types.js +4 -0
  120. package/lib/module/particles/types.js.map +1 -0
  121. package/lib/module/particles.js +4 -0
  122. package/lib/module/particles.js.map +1 -0
  123. package/lib/module/react/GameButtonPad.js +344 -0
  124. package/lib/module/react/GameButtonPad.js.map +1 -0
  125. package/lib/module/react/GamePointerInput.js +74 -16
  126. package/lib/module/react/GamePointerInput.js.map +1 -1
  127. package/lib/module/react/GameView.js +139 -60
  128. package/lib/module/react/GameView.js.map +1 -1
  129. package/lib/module/react/assets/createGameAssetStore.js +145 -95
  130. package/lib/module/react/assets/createGameAssetStore.js.map +1 -1
  131. package/lib/module/react/assets/useGameAssets.js +60 -35
  132. package/lib/module/react/assets/useGameAssets.js.map +1 -1
  133. package/lib/module/react/bindAppLifecycle.js +46 -17
  134. package/lib/module/react/bindAppLifecycle.js.map +1 -1
  135. package/lib/module/react/bindGameSession.js +13 -2
  136. package/lib/module/react/bindGameSession.js.map +1 -1
  137. package/lib/module/react/camera2d/GameLayer2D.js +50 -0
  138. package/lib/module/react/camera2d/GameLayer2D.js.map +1 -0
  139. package/lib/module/react/camera2d/defineGameCamera2D.js +30 -0
  140. package/lib/module/react/camera2d/defineGameCamera2D.js.map +1 -0
  141. package/lib/module/react/camera2d/usePresentedCameraBinding.js +177 -0
  142. package/lib/module/react/camera2d/usePresentedCameraBinding.js.map +1 -0
  143. package/lib/module/react/cleanupList.js +38 -0
  144. package/lib/module/react/cleanupList.js.map +1 -0
  145. package/lib/module/react/lifecycleSource.js +49 -0
  146. package/lib/module/react/lifecycleSource.js.map +1 -0
  147. package/lib/module/react/particles/ParticleView.js +308 -0
  148. package/lib/module/react/particles/ParticleView.js.map +1 -0
  149. package/lib/module/react/particles/culling.js +115 -0
  150. package/lib/module/react/particles/culling.js.map +1 -0
  151. package/lib/module/react/particles/index.js +7 -0
  152. package/lib/module/react/particles/index.js.map +1 -0
  153. package/lib/module/react/particles/spriteXForm.js +45 -0
  154. package/lib/module/react/particles/spriteXForm.js.map +1 -0
  155. package/lib/module/react/particles/useParticlePresentation.js +204 -0
  156. package/lib/module/react/particles/useParticlePresentation.js.map +1 -0
  157. package/lib/module/react/pointerBinding.js +55 -17
  158. package/lib/module/react/pointerBinding.js.map +1 -1
  159. package/lib/module/react/pointerCamera.js +28 -0
  160. package/lib/module/react/pointerCamera.js.map +1 -0
  161. package/lib/module/react/pointerCoalescer.js +16 -9
  162. package/lib/module/react/pointerCoalescer.js.map +1 -1
  163. package/lib/module/react/sprites/GameSprite.js +5 -17
  164. package/lib/module/react/sprites/GameSprite.js.map +1 -1
  165. package/lib/module/react/sprites/GameWorld2D.js +112 -9
  166. package/lib/module/react/sprites/GameWorld2D.js.map +1 -1
  167. package/lib/module/react/sprites/Sprite.js +48 -63
  168. package/lib/module/react/sprites/Sprite.js.map +1 -1
  169. package/lib/module/react/sprites/SpriteBatch.js +53 -28
  170. package/lib/module/react/sprites/SpriteBatch.js.map +1 -1
  171. package/lib/module/react/sprites/batchVisibility.js +58 -0
  172. package/lib/module/react/sprites/batchVisibility.js.map +1 -0
  173. package/lib/module/react/sprites/spriteSelection.js +103 -0
  174. package/lib/module/react/sprites/spriteSelection.js.map +1 -0
  175. package/lib/module/react/sprites/spriteTransform.js +46 -25
  176. package/lib/module/react/sprites/spriteTransform.js.map +1 -1
  177. package/lib/module/react/tilemap/TileMapLayer2D.js +217 -0
  178. package/lib/module/react/tilemap/TileMapLayer2D.js.map +1 -0
  179. package/lib/module/react/tilemap/tilePresentation.js +374 -0
  180. package/lib/module/react/tilemap/tilePresentation.js.map +1 -0
  181. package/lib/module/react/useGameSession.js +70 -0
  182. package/lib/module/react/useGameSession.js.map +1 -0
  183. package/lib/module/react/useGameSessionStatus.js +46 -0
  184. package/lib/module/react/useGameSessionStatus.js.map +1 -0
  185. package/lib/module/react/viewportBinding.js +5 -1
  186. package/lib/module/react/viewportBinding.js.map +1 -1
  187. package/lib/module/react.js +12 -1
  188. package/lib/module/react.js.map +1 -1
  189. package/lib/module/scene/defineScene.js +17 -0
  190. package/lib/module/scene/defineScene.js.map +1 -1
  191. package/lib/module/sprites/sampleSpriteClip.js +66 -6
  192. package/lib/module/sprites/sampleSpriteClip.js.map +1 -1
  193. package/lib/module/sprites/spriteAnimationState.js +10 -20
  194. package/lib/module/sprites/spriteAnimationState.js.map +1 -1
  195. package/lib/module/sprites.js +11 -0
  196. package/lib/module/sprites.js.map +1 -0
  197. package/lib/module/storage/adapters/asyncStorage.js +57 -0
  198. package/lib/module/storage/adapters/asyncStorage.js.map +1 -0
  199. package/lib/module/storage/adapters/memory.js +50 -0
  200. package/lib/module/storage/adapters/memory.js.map +1 -0
  201. package/lib/module/storage/errors.js +34 -0
  202. package/lib/module/storage/errors.js.map +1 -0
  203. package/lib/module/storage/index.js +11 -0
  204. package/lib/module/storage/index.js.map +1 -0
  205. package/lib/module/storage/schema.js +151 -0
  206. package/lib/module/storage/schema.js.map +1 -0
  207. package/lib/module/storage/serialization.js +249 -0
  208. package/lib/module/storage/serialization.js.map +1 -0
  209. package/lib/module/storage/store.js +387 -0
  210. package/lib/module/storage/store.js.map +1 -0
  211. package/lib/module/storage/types.js +16 -0
  212. package/lib/module/storage/types.js.map +1 -0
  213. package/lib/module/storage/validation.js +111 -0
  214. package/lib/module/storage/validation.js.map +1 -0
  215. package/lib/module/storage.js +4 -0
  216. package/lib/module/storage.js.map +1 -0
  217. package/lib/module/testing.js +4 -0
  218. package/lib/module/testing.js.map +1 -1
  219. package/lib/module/tilemap/chunkStats.js +27 -0
  220. package/lib/module/tilemap/chunkStats.js.map +1 -0
  221. package/lib/module/tilemap/definitions.js +308 -0
  222. package/lib/module/tilemap/definitions.js.map +1 -0
  223. package/lib/module/tilemap/errors.js +13 -0
  224. package/lib/module/tilemap/errors.js.map +1 -0
  225. package/lib/module/tilemap/index.js +10 -0
  226. package/lib/module/tilemap/index.js.map +1 -0
  227. package/lib/module/tilemap/movement.js +379 -0
  228. package/lib/module/tilemap/movement.js.map +1 -0
  229. package/lib/module/tilemap/queries.js +114 -0
  230. package/lib/module/tilemap/queries.js.map +1 -0
  231. package/lib/module/tilemap/tiledAdapter.js +141 -0
  232. package/lib/module/tilemap/tiledAdapter.js.map +1 -0
  233. package/lib/module/tilemap/types.js +4 -0
  234. package/lib/module/tilemap/types.js.map +1 -0
  235. package/lib/module/tilemap.js +4 -0
  236. package/lib/module/tilemap.js.map +1 -0
  237. package/lib/typescript/src/assets/defineAssets.d.ts +1 -1
  238. package/lib/typescript/src/assets/defineAssets.d.ts.map +1 -1
  239. package/lib/typescript/src/assets.d.ts +11 -0
  240. package/lib/typescript/src/assets.d.ts.map +1 -0
  241. package/lib/typescript/src/audio/createGameAudio.d.ts +5 -0
  242. package/lib/typescript/src/audio/createGameAudio.d.ts.map +1 -0
  243. package/lib/typescript/src/audio/errors.d.ts +6 -0
  244. package/lib/typescript/src/audio/errors.d.ts.map +1 -0
  245. package/lib/typescript/src/audio/index.d.ts +4 -0
  246. package/lib/typescript/src/audio/index.d.ts.map +1 -0
  247. package/lib/typescript/src/audio/resolver.d.ts +44 -0
  248. package/lib/typescript/src/audio/resolver.d.ts.map +1 -0
  249. package/lib/typescript/src/audio/types.d.ts +42 -0
  250. package/lib/typescript/src/audio/types.d.ts.map +1 -0
  251. package/lib/typescript/src/audio.d.ts +8 -0
  252. package/lib/typescript/src/audio.d.ts.map +1 -0
  253. package/lib/typescript/src/camera2d/bounds.d.ts +25 -0
  254. package/lib/typescript/src/camera2d/bounds.d.ts.map +1 -0
  255. package/lib/typescript/src/camera2d/extents.d.ts +17 -0
  256. package/lib/typescript/src/camera2d/extents.d.ts.map +1 -0
  257. package/lib/typescript/src/camera2d/follow.d.ts +24 -0
  258. package/lib/typescript/src/camera2d/follow.d.ts.map +1 -0
  259. package/lib/typescript/src/camera2d/index.d.ts +19 -0
  260. package/lib/typescript/src/camera2d/index.d.ts.map +1 -0
  261. package/lib/typescript/src/camera2d/interpolation.d.ts +17 -0
  262. package/lib/typescript/src/camera2d/interpolation.d.ts.map +1 -0
  263. package/lib/typescript/src/camera2d/shake.d.ts +20 -0
  264. package/lib/typescript/src/camera2d/shake.d.ts.map +1 -0
  265. package/lib/typescript/src/camera2d/transform.d.ts +44 -0
  266. package/lib/typescript/src/camera2d/transform.d.ts.map +1 -0
  267. package/lib/typescript/src/camera2d/types.d.ts +74 -0
  268. package/lib/typescript/src/camera2d/types.d.ts.map +1 -0
  269. package/lib/typescript/src/camera2d/validation.d.ts +30 -0
  270. package/lib/typescript/src/camera2d/validation.d.ts.map +1 -0
  271. package/lib/typescript/src/camera2d/visibility.d.ts +47 -0
  272. package/lib/typescript/src/camera2d/visibility.d.ts.map +1 -0
  273. package/lib/typescript/src/camera2d.d.ts +7 -0
  274. package/lib/typescript/src/camera2d.d.ts.map +1 -0
  275. package/lib/typescript/src/collision2d/colliders.d.ts +120 -0
  276. package/lib/typescript/src/collision2d/colliders.d.ts.map +1 -0
  277. package/lib/typescript/src/collision2d/debug.d.ts +67 -0
  278. package/lib/typescript/src/collision2d/debug.d.ts.map +1 -0
  279. package/lib/typescript/src/collision2d/filters.d.ts +28 -0
  280. package/lib/typescript/src/collision2d/filters.d.ts.map +1 -0
  281. package/lib/typescript/src/collision2d/index.d.ts +17 -0
  282. package/lib/typescript/src/collision2d/index.d.ts.map +1 -0
  283. package/lib/typescript/src/collision2d/intersections.d.ts +24 -0
  284. package/lib/typescript/src/collision2d/intersections.d.ts.map +1 -0
  285. package/lib/typescript/src/collision2d/manifolds.d.ts +39 -0
  286. package/lib/typescript/src/collision2d/manifolds.d.ts.map +1 -0
  287. package/lib/typescript/src/collision2d/segments.d.ts +24 -0
  288. package/lib/typescript/src/collision2d/segments.d.ts.map +1 -0
  289. package/lib/typescript/src/collision2d/spatialHash.d.ts +50 -0
  290. package/lib/typescript/src/collision2d/spatialHash.d.ts.map +1 -0
  291. package/lib/typescript/src/collision2d/sweeps.d.ts +60 -0
  292. package/lib/typescript/src/collision2d/sweeps.d.ts.map +1 -0
  293. package/lib/typescript/src/collision2d.d.ts +7 -0
  294. package/lib/typescript/src/collision2d.d.ts.map +1 -0
  295. package/lib/typescript/src/core/input/buttonPad.d.ts +59 -0
  296. package/lib/typescript/src/core/input/buttonPad.d.ts.map +1 -0
  297. package/lib/typescript/src/core/input/createInputBuffer.d.ts +1 -1
  298. package/lib/typescript/src/core/input/createInputBuffer.d.ts.map +1 -1
  299. package/lib/typescript/src/core/input/types.d.ts +7 -0
  300. package/lib/typescript/src/core/input/types.d.ts.map +1 -1
  301. package/lib/typescript/src/core/session/createGameSession.d.ts +4 -2
  302. package/lib/typescript/src/core/session/createGameSession.d.ts.map +1 -1
  303. package/lib/typescript/src/core/session/deepFreeze.d.ts +21 -1
  304. package/lib/typescript/src/core/session/deepFreeze.d.ts.map +1 -1
  305. package/lib/typescript/src/core/session/diagnostics.d.ts +2 -0
  306. package/lib/typescript/src/core/session/diagnostics.d.ts.map +1 -1
  307. package/lib/typescript/src/core/session/types.d.ts +69 -4
  308. package/lib/typescript/src/core/session/types.d.ts.map +1 -1
  309. package/lib/typescript/src/definition/defineGame.d.ts +12 -1
  310. package/lib/typescript/src/definition/defineGame.d.ts.map +1 -1
  311. package/lib/typescript/src/definition/types.d.ts +10 -1
  312. package/lib/typescript/src/definition/types.d.ts.map +1 -1
  313. package/lib/typescript/src/events/defineGameEvents.d.ts +26 -0
  314. package/lib/typescript/src/events/defineGameEvents.d.ts.map +1 -0
  315. package/lib/typescript/src/events/errors.d.ts +12 -0
  316. package/lib/typescript/src/events/errors.d.ts.map +1 -0
  317. package/lib/typescript/src/events/index.d.ts +6 -0
  318. package/lib/typescript/src/events/index.d.ts.map +1 -0
  319. package/lib/typescript/src/events/payload.d.ts +21 -0
  320. package/lib/typescript/src/events/payload.d.ts.map +1 -0
  321. package/lib/typescript/src/events/seed.d.ts +3 -0
  322. package/lib/typescript/src/events/seed.d.ts.map +1 -0
  323. package/lib/typescript/src/events/types.d.ts +42 -0
  324. package/lib/typescript/src/events/types.d.ts.map +1 -0
  325. package/lib/typescript/src/events.d.ts +12 -0
  326. package/lib/typescript/src/events.d.ts.map +1 -0
  327. package/lib/typescript/src/geometry/helpers.d.ts +35 -0
  328. package/lib/typescript/src/geometry/helpers.d.ts.map +1 -0
  329. package/lib/typescript/src/geometry/index.d.ts +4 -0
  330. package/lib/typescript/src/geometry/index.d.ts.map +1 -0
  331. package/lib/typescript/src/geometry/types.d.ts +49 -0
  332. package/lib/typescript/src/geometry/types.d.ts.map +1 -1
  333. package/lib/typescript/src/geometry/validation.d.ts +44 -0
  334. package/lib/typescript/src/geometry/validation.d.ts.map +1 -0
  335. package/lib/typescript/src/geometry.d.ts +7 -0
  336. package/lib/typescript/src/geometry.d.ts.map +1 -0
  337. package/lib/typescript/src/haptics/createGameHaptics.d.ts +3 -0
  338. package/lib/typescript/src/haptics/createGameHaptics.d.ts.map +1 -0
  339. package/lib/typescript/src/haptics/errors.d.ts +6 -0
  340. package/lib/typescript/src/haptics/errors.d.ts.map +1 -0
  341. package/lib/typescript/src/haptics/index.d.ts +4 -0
  342. package/lib/typescript/src/haptics/index.d.ts.map +1 -0
  343. package/lib/typescript/src/haptics/resolver.d.ts +22 -0
  344. package/lib/typescript/src/haptics/resolver.d.ts.map +1 -0
  345. package/lib/typescript/src/haptics/types.d.ts +37 -0
  346. package/lib/typescript/src/haptics/types.d.ts.map +1 -0
  347. package/lib/typescript/src/haptics.d.ts +8 -0
  348. package/lib/typescript/src/haptics.d.ts.map +1 -0
  349. package/lib/typescript/src/index.d.ts +10 -2
  350. package/lib/typescript/src/index.d.ts.map +1 -1
  351. package/lib/typescript/src/particles/createParticleSystem.d.ts +5 -0
  352. package/lib/typescript/src/particles/createParticleSystem.d.ts.map +1 -0
  353. package/lib/typescript/src/particles/defineParticleEffect.d.ts +3 -0
  354. package/lib/typescript/src/particles/defineParticleEffect.d.ts.map +1 -0
  355. package/lib/typescript/src/particles/errors.d.ts +5 -0
  356. package/lib/typescript/src/particles/errors.d.ts.map +1 -0
  357. package/lib/typescript/src/particles/index.d.ts +6 -0
  358. package/lib/typescript/src/particles/index.d.ts.map +1 -0
  359. package/lib/typescript/src/particles/sampling.d.ts +54 -0
  360. package/lib/typescript/src/particles/sampling.d.ts.map +1 -0
  361. package/lib/typescript/src/particles/types.d.ts +292 -0
  362. package/lib/typescript/src/particles/types.d.ts.map +1 -0
  363. package/lib/typescript/src/particles.d.ts +2 -0
  364. package/lib/typescript/src/particles.d.ts.map +1 -0
  365. package/lib/typescript/src/react/GameButtonPad.d.ts +84 -0
  366. package/lib/typescript/src/react/GameButtonPad.d.ts.map +1 -0
  367. package/lib/typescript/src/react/GamePointerInput.d.ts.map +1 -1
  368. package/lib/typescript/src/react/GameView.d.ts +27 -1
  369. package/lib/typescript/src/react/GameView.d.ts.map +1 -1
  370. package/lib/typescript/src/react/assets/createGameAssetStore.d.ts.map +1 -1
  371. package/lib/typescript/src/react/assets/useGameAssets.d.ts.map +1 -1
  372. package/lib/typescript/src/react/bindAppLifecycle.d.ts +7 -1
  373. package/lib/typescript/src/react/bindAppLifecycle.d.ts.map +1 -1
  374. package/lib/typescript/src/react/bindGameSession.d.ts.map +1 -1
  375. package/lib/typescript/src/react/camera2d/GameLayer2D.d.ts +24 -0
  376. package/lib/typescript/src/react/camera2d/GameLayer2D.d.ts.map +1 -0
  377. package/lib/typescript/src/react/camera2d/defineGameCamera2D.d.ts +44 -0
  378. package/lib/typescript/src/react/camera2d/defineGameCamera2D.d.ts.map +1 -0
  379. package/lib/typescript/src/react/camera2d/usePresentedCameraBinding.d.ts +22 -0
  380. package/lib/typescript/src/react/camera2d/usePresentedCameraBinding.d.ts.map +1 -0
  381. package/lib/typescript/src/react/cleanupList.d.ts +21 -0
  382. package/lib/typescript/src/react/cleanupList.d.ts.map +1 -0
  383. package/lib/typescript/src/react/instrumentation.d.ts +33 -3
  384. package/lib/typescript/src/react/instrumentation.d.ts.map +1 -1
  385. package/lib/typescript/src/react/lifecycleSource.d.ts +21 -0
  386. package/lib/typescript/src/react/lifecycleSource.d.ts.map +1 -0
  387. package/lib/typescript/src/react/particles/ParticleView.d.ts +65 -0
  388. package/lib/typescript/src/react/particles/ParticleView.d.ts.map +1 -0
  389. package/lib/typescript/src/react/particles/culling.d.ts +70 -0
  390. package/lib/typescript/src/react/particles/culling.d.ts.map +1 -0
  391. package/lib/typescript/src/react/particles/index.d.ts +7 -0
  392. package/lib/typescript/src/react/particles/index.d.ts.map +1 -0
  393. package/lib/typescript/src/react/particles/spriteXForm.d.ts +28 -0
  394. package/lib/typescript/src/react/particles/spriteXForm.d.ts.map +1 -0
  395. package/lib/typescript/src/react/particles/useParticlePresentation.d.ts +48 -0
  396. package/lib/typescript/src/react/particles/useParticlePresentation.d.ts.map +1 -0
  397. package/lib/typescript/src/react/pointerBinding.d.ts +38 -8
  398. package/lib/typescript/src/react/pointerBinding.d.ts.map +1 -1
  399. package/lib/typescript/src/react/pointerCamera.d.ts +20 -0
  400. package/lib/typescript/src/react/pointerCamera.d.ts.map +1 -0
  401. package/lib/typescript/src/react/pointerCoalescer.d.ts +17 -1
  402. package/lib/typescript/src/react/pointerCoalescer.d.ts.map +1 -1
  403. package/lib/typescript/src/react/sprites/GameSprite.d.ts +3 -10
  404. package/lib/typescript/src/react/sprites/GameSprite.d.ts.map +1 -1
  405. package/lib/typescript/src/react/sprites/GameWorld2D.d.ts +51 -6
  406. package/lib/typescript/src/react/sprites/GameWorld2D.d.ts.map +1 -1
  407. package/lib/typescript/src/react/sprites/Sprite.d.ts.map +1 -1
  408. package/lib/typescript/src/react/sprites/SpriteBatch.d.ts +22 -1
  409. package/lib/typescript/src/react/sprites/SpriteBatch.d.ts.map +1 -1
  410. package/lib/typescript/src/react/sprites/batchVisibility.d.ts +28 -0
  411. package/lib/typescript/src/react/sprites/batchVisibility.d.ts.map +1 -0
  412. package/lib/typescript/src/react/sprites/spriteSelection.d.ts +58 -0
  413. package/lib/typescript/src/react/sprites/spriteSelection.d.ts.map +1 -0
  414. package/lib/typescript/src/react/sprites/spriteTransform.d.ts +27 -12
  415. package/lib/typescript/src/react/sprites/spriteTransform.d.ts.map +1 -1
  416. package/lib/typescript/src/react/tilemap/TileMapLayer2D.d.ts +69 -0
  417. package/lib/typescript/src/react/tilemap/TileMapLayer2D.d.ts.map +1 -0
  418. package/lib/typescript/src/react/tilemap/tilePresentation.d.ts +217 -0
  419. package/lib/typescript/src/react/tilemap/tilePresentation.d.ts.map +1 -0
  420. package/lib/typescript/src/react/useGameSession.d.ts +48 -0
  421. package/lib/typescript/src/react/useGameSession.d.ts.map +1 -0
  422. package/lib/typescript/src/react/useGameSessionStatus.d.ts +23 -0
  423. package/lib/typescript/src/react/useGameSessionStatus.d.ts.map +1 -0
  424. package/lib/typescript/src/react/viewportBinding.d.ts +5 -1
  425. package/lib/typescript/src/react/viewportBinding.d.ts.map +1 -1
  426. package/lib/typescript/src/react.d.ts +18 -1
  427. package/lib/typescript/src/react.d.ts.map +1 -1
  428. package/lib/typescript/src/scene/defineScene.d.ts +22 -2
  429. package/lib/typescript/src/scene/defineScene.d.ts.map +1 -1
  430. package/lib/typescript/src/scene/types.d.ts +24 -4
  431. package/lib/typescript/src/scene/types.d.ts.map +1 -1
  432. package/lib/typescript/src/sprites/sampleSpriteClip.d.ts +26 -2
  433. package/lib/typescript/src/sprites/sampleSpriteClip.d.ts.map +1 -1
  434. package/lib/typescript/src/sprites/spriteAnimationState.d.ts +6 -7
  435. package/lib/typescript/src/sprites/spriteAnimationState.d.ts.map +1 -1
  436. package/lib/typescript/src/sprites.d.ts +10 -0
  437. package/lib/typescript/src/sprites.d.ts.map +1 -0
  438. package/lib/typescript/src/storage/adapters/asyncStorage.d.ts +18 -0
  439. package/lib/typescript/src/storage/adapters/asyncStorage.d.ts.map +1 -0
  440. package/lib/typescript/src/storage/adapters/memory.d.ts +16 -0
  441. package/lib/typescript/src/storage/adapters/memory.d.ts.map +1 -0
  442. package/lib/typescript/src/storage/errors.d.ts +37 -0
  443. package/lib/typescript/src/storage/errors.d.ts.map +1 -0
  444. package/lib/typescript/src/storage/index.d.ts +11 -0
  445. package/lib/typescript/src/storage/index.d.ts.map +1 -0
  446. package/lib/typescript/src/storage/schema.d.ts +22 -0
  447. package/lib/typescript/src/storage/schema.d.ts.map +1 -0
  448. package/lib/typescript/src/storage/serialization.d.ts +23 -0
  449. package/lib/typescript/src/storage/serialization.d.ts.map +1 -0
  450. package/lib/typescript/src/storage/store.d.ts +3 -0
  451. package/lib/typescript/src/storage/store.d.ts.map +1 -0
  452. package/lib/typescript/src/storage/types.d.ts +69 -0
  453. package/lib/typescript/src/storage/types.d.ts.map +1 -0
  454. package/lib/typescript/src/storage/validation.d.ts +24 -0
  455. package/lib/typescript/src/storage/validation.d.ts.map +1 -0
  456. package/lib/typescript/src/storage.d.ts +2 -0
  457. package/lib/typescript/src/storage.d.ts.map +1 -0
  458. package/lib/typescript/src/testing.d.ts +1 -0
  459. package/lib/typescript/src/testing.d.ts.map +1 -1
  460. package/lib/typescript/src/tilemap/chunkStats.d.ts +14 -0
  461. package/lib/typescript/src/tilemap/chunkStats.d.ts.map +1 -0
  462. package/lib/typescript/src/tilemap/definitions.d.ts +38 -0
  463. package/lib/typescript/src/tilemap/definitions.d.ts.map +1 -0
  464. package/lib/typescript/src/tilemap/errors.d.ts +7 -0
  465. package/lib/typescript/src/tilemap/errors.d.ts.map +1 -0
  466. package/lib/typescript/src/tilemap/index.d.ts +8 -0
  467. package/lib/typescript/src/tilemap/index.d.ts.map +1 -0
  468. package/lib/typescript/src/tilemap/movement.d.ts +52 -0
  469. package/lib/typescript/src/tilemap/movement.d.ts.map +1 -0
  470. package/lib/typescript/src/tilemap/queries.d.ts +21 -0
  471. package/lib/typescript/src/tilemap/queries.d.ts.map +1 -0
  472. package/lib/typescript/src/tilemap/tiledAdapter.d.ts +32 -0
  473. package/lib/typescript/src/tilemap/tiledAdapter.d.ts.map +1 -0
  474. package/lib/typescript/src/tilemap/types.d.ts +127 -0
  475. package/lib/typescript/src/tilemap/types.d.ts.map +1 -0
  476. package/lib/typescript/src/tilemap.d.ts +2 -0
  477. package/lib/typescript/src/tilemap.d.ts.map +1 -0
  478. package/package.json +94 -4
  479. package/src/assets/defineAssets.ts +31 -5
  480. package/src/assets.ts +27 -0
  481. package/src/audio/createGameAudio.ts +749 -0
  482. package/src/audio/errors.ts +12 -0
  483. package/src/audio/index.ts +9 -0
  484. package/src/audio/resolver.ts +74 -0
  485. package/src/audio/types.ts +47 -0
  486. package/src/audio.ts +13 -0
  487. package/src/camera2d/bounds.ts +69 -0
  488. package/src/camera2d/extents.ts +25 -0
  489. package/src/camera2d/follow.ts +165 -0
  490. package/src/camera2d/index.ts +29 -0
  491. package/src/camera2d/interpolation.ts +113 -0
  492. package/src/camera2d/shake.ts +90 -0
  493. package/src/camera2d/transform.ts +148 -0
  494. package/src/camera2d/types.ts +73 -0
  495. package/src/camera2d/validation.ts +126 -0
  496. package/src/camera2d/visibility.ts +181 -0
  497. package/src/camera2d.ts +6 -0
  498. package/src/collision2d/colliders.ts +292 -0
  499. package/src/collision2d/debug.ts +133 -0
  500. package/src/collision2d/filters.ts +48 -0
  501. package/src/collision2d/index.ts +74 -0
  502. package/src/collision2d/intersections.ts +82 -0
  503. package/src/collision2d/manifolds.ts +191 -0
  504. package/src/collision2d/segments.ts +176 -0
  505. package/src/collision2d/spatialHash.ts +211 -0
  506. package/src/collision2d/sweeps.ts +269 -0
  507. package/src/collision2d.ts +6 -0
  508. package/src/core/input/buttonPad.ts +235 -0
  509. package/src/core/input/createInputBuffer.ts +95 -14
  510. package/src/core/input/types.ts +7 -0
  511. package/src/core/session/createGameSession.ts +480 -53
  512. package/src/core/session/deepFreeze.ts +104 -3
  513. package/src/core/session/diagnostics.ts +2 -0
  514. package/src/core/session/types.ts +77 -4
  515. package/src/definition/defineGame.ts +61 -3
  516. package/src/definition/types.ts +10 -0
  517. package/src/events/defineGameEvents.ts +46 -0
  518. package/src/events/errors.ts +14 -0
  519. package/src/events/index.ts +14 -0
  520. package/src/events/payload.ts +234 -0
  521. package/src/events/seed.ts +33 -0
  522. package/src/events/types.ts +53 -0
  523. package/src/events.ts +20 -0
  524. package/src/geometry/helpers.ts +136 -0
  525. package/src/geometry/index.ts +14 -0
  526. package/src/geometry/types.ts +54 -0
  527. package/src/geometry/validation.ts +131 -0
  528. package/src/geometry.ts +6 -0
  529. package/src/haptics/createGameHaptics.ts +214 -0
  530. package/src/haptics/errors.ts +12 -0
  531. package/src/haptics/index.ts +3 -0
  532. package/src/haptics/resolver.ts +58 -0
  533. package/src/haptics/types.ts +48 -0
  534. package/src/haptics.ts +7 -0
  535. package/src/index.ts +37 -1
  536. package/src/particles/createParticleSystem.ts +505 -0
  537. package/src/particles/defineParticleEffect.ts +164 -0
  538. package/src/particles/errors.ts +6 -0
  539. package/src/particles/index.ts +5 -0
  540. package/src/particles/sampling.ts +141 -0
  541. package/src/particles/types.ts +327 -0
  542. package/src/particles.ts +1 -0
  543. package/src/react/GameButtonPad.tsx +436 -0
  544. package/src/react/GamePointerInput.tsx +73 -8
  545. package/src/react/GameView.tsx +160 -61
  546. package/src/react/assets/createGameAssetStore.ts +140 -107
  547. package/src/react/assets/useGameAssets.ts +63 -31
  548. package/src/react/bindAppLifecycle.ts +55 -19
  549. package/src/react/bindGameSession.ts +12 -2
  550. package/src/react/camera2d/GameLayer2D.tsx +43 -0
  551. package/src/react/camera2d/defineGameCamera2D.ts +59 -0
  552. package/src/react/camera2d/usePresentedCameraBinding.ts +185 -0
  553. package/src/react/cleanupList.ts +48 -0
  554. package/src/react/instrumentation.ts +31 -3
  555. package/src/react/lifecycleSource.ts +58 -0
  556. package/src/react/particles/ParticleView.tsx +358 -0
  557. package/src/react/particles/culling.ts +145 -0
  558. package/src/react/particles/index.ts +6 -0
  559. package/src/react/particles/spriteXForm.ts +72 -0
  560. package/src/react/particles/useParticlePresentation.ts +261 -0
  561. package/src/react/pointerBinding.ts +74 -16
  562. package/src/react/pointerCamera.ts +33 -0
  563. package/src/react/pointerCoalescer.ts +36 -10
  564. package/src/react/sprites/GameSprite.tsx +4 -33
  565. package/src/react/sprites/GameWorld2D.tsx +113 -7
  566. package/src/react/sprites/Sprite.tsx +51 -72
  567. package/src/react/sprites/SpriteBatch.tsx +74 -22
  568. package/src/react/sprites/batchVisibility.ts +76 -0
  569. package/src/react/sprites/spriteSelection.ts +133 -0
  570. package/src/react/sprites/spriteTransform.ts +46 -26
  571. package/src/react/tilemap/TileMapLayer2D.tsx +274 -0
  572. package/src/react/tilemap/tilePresentation.ts +491 -0
  573. package/src/react/useGameSession.ts +90 -0
  574. package/src/react/useGameSessionStatus.ts +53 -0
  575. package/src/react/viewportBinding.ts +5 -1
  576. package/src/react.ts +18 -1
  577. package/src/scene/defineScene.ts +47 -5
  578. package/src/scene/types.ts +37 -3
  579. package/src/sprites/sampleSpriteClip.ts +82 -14
  580. package/src/sprites/spriteAnimationState.ts +29 -25
  581. package/src/sprites.ts +22 -0
  582. package/src/storage/adapters/asyncStorage.ts +77 -0
  583. package/src/storage/adapters/memory.ts +58 -0
  584. package/src/storage/errors.ts +88 -0
  585. package/src/storage/index.ts +18 -0
  586. package/src/storage/schema.ts +147 -0
  587. package/src/storage/serialization.ts +248 -0
  588. package/src/storage/store.ts +380 -0
  589. package/src/storage/types.ts +76 -0
  590. package/src/storage/validation.ts +102 -0
  591. package/src/storage.ts +1 -0
  592. package/src/testing.ts +4 -0
  593. package/src/tilemap/chunkStats.ts +24 -0
  594. package/src/tilemap/definitions.ts +327 -0
  595. package/src/tilemap/errors.ts +11 -0
  596. package/src/tilemap/index.ts +10 -0
  597. package/src/tilemap/movement.ts +368 -0
  598. package/src/tilemap/queries.ts +136 -0
  599. package/src/tilemap/tiledAdapter.ts +165 -0
  600. package/src/tilemap/types.ts +119 -0
  601. package/src/tilemap.ts +1 -0
@@ -0,0 +1,784 @@
1
+ "use strict";
2
+
3
+ import { createAudioInstallationError, GameAudioError } from "./errors.js";
4
+ import { loadAudioApi } from "./resolver.js";
5
+ const CATEGORIES = ['master', 'music', 'sfx', 'ui'];
6
+ function isValidVolume(volume) {
7
+ return Number.isFinite(volume) && volume >= 0 && volume <= 1;
8
+ }
9
+ function assertCategory(category) {
10
+ if (!CATEGORIES.includes(category)) {
11
+ throw new GameAudioError(`Unknown audio category "${String(category)}"`);
12
+ }
13
+ }
14
+ function assertVolume(volume) {
15
+ if (!isValidVolume(volume)) {
16
+ throw new GameAudioError(`Volume must be a finite number in [0, 1], got ${String(volume)}`);
17
+ }
18
+ }
19
+
20
+ // GS-AUDIO-04: backend-global interruption observation is reference
21
+ // counted — the first live instance enables it, the last dispose disables
22
+ // it, so two instances can never disable each other's observation.
23
+ let interruptionObserverCount = 0;
24
+ let assetInputLoader = null;
25
+ export function __setAssetInputLoader(fn) {
26
+ assetInputLoader = fn;
27
+ }
28
+ export function __getAssetInputLoader() {
29
+ return assetInputLoader;
30
+ }
31
+ export async function createGameAudio(options) {
32
+ let api;
33
+ try {
34
+ api = await loadAudioApi();
35
+ } catch {
36
+ throw createAudioInstallationError();
37
+ }
38
+ if (!api || !api.AudioContext) {
39
+ throw createAudioInstallationError();
40
+ }
41
+ if (!options || typeof options.sounds !== 'object' || options.sounds === null) {
42
+ throw new GameAudioError('createGameAudio requires { sounds: Record<string, number> }');
43
+ }
44
+ const soundIds = Object.keys(options.sounds);
45
+ if (soundIds.length === 0) {
46
+ throw new GameAudioError('createGameAudio sounds must not be empty');
47
+ }
48
+ for (const id of soundIds) {
49
+ const v = options.sounds[id];
50
+ if (typeof v !== 'number' || !Number.isFinite(v)) {
51
+ throw new GameAudioError(`Sound "${id}" must be a finite asset ID (require result)`);
52
+ }
53
+ }
54
+ const {
55
+ AudioContext,
56
+ AudioManager
57
+ } = api;
58
+ let context = null;
59
+ let masterGain = null;
60
+ const categoryGains = {
61
+ master: null,
62
+ music: null,
63
+ sfx: null,
64
+ ui: null
65
+ };
66
+ let interruptionSub = null;
67
+ let interruptionEnabled = false;
68
+ let appStateSub = null;
69
+ let idleSuspendTimer = null;
70
+
71
+ // Create context in a transaction so failure cleans up
72
+ try {
73
+ context = new AudioContext();
74
+ } catch (e) {
75
+ throw e;
76
+ }
77
+ const volumes = {
78
+ master: 1,
79
+ music: 1,
80
+ sfx: 1,
81
+ ui: 1
82
+ };
83
+ let muted = false;
84
+ let disposed = false;
85
+ let userPaused = false;
86
+ let sessionPaused = false;
87
+ let appPaused = false;
88
+ let interruptionPaused = false;
89
+ let interruptionRequiresExplicitResume = false;
90
+ const bufferCache = new Map();
91
+ const pendingDecodes = new Map();
92
+ async function getBuffer(id) {
93
+ if (disposed) throw new GameAudioError('GameAudio is disposed');
94
+ if (bufferCache.has(id)) return bufferCache.get(id);
95
+ if (pendingDecodes.has(id)) return pendingDecodes.get(id);
96
+ const assetId = options.sounds[id];
97
+ const promise = (async () => {
98
+ let input;
99
+ if (assetInputLoader) {
100
+ input = await assetInputLoader(assetId);
101
+ } else {
102
+ let assetUri = null;
103
+ let expoAssetFailed = false;
104
+ try {
105
+ const {
106
+ Asset: ExpoAsset
107
+ } = await import('expo-asset');
108
+ const asset = ExpoAsset.fromModule(assetId);
109
+ await asset.downloadAsync();
110
+ assetUri = asset.localUri ?? asset.uri;
111
+ } catch {
112
+ expoAssetFailed = true;
113
+ }
114
+ if (assetUri) input = assetUri;else if (expoAssetFailed) input = assetId;else throw new GameAudioError(`Failed to resolve asset for sound "${String(id)}" — expo-asset returned no URI`);
115
+ }
116
+ let buffer;
117
+ try {
118
+ buffer = await context.decodeAudioData(input);
119
+ } catch (e) {
120
+ throw new GameAudioError(`Failed to decode audio asset "${String(id)}": ${e.message}`);
121
+ }
122
+ bufferCache.set(id, buffer);
123
+ pendingDecodes.delete(id);
124
+ return buffer;
125
+ })();
126
+ pendingDecodes.set(id, promise);
127
+ try {
128
+ return await promise;
129
+ } catch (e) {
130
+ pendingDecodes.delete(id);
131
+ throw e;
132
+ }
133
+ }
134
+ function applyGain(category) {
135
+ const gain = categoryGains[category];
136
+ if (!gain) return;
137
+ // F1: write only own volume; composition happens in graph (master * category)
138
+ const value = volumes[category];
139
+ try {
140
+ const param = gain.gain;
141
+ const now = context.currentTime ?? 0;
142
+ if (param.cancelScheduledValues) param.cancelScheduledValues(now);
143
+ if (param.setValueAtTime) param.setValueAtTime(param.value, now);
144
+ if (param.linearRampToValueAtTime) param.linearRampToValueAtTime(value, now + 0.02);else param.value = value;
145
+ } catch {
146
+ try {
147
+ gain.gain.value = value;
148
+ } catch {}
149
+ }
150
+ }
151
+ function applyAllGains() {
152
+ for (const c of CATEGORIES) applyGain(c);
153
+ }
154
+
155
+ // Transaction: gain graph plus eager decode, with cleanup on failure
156
+ // (F3, GS-AUDIO-03). Any failure closes the half-built context before
157
+ // rethrowing — init never returns a silent partial object.
158
+ try {
159
+ // Gain setup — master -> destination, categories -> master (F1).
160
+ // GS-AUDIO-03: the gain graph is REQUIRED setup. A failure throws
161
+ // transactionally (the init boundary closes the context and rethrows)
162
+ // instead of returning an apparently usable but silent object.
163
+ const mg = context.createGain?.();
164
+ if (!mg) {
165
+ throw new GameAudioError('createGameAudio requires a working channel gain graph (master createGain failed)');
166
+ }
167
+ masterGain = mg;
168
+ try {
169
+ mg.connect(context.destination);
170
+ } catch (e) {
171
+ throw new GameAudioError(`createGameAudio requires a working channel gain graph (master connect failed: ${e.message})`);
172
+ }
173
+ for (const cat of CATEGORIES) {
174
+ if (cat === 'master') {
175
+ categoryGains[cat] = mg;
176
+ continue;
177
+ }
178
+ const cg = context.createGain?.();
179
+ if (!cg) {
180
+ throw new GameAudioError(`createGameAudio requires a working channel gain graph (category ${cat} createGain failed)`);
181
+ }
182
+ categoryGains[cat] = cg;
183
+ try {
184
+ cg.connect(mg);
185
+ } catch (e) {
186
+ throw new GameAudioError(`createGameAudio requires a working channel gain graph (category ${cat} connect failed: ${e.message})`);
187
+ }
188
+ }
189
+ await Promise.all(soundIds.map(id => getBuffer(id)));
190
+ } catch (e) {
191
+ // Close context exactly once before rethrowing
192
+ try {
193
+ await context.close();
194
+ } catch {}
195
+ pendingDecodes.clear();
196
+ bufferCache.clear();
197
+ throw e;
198
+ }
199
+ let currentMusicId = null;
200
+ let currentMusicNode = null;
201
+ let musicGeneration = 0;
202
+ let activeMusicGeneration = 0;
203
+ let pendingMusic = null;
204
+ const activeVoices = new Set();
205
+ const concurrencyMap = new Map();
206
+ // GS-AUDIO-02: pending reservations are tracked distinctly from live
207
+ // voices. Only pending work takes cancellation tokens (removed when its
208
+ // continuation runs); live voices use normal stop/cleanup and lose all
209
+ // owner references immediately — never a token.
210
+ const pendingReservations = new Set();
211
+ const cancelledReservations = new Set();
212
+ function isEffectivelyPaused() {
213
+ return userPaused || sessionPaused || appPaused || interruptionPaused || muted;
214
+ }
215
+
216
+ // GS-AUDIO-04: serialized suspend/resume intents. Every pause-affecting
217
+ // call enqueues one link; each link re-reads the CURRENT effective pause
218
+ // state and converges the context to it, so rapid intent changes settle
219
+ // to the latest request instead of racing delayed native promises.
220
+ // Native calls never overlap: at most one suspend/resume is in flight.
221
+ let suspendChain = Promise.resolve();
222
+ async function runSuspendLink() {
223
+ if (disposed || !context) return;
224
+ if (isEffectivelyPaused()) {
225
+ if (idleSuspendTimer) {
226
+ clearTimeout(idleSuspendTimer);
227
+ idleSuspendTimer = null;
228
+ }
229
+ try {
230
+ await context.suspend();
231
+ } catch {}
232
+ return;
233
+ }
234
+ try {
235
+ const state = context.state;
236
+ if (state === 'suspended') {
237
+ await context.resume();
238
+ }
239
+ } catch {}
240
+ applyAllGains();
241
+ // If we have deferred music intent and now unpaused, start it (F4)
242
+ if (pendingMusic && !isEffectivelyPaused()) {
243
+ const {
244
+ id,
245
+ generation
246
+ } = pendingMusic;
247
+ pendingMusic = null;
248
+ void startMusicInternal(id, generation);
249
+ }
250
+ scheduleIdleSuspend();
251
+ }
252
+ function requestSuspendUpdate() {
253
+ suspendChain = suspendChain.then(runSuspendLink, runSuspendLink);
254
+ }
255
+ function updateSuspendState() {
256
+ requestSuspendUpdate();
257
+ }
258
+ function scheduleIdleSuspend() {
259
+ if (idleSuspendTimer) clearTimeout(idleSuspendTimer);
260
+ if (disposed || !context || isEffectivelyPaused()) return;
261
+ if (activeVoices.size === 0 && currentMusicNode === null && !pendingMusic) {
262
+ idleSuspendTimer = setTimeout(() => {
263
+ if (!disposed && context && activeVoices.size === 0 && currentMusicNode === null && !pendingMusic && !isEffectivelyPaused()) {
264
+ void context.suspend().catch(() => {});
265
+ }
266
+ }, 1500);
267
+ }
268
+ }
269
+
270
+ /** Drop one live voice: normal stop/cleanup with no token (GS-AUDIO-02). */
271
+ function dropVoice(voice, concurrencyKey) {
272
+ activeVoices.delete(voice);
273
+ if (concurrencyKey !== undefined) {
274
+ const set = concurrencyMap.get(concurrencyKey);
275
+ if (set) {
276
+ set.delete(voice);
277
+ if (set.size === 0) concurrencyMap.delete(concurrencyKey);
278
+ }
279
+ }
280
+ cancelledReservations.delete(voice);
281
+ scheduleIdleSuspend();
282
+ }
283
+
284
+ /** Drop one pending reservation from every collection that holds it. */
285
+ function dropReservation(reservation, concurrencyKey) {
286
+ pendingReservations.delete(reservation);
287
+ const set = concurrencyMap.get(concurrencyKey);
288
+ if (set) {
289
+ set.delete(reservation);
290
+ if (set.size === 0) concurrencyMap.delete(concurrencyKey);
291
+ }
292
+ cancelledReservations.delete(reservation);
293
+ }
294
+ const ensureNotDisposed = () => {
295
+ if (disposed) throw new GameAudioError('GameAudio is disposed');
296
+ };
297
+ function handleInterruption(event) {
298
+ const e = event;
299
+ if (e.type === 'began') {
300
+ interruptionPaused = true;
301
+ interruptionRequiresExplicitResume = false;
302
+ requestSuspendUpdate();
303
+ } else if (e.type === 'ended') {
304
+ if (e.shouldResume) {
305
+ if (interruptionRequiresExplicitResume) {
306
+ // Denied auto-resume persists until explicit user action (F2)
307
+ requestSuspendUpdate();
308
+ return;
309
+ }
310
+ interruptionPaused = false;
311
+ interruptionRequiresExplicitResume = false;
312
+ updateSuspendState();
313
+ } else {
314
+ // Platform says don't auto-resume: keep paused until explicit user action (F2)
315
+ interruptionPaused = true;
316
+ interruptionRequiresExplicitResume = true;
317
+ requestSuspendUpdate();
318
+ }
319
+ }
320
+ }
321
+ try {
322
+ // GS-AUDIO-03: interruption observation is explicitly optional. Without
323
+ // an AudioManager the service still plays, but warns once so the gap
324
+ // is visible instead of silently disappearing behind a no-op fallback.
325
+ if (AudioManager) {
326
+ if (interruptionObserverCount === 0) {
327
+ AudioManager.observeAudioInterruptions(true);
328
+ }
329
+ interruptionObserverCount++;
330
+ interruptionEnabled = true;
331
+ interruptionSub = AudioManager.addSystemEventListener('interruption', handleInterruption);
332
+ } else {
333
+ console.warn('[GameAudio] AudioManager unavailable — interruption observation disabled');
334
+ }
335
+ } catch {
336
+ interruptionSub = null;
337
+ }
338
+ try {
339
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
340
+ const RN = require('react-native');
341
+ const AppState = RN?.AppState;
342
+ if (AppState?.addEventListener) {
343
+ const isInactive = s => s === 'inactive' || s === 'background';
344
+ if (isInactive(AppState.currentState)) {
345
+ appPaused = true;
346
+ requestSuspendUpdate();
347
+ }
348
+ appStateSub = AppState.addEventListener('change', next => {
349
+ if (isInactive(next)) {
350
+ appPaused = true;
351
+ requestSuspendUpdate();
352
+ } else if (next === 'active') {
353
+ appPaused = false;
354
+ updateSuspendState();
355
+ }
356
+ });
357
+ }
358
+ } catch {}
359
+ applyAllGains();
360
+ // Initial idle suspend (F2): resource with no playback should suspend
361
+ scheduleIdleSuspend();
362
+ async function startMusicInternal(id, generation) {
363
+ if (disposed || !context) return;
364
+ if (isEffectivelyPaused()) {
365
+ // Defer until resume
366
+ pendingMusic = {
367
+ id,
368
+ generation
369
+ };
370
+ return;
371
+ }
372
+ if (generation !== musicGeneration) return;
373
+ try {
374
+ const buffer = await getBuffer(id);
375
+ if (disposed || !context) return;
376
+ if (generation !== musicGeneration) return;
377
+ if (isEffectivelyPaused()) {
378
+ pendingMusic = {
379
+ id,
380
+ generation
381
+ };
382
+ return;
383
+ }
384
+ if (currentMusicId !== id || activeMusicGeneration !== generation) {
385
+ // If another generation has taken over, don't start
386
+ if (generation !== musicGeneration) return;
387
+ }
388
+ const source = context.createBufferSource();
389
+ source.buffer = buffer;
390
+ source.loop = true;
391
+ const dest = categoryGains['music'] ?? masterGain ?? context.destination;
392
+ source.connect(dest);
393
+ // Stop previous
394
+ if (currentMusicNode) {
395
+ try {
396
+ currentMusicNode.stop();
397
+ } catch {}
398
+ }
399
+ currentMusicNode = source;
400
+ currentMusicId = id;
401
+ activeMusicGeneration = generation;
402
+ try {
403
+ source.start();
404
+ } catch (e) {
405
+ // GS-AUDIO-01: a failed music start must not wedge the music node —
406
+ // clear it so idle suspension and retries proceed, then report.
407
+ try {
408
+ source.disconnect?.();
409
+ } catch {}
410
+ if (currentMusicNode === source) {
411
+ currentMusicNode = null;
412
+ }
413
+ scheduleIdleSuspend();
414
+ throw e;
415
+ }
416
+ if (idleSuspendTimer) {
417
+ clearTimeout(idleSuspendTimer);
418
+ idleSuspendTimer = null;
419
+ }
420
+ const state = context.state;
421
+ if (state === 'suspended' && !isEffectivelyPaused()) await context.resume().catch(() => {});
422
+ } catch (e) {
423
+ if (generation === musicGeneration) {
424
+ console.warn(`[GameAudio] playMusic("${String(id)}") failed:`, e);
425
+ if (currentMusicId === id && activeMusicGeneration === generation) {
426
+ currentMusicId = null;
427
+ }
428
+ }
429
+ }
430
+ }
431
+ let lifecycleDetach = null;
432
+ const setSessionPaused = paused => {
433
+ sessionPaused = paused;
434
+ requestSuspendUpdate();
435
+ };
436
+ const audio = {
437
+ play(id, opts) {
438
+ ensureNotDisposed();
439
+ if (isEffectivelyPaused()) return;
440
+ if (opts?.category !== undefined) assertCategory(opts.category);
441
+ if (opts?.volume !== undefined) assertVolume(opts.volume);
442
+ const category = opts?.category ?? 'sfx';
443
+ const concurrencyKey = opts?.concurrency?.key ?? String(id);
444
+ const limit = opts?.concurrency?.limit;
445
+ const overflow = opts?.concurrency?.overflow ?? 'drop-new';
446
+ let reservation = null;
447
+ if (limit !== undefined) {
448
+ if (!Number.isFinite(limit) || limit < 1 || Math.floor(limit) !== limit) {
449
+ throw new GameAudioError(`Concurrency limit must be a positive integer, got ${String(limit)}`);
450
+ }
451
+ let set = concurrencyMap.get(concurrencyKey);
452
+ if (!set) {
453
+ set = new Set();
454
+ concurrencyMap.set(concurrencyKey, set);
455
+ }
456
+ if (set.size >= limit) {
457
+ if (overflow === 'drop-new') return;
458
+ if (overflow === 'stop-oldest') {
459
+ const oldest = set.values().next().value;
460
+ if (oldest) {
461
+ if (pendingReservations.has(oldest)) {
462
+ cancelledReservations.add(oldest);
463
+ } else {
464
+ try {
465
+ oldest.stop();
466
+ } catch {}
467
+ dropVoice(oldest, concurrencyKey);
468
+ }
469
+ }
470
+ }
471
+ }
472
+ reservation = {};
473
+ set.add(reservation);
474
+ pendingReservations.add(reservation);
475
+ }
476
+ try {
477
+ const state = context.state;
478
+ if (state === 'suspended' && !isEffectivelyPaused()) void context.resume().catch(() => {});
479
+ } catch {}
480
+ if (idleSuspendTimer) {
481
+ clearTimeout(idleSuspendTimer);
482
+ idleSuspendTimer = null;
483
+ }
484
+ void (async () => {
485
+ if (disposed || !context || isEffectivelyPaused()) {
486
+ if (reservation) {
487
+ dropReservation(reservation, concurrencyKey);
488
+ }
489
+ return;
490
+ }
491
+ try {
492
+ const buffer = await getBuffer(id);
493
+ if (disposed || !context || isEffectivelyPaused()) {
494
+ if (reservation) {
495
+ dropReservation(reservation, concurrencyKey);
496
+ }
497
+ return;
498
+ }
499
+ if (reservation && cancelledReservations.has(reservation)) {
500
+ dropReservation(reservation, concurrencyKey);
501
+ return;
502
+ }
503
+ // GS-AUDIO-01: one idempotent cleanup owns every stage from here.
504
+ // A failure in create/connect/start removes BOTH the reservation
505
+ // and the actual source, detaches handlers, disconnects owned
506
+ // nodes, and reconsiders idle suspension — never half-registered.
507
+ let voiceGain = null;
508
+ let cleaned = false;
509
+ let source = null;
510
+ const releaseVoice = () => {
511
+ if (cleaned) return;
512
+ cleaned = true;
513
+ if (source !== null) {
514
+ dropVoice(source, limit !== undefined ? concurrencyKey : undefined);
515
+ }
516
+ if (reservation && limit !== undefined) {
517
+ dropReservation(reservation, concurrencyKey);
518
+ }
519
+ const anySource = source;
520
+ if (anySource !== null && anySource.onended === cleanup) anySource.onended = null;
521
+ try {
522
+ source?.disconnect?.();
523
+ } catch {}
524
+ try {
525
+ if (voiceGain !== null) {
526
+ voiceGain.disconnect?.();
527
+ }
528
+ } catch {}
529
+ scheduleIdleSuspend();
530
+ };
531
+ const cleanup = () => {
532
+ releaseVoice();
533
+ };
534
+ try {
535
+ source = context.createBufferSource();
536
+ source.buffer = buffer;
537
+ if (opts?.loop) source.loop = true;
538
+ let dest = context.destination;
539
+ const catGain = categoryGains[category];
540
+ if (catGain) dest = catGain;else if (masterGain) dest = masterGain;
541
+ if (opts?.volume !== undefined) {
542
+ try {
543
+ voiceGain = context.createGain();
544
+ if (voiceGain) {
545
+ const v = opts.volume;
546
+ try {
547
+ voiceGain.gain.value = v;
548
+ } catch {}
549
+ voiceGain.connect(dest);
550
+ dest = voiceGain;
551
+ }
552
+ } catch {}
553
+ }
554
+ source.connect(dest);
555
+ activeVoices.add(source);
556
+ if (reservation) {
557
+ pendingReservations.delete(reservation);
558
+ const set = concurrencyMap.get(concurrencyKey);
559
+ if (set) {
560
+ set.delete(reservation);
561
+ set.add(source);
562
+ }
563
+ }
564
+ const anySource = source;
565
+ if (typeof anySource.addEventListener === 'function') anySource.addEventListener('ended', cleanup);else anySource.onended = cleanup;
566
+ source.start();
567
+ if (idleSuspendTimer) {
568
+ clearTimeout(idleSuspendTimer);
569
+ idleSuspendTimer = null;
570
+ }
571
+ } catch (e) {
572
+ releaseVoice();
573
+ console.warn(`[GameAudio] play("${String(id)}") failed:`, e);
574
+ }
575
+ } catch (e) {
576
+ // Pre-voice stages (decode/buffer) failed: no voice exists, but
577
+ // the reservation must still be released exactly once.
578
+ if (reservation) {
579
+ const set = concurrencyMap.get(concurrencyKey);
580
+ if (set) {
581
+ set.delete(reservation);
582
+ if (set.size === 0) concurrencyMap.delete(concurrencyKey);
583
+ }
584
+ cancelledReservations.delete(reservation);
585
+ }
586
+ console.warn(`[GameAudio] play("${String(id)}") failed:`, e);
587
+ }
588
+ })();
589
+ },
590
+ async playMusic(id) {
591
+ ensureNotDisposed();
592
+ musicGeneration++;
593
+ const gen = musicGeneration;
594
+ // Stop previous immediately and mark generation
595
+ if (currentMusicNode) {
596
+ try {
597
+ currentMusicNode.stop();
598
+ } catch {}
599
+ currentMusicNode = null;
600
+ }
601
+ currentMusicId = id;
602
+ // If effectively paused, defer (F4)
603
+ if (isEffectivelyPaused()) {
604
+ pendingMusic = {
605
+ id: id,
606
+ generation: gen
607
+ };
608
+ return;
609
+ }
610
+ await startMusicInternal(id, gen);
611
+ },
612
+ stopMusic() {
613
+ ensureNotDisposed();
614
+ musicGeneration++;
615
+ if (currentMusicNode) {
616
+ try {
617
+ currentMusicNode.stop();
618
+ } catch {}
619
+ currentMusicNode = null;
620
+ }
621
+ currentMusicId = null;
622
+ pendingMusic = null;
623
+ scheduleIdleSuspend();
624
+ },
625
+ pause() {
626
+ ensureNotDisposed();
627
+ if (userPaused) return;
628
+ userPaused = true;
629
+ requestSuspendUpdate();
630
+ // FF1: keep denied-interruption flag intact; only explicit resume() clears it
631
+ },
632
+ resume() {
633
+ ensureNotDisposed();
634
+ if (!userPaused && !interruptionRequiresExplicitResume) return;
635
+ const wasExplicit = interruptionRequiresExplicitResume;
636
+ userPaused = false;
637
+ if (wasExplicit) {
638
+ // Explicit user action clears denied auto-resume (F2)
639
+ interruptionPaused = false;
640
+ interruptionRequiresExplicitResume = false;
641
+ }
642
+ updateSuspendState();
643
+ },
644
+ setVolume(category, volume) {
645
+ ensureNotDisposed();
646
+ assertCategory(category);
647
+ assertVolume(volume);
648
+ volumes[category] = volume;
649
+ applyGain(category);
650
+ // F1: don't re-apply master when changing category, and vice versa — only own gain
651
+ },
652
+ getVolume(category) {
653
+ ensureNotDisposed();
654
+ assertCategory(category);
655
+ return volumes[category];
656
+ },
657
+ setMuted(next) {
658
+ ensureNotDisposed();
659
+ muted = Boolean(next);
660
+ updateSuspendState();
661
+ },
662
+ isMuted() {
663
+ ensureNotDisposed();
664
+ return muted;
665
+ },
666
+ setPaused(next) {
667
+ ensureNotDisposed();
668
+ setSessionPaused(Boolean(next));
669
+ },
670
+ bindLifecycle(source) {
671
+ return bindAudioLifecycle(source);
672
+ },
673
+ /** Compat alias for the pre-T20.7 session channel; use setPaused. */
674
+ _setSessionPaused(p) {
675
+ ensureNotDisposed();
676
+ setSessionPaused(Boolean(p));
677
+ },
678
+ dispose() {
679
+ if (disposed) return;
680
+ disposed = true;
681
+ currentMusicId = null;
682
+ pendingMusic = null;
683
+ if (currentMusicNode) {
684
+ try {
685
+ currentMusicNode.stop();
686
+ } catch {}
687
+ currentMusicNode = null;
688
+ }
689
+ for (const v of activeVoices) {
690
+ try {
691
+ v.stop();
692
+ } catch {}
693
+ }
694
+ activeVoices.clear();
695
+ concurrencyMap.clear();
696
+ cancelledReservations.clear();
697
+ pendingDecodes.clear();
698
+ bufferCache.clear();
699
+ if (idleSuspendTimer) {
700
+ clearTimeout(idleSuspendTimer);
701
+ idleSuspendTimer = null;
702
+ }
703
+ lifecycleDetach?.();
704
+ lifecycleDetach = null;
705
+ if (interruptionSub) {
706
+ try {
707
+ interruptionSub.remove();
708
+ } catch {}
709
+ interruptionSub = null;
710
+ }
711
+ if (interruptionEnabled) {
712
+ interruptionObserverCount = Math.max(0, interruptionObserverCount - 1);
713
+ if (interruptionObserverCount === 0) {
714
+ try {
715
+ AudioManager?.observeAudioInterruptions(false);
716
+ } catch {}
717
+ }
718
+ interruptionEnabled = false;
719
+ }
720
+ if (appStateSub) {
721
+ try {
722
+ appStateSub.remove();
723
+ } catch {}
724
+ appStateSub = null;
725
+ }
726
+ if (context) void context.close().catch(() => {});
727
+ }
728
+ };
729
+ const bindAudioLifecycle = source => {
730
+ ensureNotDisposed();
731
+ // One active source: a replacement detaches the previous one first.
732
+ lifecycleDetach?.();
733
+ lifecycleDetach = null;
734
+ // Apply the current status immediately, then follow transitions.
735
+ // AppState backgrounding stays independent (separate flag).
736
+ setSessionPaused(source.getStatus() !== 'running');
737
+ const sourceDetach = source.subscribe(status => {
738
+ setSessionPaused(status !== 'running');
739
+ });
740
+ let detached = false;
741
+ const detach = () => {
742
+ if (detached) return;
743
+ detached = true;
744
+ sourceDetach();
745
+ if (lifecycleDetach === detach) lifecycleDetach = null;
746
+ };
747
+ lifecycleDetach = detach;
748
+ return detach;
749
+ };
750
+ audio._isIdleSuspended = () => {
751
+ try {
752
+ return context.state === 'suspended';
753
+ } catch {
754
+ return false;
755
+ }
756
+ };
757
+ audio._getConcurrencyCount = k => concurrencyMap.get(k)?.size ?? 0;
758
+ // Test-only collection sizes for the ownership suites (GS-AUDIO-01/02).
759
+ audio._getVoiceCounts = () => ({
760
+ activeVoices: activeVoices.size,
761
+ concurrencyKeys: concurrencyMap.size,
762
+ cancelled: cancelledReservations.size
763
+ });
764
+ audio._handleInterruption = handleInterruption;
765
+ audio._getVolumes = () => ({
766
+ ...volumes
767
+ });
768
+ audio._getGainTargets = () => {
769
+ const out = {};
770
+ for (const c of CATEGORIES) {
771
+ const g = categoryGains[c];
772
+ if (g) {
773
+ try {
774
+ out[c] = g.gain.value;
775
+ } catch {
776
+ out[c] = volumes[c];
777
+ }
778
+ }
779
+ }
780
+ return out;
781
+ };
782
+ return audio;
783
+ }
784
+ //# sourceMappingURL=createGameAudio.js.map