rn-gamekit 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +97 -16
  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 +100 -10
  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
@@ -1,5 +1,6 @@
1
1
  import type { InputMap, SceneMap } from '../definition/types';
2
2
  import type { CommitFrame, GameSession } from '../core/session/types';
3
+ import { createCleanupList } from './cleanupList';
3
4
 
4
5
  /**
5
6
  * Bind a live session to an imperative presentation sink.
@@ -15,6 +16,9 @@ export function bindGameSession<TScenes extends SceneMap, TInput extends InputMa
15
16
  game: GameSession<TScenes, TInput>,
16
17
  present: (frame: CommitFrame<TScenes>) => void,
17
18
  ): () => void {
19
+ // GS-REACT-02: setup is transactional — the commit listener registered
20
+ // below is released when the subsequent start() throws.
21
+ const cleanups = createCleanupList();
18
22
  let lastRevision = -1;
19
23
  const presentIfNewer = (frame: CommitFrame<TScenes>) => {
20
24
  if (frame.revision <= lastRevision) {
@@ -25,7 +29,13 @@ export function bindGameSession<TScenes extends SceneMap, TInput extends InputMa
25
29
  };
26
30
  presentIfNewer(game.getRenderFrame());
27
31
  const subscription = game.addCommitListener(presentIfNewer);
28
- game.start();
32
+ cleanups.add(() => subscription.remove());
33
+ try {
34
+ game.start();
35
+ } catch (error) {
36
+ cleanups.releaseAll();
37
+ throw error;
38
+ }
29
39
  let cleanedUp = false;
30
40
 
31
41
  return () => {
@@ -33,7 +43,7 @@ export function bindGameSession<TScenes extends SceneMap, TInput extends InputMa
33
43
  return;
34
44
  }
35
45
  cleanedUp = true;
36
- subscription.remove();
46
+ cleanups.releaseAll();
37
47
  if (game.status !== 'disposed') {
38
48
  game.pause();
39
49
  }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * `GameLayer2D` — an ordered parallax layer (T12.5).
3
+ *
4
+ * A small rendering primitive, not a scene graph: the layer draws its
5
+ * children with the presented camera whose center contribution is scaled
6
+ * per axis by the parallax factor. JSX order is render order; no z-index
7
+ * scheduler exists.
8
+ *
9
+ * Frozen policy: parallax scales only the camera center contribution. Zoom
10
+ * and rotation apply fully at every factor; factor 1 is the primary layer,
11
+ * factor 0 is camera-fixed on that axis. The correction is a pure
12
+ * translation relative to the parent camera, so layers never double-apply
13
+ * zoom or rotation.
14
+ */
15
+ import type { ReactNode } from 'react';
16
+ import { Group } from '@shopify/react-native-skia';
17
+ import { useDerivedValue } from 'react-native-reanimated';
18
+
19
+ import { layerParallaxTransform2D, useGameWorldContext } from '../sprites/GameWorld2D';
20
+
21
+ function assertFiniteParallax(value: number, axis: 'x' | 'y'): void {
22
+ if (!Number.isFinite(value)) {
23
+ throw new RangeError(`GameLayer2D parallax.${axis} must be finite, got ${String(value)}`);
24
+ }
25
+ }
26
+
27
+ export function GameLayer2D({
28
+ parallax = { x: 1, y: 1 },
29
+ children,
30
+ }: {
31
+ /** Per-axis parallax factor; defaults to the primary layer `{ x: 1, y: 1 }`. */
32
+ readonly parallax?: { readonly x: number; readonly y: number };
33
+ readonly children: ReactNode;
34
+ }) {
35
+ assertFiniteParallax(parallax.x, 'x');
36
+ assertFiniteParallax(parallax.y, 'y');
37
+ const { viewport, camera } = useGameWorldContext();
38
+ const transform = useDerivedValue(() => {
39
+ 'worklet';
40
+ return layerParallaxTransform2D(camera?.value, viewport.value, parallax.x, parallax.y);
41
+ });
42
+ return <Group transform={transform as never}>{children}</Group>;
43
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Camera2D definition (T12.3).
3
+ *
4
+ * A static, declarative camera binding: `select` reads the authored camera
5
+ * from committed frames, and the optional `cut` predicate signals an
6
+ * explicit cut (teleports, respawns) where interpolation must snap. The
7
+ * binding is owned by `GameView` and never by the renderer or the pointer
8
+ * adapter, so both consume the same presented generation.
9
+ */
10
+ import type { Camera2D } from '../../camera2d';
11
+
12
+ /** Failure context for a camera selector/cut/validation failure (GS-CAMERA-02). */
13
+ export interface GameCameraErrorInfo {
14
+ /** Which stage of the commit transaction failed. */
15
+ readonly phase: 'select' | 'cut' | 'validate';
16
+ /** The original thrown value, preserved verbatim. */
17
+ readonly error: unknown;
18
+ /** The scene whose commit failed. */
19
+ readonly scene: string;
20
+ }
21
+
22
+ /** The static camera definition supplied to `GameView`. */
23
+ export interface GameCamera2DDefinition<TFrame> {
24
+ /**
25
+ * Read the authored camera from a committed frame. Runs once per commit
26
+ * on the JS runtime; returning the same value keeps the camera static.
27
+ */
28
+ readonly select: (frame: TFrame) => Camera2D;
29
+ /**
30
+ * Optional explicit cut signal evaluated per commit. Returning true
31
+ * snaps presentation (no interpolation into the new camera), joining the
32
+ * automatic cuts for scene transitions, session replacement, and
33
+ * binding-generation changes.
34
+ */
35
+ readonly cut?: (frame: TFrame) => boolean;
36
+ /**
37
+ * Optional failure reporter (GS-CAMERA-02). Invoked at most once per
38
+ * failure episode with the failing phase and scene; a successful commit
39
+ * resets deduplication. Failures without a reporter keep the last valid
40
+ * presentation silently.
41
+ */
42
+ readonly onError?: (info: GameCameraErrorInfo) => void;
43
+ }
44
+
45
+ /** Validate and return a camera definition. */
46
+ export function defineGameCamera2D<TFrame>(
47
+ definition: GameCamera2DDefinition<TFrame>,
48
+ ): GameCamera2DDefinition<TFrame> {
49
+ if (typeof definition.select !== 'function') {
50
+ throw new Error('defineGameCamera2D requires a select function');
51
+ }
52
+ if (definition.cut !== undefined && typeof definition.cut !== 'function') {
53
+ throw new Error('defineGameCamera2D requires cut to be a function when provided');
54
+ }
55
+ if (definition.onError !== undefined && typeof definition.onError !== 'function') {
56
+ throw new Error('defineGameCamera2D requires onError to be a function when provided');
57
+ }
58
+ return definition;
59
+ }
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Presented camera binding (T12.3, T12-F2, T12-F3).
3
+ *
4
+ * Joins authored camera data to the UI presentation pipeline: `commit`
5
+ * runs per simulation commit on the JS runtime and evaluates the
6
+ * definition's selector AND cut predicate as ONE exception-safe
7
+ * transaction, validating the selected camera before any shared value is
8
+ * published. `present` runs on the UI runtime per display frame and
9
+ * delegates to the trusted scalar projector (a complete worklet call
10
+ * graph), writing the read-only `CameraCut2D` into the GameView-owned
11
+ * shared value that renderer and pointer adapter both consume.
12
+ *
13
+ * Cut semantics (snap instead of interpolate): scene transitions
14
+ * (`hardCut` or a scene-name change), explicit `cut` predicate hits,
15
+ * session replacement, and definition replacement — which is modeled as
16
+ * ONE pending cut owned by the replacement and consumed on its first
17
+ * successful commit, so later commits interpolate normally (T12-F3).
18
+ * A throwing selector or cut predicate retains the last valid presented
19
+ * value and leaves no half-updated state; the next valid commit recovers.
20
+ */
21
+ import { useEffect, useMemo, useRef } from 'react';
22
+ import { useSharedValue, type SharedValue } from 'react-native-reanimated';
23
+
24
+ import { interpolateCameraScalar2D, type CameraCut2D } from '../../camera2d';
25
+ import { cloneValidCamera2D } from '../../camera2d/validation';
26
+ import type { CommitFrame } from '../../core/session/types';
27
+ import type { SceneMap } from '../../definition/types';
28
+ import type { GameCamera2DDefinition } from './defineGameCamera2D';
29
+
30
+ /** A UI-side camera binding for one session presentation. */
31
+ export interface PresentedCameraBinding<TScenes extends SceneMap> {
32
+ /** Evaluate the selector against one committed frame (JS runtime). */
33
+ commit(frame: CommitFrame<TScenes>): void;
34
+ /** Advance presentation by the current alpha (UI runtime worklet). */
35
+ present(alpha: number): void;
36
+ /** Drop the current state; the presented value stays as-is. */
37
+ dispose(): void;
38
+ }
39
+
40
+ function sameSceneName(first: string | undefined, second: string | undefined): boolean {
41
+ return first === second;
42
+ }
43
+
44
+ /**
45
+ * Create the camera binding for one presentation.
46
+ *
47
+ * The `presented` shared value is owned by `GameView` so the pointer
48
+ * adapter (a sibling of the renderer) reads the same generation.
49
+ */
50
+ export function usePresentedCameraBinding<TScenes extends SceneMap>(
51
+ definition: GameCamera2DDefinition<CommitFrame<TScenes>> | undefined,
52
+ presented: SharedValue<CameraCut2D | undefined>,
53
+ ): PresentedCameraBinding<TScenes> {
54
+ const authoredPrevious = useSharedValue<CameraCut2D | undefined>(undefined);
55
+ const authoredCurrent = useSharedValue<CameraCut2D | undefined>(undefined);
56
+ const cutId = useSharedValue(0);
57
+ const sceneNameRef = useRef<string | undefined>(undefined);
58
+ // T12-F3: definition replacement is ONE pending cut, consumed by the
59
+ // first successful commit of the replacement binding — never a
60
+ // render-time boolean that stays true for the binding lifetime.
61
+ const pendingCutRef = useRef(false);
62
+
63
+ const definitionRef = useRef(definition);
64
+ useEffect(() => {
65
+ if (definitionRef.current === definition) {
66
+ return;
67
+ }
68
+ definitionRef.current = definition;
69
+ pendingCutRef.current = true;
70
+ authoredPrevious.value = undefined;
71
+ authoredCurrent.value = undefined;
72
+ sceneNameRef.current = undefined;
73
+ cutId.value += 1;
74
+ presented.value = undefined;
75
+ }, [authoredCurrent, authoredPrevious, cutId, definition, presented]);
76
+
77
+ const binding = useMemo<PresentedCameraBinding<TScenes>>(
78
+ () => {
79
+ // GS-CAMERA-02: one report per failure episode (phase + message),
80
+ // reset by the next successful commit so a later distinct failure
81
+ // stays visible.
82
+ let lastReportedFailureKey: string | null = null;
83
+ const reportCameraError = (
84
+ activeDefinition: GameCamera2DDefinition<CommitFrame<TScenes>>,
85
+ phase: 'select' | 'cut' | 'validate',
86
+ error: unknown,
87
+ frame: CommitFrame<TScenes>,
88
+ ): void => {
89
+ const onError = activeDefinition.onError;
90
+ if (onError === undefined) {
91
+ return;
92
+ }
93
+ const message = error instanceof Error ? error.message : String(error);
94
+ const key = `${phase}:${message}`;
95
+ if (key === lastReportedFailureKey) {
96
+ return;
97
+ }
98
+ lastReportedFailureKey = key;
99
+ try {
100
+ onError({ phase, error, scene: String(frame.scene) });
101
+ } catch {
102
+ // A throwing reporter must not break the last-valid fallback.
103
+ }
104
+ };
105
+ const markRecovered = (): void => {
106
+ lastReportedFailureKey = null;
107
+ };
108
+ return {
109
+ commit: (frame) => {
110
+ // GS-CAMERA-01: the binding identity is stable across definition
111
+ // replacements (the inner effect owns the pending cut), so a
112
+ // definition change never tears down presentation or restarts the
113
+ // session. Always read the current definition here.
114
+ const activeDefinition = definitionRef.current;
115
+ if (activeDefinition === undefined) {
116
+ return;
117
+ }
118
+ // One exception-safe transaction: select + cut + validation. A
119
+ // failure retains the last valid presented value and leaves no
120
+ // half-updated scene/cut state.
121
+ let camera;
122
+ let explicitCut = false;
123
+ let phase: 'select' | 'cut' | 'validate' = 'select';
124
+ try {
125
+ // T12-RF4 + T12-SF3: the selector output is validated AND copied
126
+ // at the JS commit boundary with the STRICT full-camera clone — a
127
+ // mutable selector result can never alias the authored values,
128
+ // and a partial camera is rejected, never completed with
129
+ // defaults.
130
+ const selected = activeDefinition.select(frame);
131
+ phase = 'cut';
132
+ explicitCut = activeDefinition.cut?.(frame) === true;
133
+ phase = 'validate';
134
+ camera = cloneValidCamera2D(selected);
135
+ } catch (error) {
136
+ reportCameraError(activeDefinition, phase, error, frame);
137
+ return;
138
+ }
139
+ markRecovered();
140
+ const pendingCut = pendingCutRef.current;
141
+ pendingCutRef.current = false;
142
+ const sceneChanged = !sameSceneName(sceneNameRef.current, String(frame.scene));
143
+ sceneNameRef.current = String(frame.scene);
144
+ const current: CameraCut2D = { camera, cutId: cutId.value };
145
+ if (pendingCut || explicitCut || sceneChanged || frame.hardCut) {
146
+ authoredPrevious.value = undefined;
147
+ cutId.value += 1;
148
+ authoredCurrent.value = { camera, cutId: cutId.value };
149
+ // GS-CAMERA-01: a valid hard cut installs the presented camera
150
+ // immediately — paused time presents coherently without waiting
151
+ // for the next present(alpha). Ordinary commits leave
152
+ // presentation to the frame clock so pause freezes interpolation.
153
+ presented.value = { camera, cutId: cutId.value };
154
+ } else {
155
+ authoredPrevious.value = authoredCurrent.value;
156
+ authoredCurrent.value = current;
157
+ }
158
+ },
159
+ present: (alpha: number) => {
160
+ 'worklet';
161
+ const current = authoredCurrent.value;
162
+ if (current === undefined) {
163
+ return;
164
+ }
165
+ presented.value = {
166
+ camera: interpolateCameraScalar2D(authoredPrevious.value, current, alpha),
167
+ cutId: current.cutId,
168
+ };
169
+ },
170
+ dispose: () => {
171
+ authoredPrevious.value = undefined;
172
+ authoredCurrent.value = undefined;
173
+ presented.value = undefined;
174
+ },
175
+ };
176
+ },
177
+ // GS-CAMERA-01: stable identity across definition replacements — the
178
+ // inner effect owns the pending cut, so definition changes never tear
179
+ // down presentation or restart the session. `presented` is GameView-owned
180
+ // and stable per mount.
181
+ [presented],
182
+ );
183
+
184
+ return binding;
185
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Ordered, transactional release list for multi-stage setup (GS-REACT-02).
3
+ *
4
+ * Platform-neutral: no React import, so the headless binders and the React
5
+ * adapter share it. Stages register their release as they complete; a setup
6
+ * failure releases everything acquired so far, and the final cleanup runs
7
+ * every release in reverse registration order, composing failures
8
+ * losslessly instead of stopping at the first one.
9
+ */
10
+ export interface CleanupList {
11
+ /** Register a release for a completed setup stage. */
12
+ add(release: () => void): void;
13
+ /**
14
+ * Run every registered release in reverse order. A lone failure rethrows
15
+ * unwrapped; several compose into an `AggregateError` in run order. The
16
+ * list drains, so releasing twice is a no-op.
17
+ */
18
+ releaseAll(): void;
19
+ }
20
+
21
+ export function createCleanupList(): CleanupList {
22
+ const releases: Array<() => void> = [];
23
+ return {
24
+ add(release: () => void): void {
25
+ releases.push(release);
26
+ },
27
+ releaseAll(): void {
28
+ const failures: unknown[] = [];
29
+ for (let index = releases.length - 1; index >= 0; index -= 1) {
30
+ try {
31
+ releases[index]?.();
32
+ } catch (error) {
33
+ failures.push(error);
34
+ }
35
+ }
36
+ releases.length = 0;
37
+ if (failures.length === 1) {
38
+ throw failures[0];
39
+ }
40
+ if (failures.length > 1) {
41
+ throw new AggregateError(
42
+ failures,
43
+ 'Cleanup failed with multiple errors',
44
+ );
45
+ }
46
+ },
47
+ };
48
+ }
@@ -17,6 +17,8 @@
17
17
  */
18
18
 
19
19
  import type { CoalescedPointerEvent } from './pointerCoalescer';
20
+ import type { CameraCut2D } from '../camera2d';
21
+ import type { ResolvedViewport2D } from '../viewport2d';
20
22
 
21
23
  /** Raw touch kinds as observed by the manual gesture callbacks. */
22
24
  export type PointerStageKind = 'down' | 'move' | 'up' | 'cancel';
@@ -37,6 +39,29 @@ export interface GamePointerInstrumentation {
37
39
  * counted but never sampled.
38
40
  */
39
41
  readonly onDispatchResult?: (seq: number, atMs: number, accepted: boolean) => void;
42
+ /**
43
+ * RN runtime: the CAUSE of a rejected packet (T12-RF7) — layout-epoch
44
+ * staleness (rejected before dispatch) or binding staleness (generation
45
+ * mismatch or a disposed binding). One boolean cannot attribute causes.
46
+ */
47
+ readonly onDispatchRejected?: (
48
+ cause: 'layout-epoch' | 'binding',
49
+ seq: number,
50
+ atMs: number,
51
+ ) => void;
52
+ /**
53
+ * RN runtime: one ACCEPTED surface -> world conversion (T12-TF3), with
54
+ * the exact inputs and output of the authoritative binding — surface
55
+ * point, resolved mounted viewport, event-time presented camera cut, and
56
+ * the delivered world coordinate. Lab-only diagnostics; never a second
57
+ * gameplay transform.
58
+ */
59
+ readonly onPointerSample?: (sample: {
60
+ readonly surface: { readonly x: number; readonly y: number };
61
+ readonly viewport: ResolvedViewport2D;
62
+ readonly camera: CameraCut2D | undefined;
63
+ readonly world: { readonly x: number; readonly y: number };
64
+ }) => void;
40
65
  /** The trailing-flush sampler mounted (true) or unmounted (false). */
41
66
  readonly onSamplerChanged?: (mounted: boolean) => void;
42
67
  }
@@ -46,9 +71,12 @@ export interface GameViewInstrumentation {
46
71
  /** A commit was presented to the canvas frame shared value. */
47
72
  readonly onPresentCommit?: (revision: number, atMs: number) => void;
48
73
  /**
49
- * UI runtime: the first UI frame that observed a new commit revision (the
50
- * alpha clock's reset detects it). Skia GPU presentation is not proven by
51
- * this hook, so latency consumers must name the stage honestly.
74
+ * The first UI frame that observed a new commit revision (the alpha
75
+ * clock's reset detects it), delivered ON THE RN RUNTIME: `GameView`
76
+ * detects the revision inside its UI frame callback and deliberately
77
+ * `scheduleOnRN`s this callback, so it must run on JS, never as a
78
+ * worklet. Skia GPU presentation is not proven by this hook, so latency
79
+ * consumers must name the stage honestly.
52
80
  */
53
81
  readonly onUiRevisionObserved?: (revision: number, atMs: number) => void;
54
82
  }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * T20.3: GameView owns one lifecycle source per session and supplies it to
3
+ * its renderer subtree through context. Presentation consumers (particle
4
+ * presentation, haptics binders) read the source instead of casting to
5
+ * private session methods or reaching for module-global coordinators.
6
+ *
7
+ * The source itself is a frozen plain value created by
8
+ * `createGameLifecycleSource`; replacing the session replaces the source, so
9
+ * a consumer bound to the old generation can never observe the new one.
10
+ */
11
+ import { createContext, useContext } from 'react';
12
+ import type {
13
+ GameLifecycleSource,
14
+ GameSession,
15
+ GameSessionStatus,
16
+ } from '../core/session/types';
17
+ import type { InputMap, SceneMap } from '../definition/types';
18
+
19
+ export type { GameLifecycleSource, GameSessionStatus };
20
+
21
+ const NOOP_DETACH = (): void => {};
22
+
23
+ /**
24
+ * Create the read-only lifecycle source for one session. The returned value
25
+ * is a frozen plain value with exactly `getStatus` and `subscribe`.
26
+ */
27
+ export function createGameLifecycleSource<TScenes extends SceneMap, TInput extends InputMap>(
28
+ session: GameSession<TScenes, TInput>,
29
+ ): GameLifecycleSource {
30
+ return Object.freeze({
31
+ getStatus: () => session.status,
32
+ subscribe(listener: (status: GameSessionStatus) => void): () => void {
33
+ // Disposed-error policy (mirrors useGameSessionStatus): the terminal
34
+ // notification was already delivered; never throw from a subscription.
35
+ if (session.status === 'disposed') return NOOP_DETACH;
36
+ const subscription = session.addStatusListener(listener);
37
+ return () => subscription.remove();
38
+ },
39
+ });
40
+ }
41
+
42
+ const GameLifecycleContext = createContext<GameLifecycleSource | undefined>(undefined);
43
+
44
+ /** Supply the owning session's lifecycle source to a renderer subtree. */
45
+ export const GameLifecycleProvider = GameLifecycleContext.Provider;
46
+
47
+ /**
48
+ * Read the lifecycle source provided by the surrounding `GameView`.
49
+ *
50
+ * `undefined` means the consumer is mounted outside a `GameView` — a
51
+ * legitimate state for screens that drive presentation without a session
52
+ * (they pass no lifecycle to `useParticlePresentation` and keep manual pause
53
+ * independent). Inside a `GameView` the value is always present and is
54
+ * replaced together with the session.
55
+ */
56
+ export function useGameLifecycleSource(): GameLifecycleSource | undefined {
57
+ return useContext(GameLifecycleContext);
58
+ }