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.
- package/CHANGELOG.md +68 -0
- package/README.md +95 -14
- package/lib/module/assets/defineAssets.js +28 -3
- package/lib/module/assets/defineAssets.js.map +1 -1
- package/lib/module/assets.js +11 -0
- package/lib/module/assets.js.map +1 -0
- package/lib/module/audio/createGameAudio.js +784 -0
- package/lib/module/audio/createGameAudio.js.map +1 -0
- package/lib/module/audio/errors.js +12 -0
- package/lib/module/audio/errors.js.map +1 -0
- package/lib/module/audio/index.js +5 -0
- package/lib/module/audio/index.js.map +1 -0
- package/lib/module/audio/resolver.js +37 -0
- package/lib/module/audio/resolver.js.map +1 -0
- package/lib/module/audio/types.js +4 -0
- package/lib/module/audio/types.js.map +1 -0
- package/lib/module/audio.js +9 -0
- package/lib/module/audio.js.map +1 -0
- package/lib/module/camera2d/bounds.js +59 -0
- package/lib/module/camera2d/bounds.js.map +1 -0
- package/lib/module/camera2d/extents.js +25 -0
- package/lib/module/camera2d/extents.js.map +1 -0
- package/lib/module/camera2d/follow.js +138 -0
- package/lib/module/camera2d/follow.js.map +1 -0
- package/lib/module/camera2d/index.js +20 -0
- package/lib/module/camera2d/index.js.map +1 -0
- package/lib/module/camera2d/interpolation.js +98 -0
- package/lib/module/camera2d/interpolation.js.map +1 -0
- package/lib/module/camera2d/shake.js +85 -0
- package/lib/module/camera2d/shake.js.map +1 -0
- package/lib/module/camera2d/transform.js +151 -0
- package/lib/module/camera2d/transform.js.map +1 -0
- package/lib/module/camera2d/types.js +4 -0
- package/lib/module/camera2d/types.js.map +1 -0
- package/lib/module/camera2d/validation.js +98 -0
- package/lib/module/camera2d/validation.js.map +1 -0
- package/lib/module/camera2d/visibility.js +138 -0
- package/lib/module/camera2d/visibility.js.map +1 -0
- package/lib/module/camera2d.js +9 -0
- package/lib/module/camera2d.js.map +1 -0
- package/lib/module/collision2d/colliders.js +266 -0
- package/lib/module/collision2d/colliders.js.map +1 -0
- package/lib/module/collision2d/debug.js +105 -0
- package/lib/module/collision2d/debug.js.map +1 -0
- package/lib/module/collision2d/filters.js +40 -0
- package/lib/module/collision2d/filters.js.map +1 -0
- package/lib/module/collision2d/index.js +12 -0
- package/lib/module/collision2d/index.js.map +1 -0
- package/lib/module/collision2d/intersections.js +67 -0
- package/lib/module/collision2d/intersections.js.map +1 -0
- package/lib/module/collision2d/manifolds.js +218 -0
- package/lib/module/collision2d/manifolds.js.map +1 -0
- package/lib/module/collision2d/segments.js +187 -0
- package/lib/module/collision2d/segments.js.map +1 -0
- package/lib/module/collision2d/spatialHash.js +167 -0
- package/lib/module/collision2d/spatialHash.js.map +1 -0
- package/lib/module/collision2d/sweeps.js +255 -0
- package/lib/module/collision2d/sweeps.js.map +1 -0
- package/lib/module/collision2d.js +9 -0
- package/lib/module/collision2d.js.map +1 -0
- package/lib/module/core/input/buttonPad.js +214 -0
- package/lib/module/core/input/buttonPad.js.map +1 -0
- package/lib/module/core/input/createInputBuffer.js +66 -14
- package/lib/module/core/input/createInputBuffer.js.map +1 -1
- package/lib/module/core/session/createGameSession.js +454 -50
- package/lib/module/core/session/createGameSession.js.map +1 -1
- package/lib/module/core/session/deepFreeze.js +92 -2
- package/lib/module/core/session/deepFreeze.js.map +1 -1
- package/lib/module/core/session/types.js +12 -0
- package/lib/module/core/session/types.js.map +1 -1
- package/lib/module/definition/defineGame.js +23 -0
- package/lib/module/definition/defineGame.js.map +1 -1
- package/lib/module/events/defineGameEvents.js +46 -0
- package/lib/module/events/defineGameEvents.js.map +1 -0
- package/lib/module/events/errors.js +16 -0
- package/lib/module/events/errors.js.map +1 -0
- package/lib/module/events/index.js +7 -0
- package/lib/module/events/index.js.map +1 -0
- package/lib/module/events/payload.js +219 -0
- package/lib/module/events/payload.js.map +1 -0
- package/lib/module/events/seed.js +33 -0
- package/lib/module/events/seed.js.map +1 -0
- package/lib/module/events/types.js +4 -0
- package/lib/module/events/types.js.map +1 -0
- package/lib/module/events.js +13 -0
- package/lib/module/events.js.map +1 -0
- package/lib/module/geometry/helpers.js +140 -0
- package/lib/module/geometry/helpers.js.map +1 -0
- package/lib/module/geometry/index.js +5 -0
- package/lib/module/geometry/index.js.map +1 -0
- package/lib/module/geometry/validation.js +104 -0
- package/lib/module/geometry/validation.js.map +1 -0
- package/lib/module/geometry.js +9 -0
- package/lib/module/geometry.js.map +1 -0
- package/lib/module/haptics/createGameHaptics.js +214 -0
- package/lib/module/haptics/createGameHaptics.js.map +1 -0
- package/lib/module/haptics/errors.js +12 -0
- package/lib/module/haptics/errors.js.map +1 -0
- package/lib/module/haptics/index.js +5 -0
- package/lib/module/haptics/index.js.map +1 -0
- package/lib/module/haptics/resolver.js +37 -0
- package/lib/module/haptics/resolver.js.map +1 -0
- package/lib/module/haptics/types.js +4 -0
- package/lib/module/haptics/types.js.map +1 -0
- package/lib/module/haptics.js +9 -0
- package/lib/module/haptics.js.map +1 -0
- package/lib/module/index.js +8 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/particles/createParticleSystem.js +481 -0
- package/lib/module/particles/createParticleSystem.js.map +1 -0
- package/lib/module/particles/defineParticleEffect.js +178 -0
- package/lib/module/particles/defineParticleEffect.js.map +1 -0
- package/lib/module/particles/errors.js +9 -0
- package/lib/module/particles/errors.js.map +1 -0
- package/lib/module/particles/index.js +8 -0
- package/lib/module/particles/index.js.map +1 -0
- package/lib/module/particles/sampling.js +121 -0
- package/lib/module/particles/sampling.js.map +1 -0
- package/lib/module/particles/types.js +4 -0
- package/lib/module/particles/types.js.map +1 -0
- package/lib/module/particles.js +4 -0
- package/lib/module/particles.js.map +1 -0
- package/lib/module/react/GameButtonPad.js +344 -0
- package/lib/module/react/GameButtonPad.js.map +1 -0
- package/lib/module/react/GamePointerInput.js +74 -16
- package/lib/module/react/GamePointerInput.js.map +1 -1
- package/lib/module/react/GameView.js +139 -60
- package/lib/module/react/GameView.js.map +1 -1
- package/lib/module/react/assets/createGameAssetStore.js +145 -95
- package/lib/module/react/assets/createGameAssetStore.js.map +1 -1
- package/lib/module/react/assets/useGameAssets.js +60 -35
- package/lib/module/react/assets/useGameAssets.js.map +1 -1
- package/lib/module/react/bindAppLifecycle.js +46 -17
- package/lib/module/react/bindAppLifecycle.js.map +1 -1
- package/lib/module/react/bindGameSession.js +13 -2
- package/lib/module/react/bindGameSession.js.map +1 -1
- package/lib/module/react/camera2d/GameLayer2D.js +50 -0
- package/lib/module/react/camera2d/GameLayer2D.js.map +1 -0
- package/lib/module/react/camera2d/defineGameCamera2D.js +30 -0
- package/lib/module/react/camera2d/defineGameCamera2D.js.map +1 -0
- package/lib/module/react/camera2d/usePresentedCameraBinding.js +177 -0
- package/lib/module/react/camera2d/usePresentedCameraBinding.js.map +1 -0
- package/lib/module/react/cleanupList.js +38 -0
- package/lib/module/react/cleanupList.js.map +1 -0
- package/lib/module/react/lifecycleSource.js +49 -0
- package/lib/module/react/lifecycleSource.js.map +1 -0
- package/lib/module/react/particles/ParticleView.js +308 -0
- package/lib/module/react/particles/ParticleView.js.map +1 -0
- package/lib/module/react/particles/culling.js +115 -0
- package/lib/module/react/particles/culling.js.map +1 -0
- package/lib/module/react/particles/index.js +7 -0
- package/lib/module/react/particles/index.js.map +1 -0
- package/lib/module/react/particles/spriteXForm.js +45 -0
- package/lib/module/react/particles/spriteXForm.js.map +1 -0
- package/lib/module/react/particles/useParticlePresentation.js +204 -0
- package/lib/module/react/particles/useParticlePresentation.js.map +1 -0
- package/lib/module/react/pointerBinding.js +55 -17
- package/lib/module/react/pointerBinding.js.map +1 -1
- package/lib/module/react/pointerCamera.js +28 -0
- package/lib/module/react/pointerCamera.js.map +1 -0
- package/lib/module/react/pointerCoalescer.js +16 -9
- package/lib/module/react/pointerCoalescer.js.map +1 -1
- package/lib/module/react/sprites/GameSprite.js +5 -17
- package/lib/module/react/sprites/GameSprite.js.map +1 -1
- package/lib/module/react/sprites/GameWorld2D.js +112 -9
- package/lib/module/react/sprites/GameWorld2D.js.map +1 -1
- package/lib/module/react/sprites/Sprite.js +48 -63
- package/lib/module/react/sprites/Sprite.js.map +1 -1
- package/lib/module/react/sprites/SpriteBatch.js +53 -28
- package/lib/module/react/sprites/SpriteBatch.js.map +1 -1
- package/lib/module/react/sprites/batchVisibility.js +58 -0
- package/lib/module/react/sprites/batchVisibility.js.map +1 -0
- package/lib/module/react/sprites/spriteSelection.js +103 -0
- package/lib/module/react/sprites/spriteSelection.js.map +1 -0
- package/lib/module/react/sprites/spriteTransform.js +46 -25
- package/lib/module/react/sprites/spriteTransform.js.map +1 -1
- package/lib/module/react/tilemap/TileMapLayer2D.js +217 -0
- package/lib/module/react/tilemap/TileMapLayer2D.js.map +1 -0
- package/lib/module/react/tilemap/tilePresentation.js +374 -0
- package/lib/module/react/tilemap/tilePresentation.js.map +1 -0
- package/lib/module/react/useGameSession.js +70 -0
- package/lib/module/react/useGameSession.js.map +1 -0
- package/lib/module/react/useGameSessionStatus.js +46 -0
- package/lib/module/react/useGameSessionStatus.js.map +1 -0
- package/lib/module/react/viewportBinding.js +5 -1
- package/lib/module/react/viewportBinding.js.map +1 -1
- package/lib/module/react.js +12 -1
- package/lib/module/react.js.map +1 -1
- package/lib/module/scene/defineScene.js +17 -0
- package/lib/module/scene/defineScene.js.map +1 -1
- package/lib/module/sprites/sampleSpriteClip.js +66 -6
- package/lib/module/sprites/sampleSpriteClip.js.map +1 -1
- package/lib/module/sprites/spriteAnimationState.js +10 -20
- package/lib/module/sprites/spriteAnimationState.js.map +1 -1
- package/lib/module/sprites.js +11 -0
- package/lib/module/sprites.js.map +1 -0
- package/lib/module/storage/adapters/asyncStorage.js +57 -0
- package/lib/module/storage/adapters/asyncStorage.js.map +1 -0
- package/lib/module/storage/adapters/memory.js +50 -0
- package/lib/module/storage/adapters/memory.js.map +1 -0
- package/lib/module/storage/errors.js +34 -0
- package/lib/module/storage/errors.js.map +1 -0
- package/lib/module/storage/index.js +11 -0
- package/lib/module/storage/index.js.map +1 -0
- package/lib/module/storage/schema.js +151 -0
- package/lib/module/storage/schema.js.map +1 -0
- package/lib/module/storage/serialization.js +249 -0
- package/lib/module/storage/serialization.js.map +1 -0
- package/lib/module/storage/store.js +387 -0
- package/lib/module/storage/store.js.map +1 -0
- package/lib/module/storage/types.js +16 -0
- package/lib/module/storage/types.js.map +1 -0
- package/lib/module/storage/validation.js +111 -0
- package/lib/module/storage/validation.js.map +1 -0
- package/lib/module/storage.js +4 -0
- package/lib/module/storage.js.map +1 -0
- package/lib/module/testing.js +4 -0
- package/lib/module/testing.js.map +1 -1
- package/lib/module/tilemap/chunkStats.js +27 -0
- package/lib/module/tilemap/chunkStats.js.map +1 -0
- package/lib/module/tilemap/definitions.js +308 -0
- package/lib/module/tilemap/definitions.js.map +1 -0
- package/lib/module/tilemap/errors.js +13 -0
- package/lib/module/tilemap/errors.js.map +1 -0
- package/lib/module/tilemap/index.js +10 -0
- package/lib/module/tilemap/index.js.map +1 -0
- package/lib/module/tilemap/movement.js +379 -0
- package/lib/module/tilemap/movement.js.map +1 -0
- package/lib/module/tilemap/queries.js +114 -0
- package/lib/module/tilemap/queries.js.map +1 -0
- package/lib/module/tilemap/tiledAdapter.js +141 -0
- package/lib/module/tilemap/tiledAdapter.js.map +1 -0
- package/lib/module/tilemap/types.js +4 -0
- package/lib/module/tilemap/types.js.map +1 -0
- package/lib/module/tilemap.js +4 -0
- package/lib/module/tilemap.js.map +1 -0
- package/lib/typescript/src/assets/defineAssets.d.ts +1 -1
- package/lib/typescript/src/assets/defineAssets.d.ts.map +1 -1
- package/lib/typescript/src/assets.d.ts +11 -0
- package/lib/typescript/src/assets.d.ts.map +1 -0
- package/lib/typescript/src/audio/createGameAudio.d.ts +5 -0
- package/lib/typescript/src/audio/createGameAudio.d.ts.map +1 -0
- package/lib/typescript/src/audio/errors.d.ts +6 -0
- package/lib/typescript/src/audio/errors.d.ts.map +1 -0
- package/lib/typescript/src/audio/index.d.ts +4 -0
- package/lib/typescript/src/audio/index.d.ts.map +1 -0
- package/lib/typescript/src/audio/resolver.d.ts +44 -0
- package/lib/typescript/src/audio/resolver.d.ts.map +1 -0
- package/lib/typescript/src/audio/types.d.ts +42 -0
- package/lib/typescript/src/audio/types.d.ts.map +1 -0
- package/lib/typescript/src/audio.d.ts +8 -0
- package/lib/typescript/src/audio.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/bounds.d.ts +25 -0
- package/lib/typescript/src/camera2d/bounds.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/extents.d.ts +17 -0
- package/lib/typescript/src/camera2d/extents.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/follow.d.ts +24 -0
- package/lib/typescript/src/camera2d/follow.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/index.d.ts +19 -0
- package/lib/typescript/src/camera2d/index.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/interpolation.d.ts +17 -0
- package/lib/typescript/src/camera2d/interpolation.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/shake.d.ts +20 -0
- package/lib/typescript/src/camera2d/shake.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/transform.d.ts +44 -0
- package/lib/typescript/src/camera2d/transform.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/types.d.ts +74 -0
- package/lib/typescript/src/camera2d/types.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/validation.d.ts +30 -0
- package/lib/typescript/src/camera2d/validation.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/visibility.d.ts +47 -0
- package/lib/typescript/src/camera2d/visibility.d.ts.map +1 -0
- package/lib/typescript/src/camera2d.d.ts +7 -0
- package/lib/typescript/src/camera2d.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/colliders.d.ts +120 -0
- package/lib/typescript/src/collision2d/colliders.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/debug.d.ts +67 -0
- package/lib/typescript/src/collision2d/debug.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/filters.d.ts +28 -0
- package/lib/typescript/src/collision2d/filters.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/index.d.ts +17 -0
- package/lib/typescript/src/collision2d/index.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/intersections.d.ts +24 -0
- package/lib/typescript/src/collision2d/intersections.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/manifolds.d.ts +39 -0
- package/lib/typescript/src/collision2d/manifolds.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/segments.d.ts +24 -0
- package/lib/typescript/src/collision2d/segments.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/spatialHash.d.ts +50 -0
- package/lib/typescript/src/collision2d/spatialHash.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/sweeps.d.ts +60 -0
- package/lib/typescript/src/collision2d/sweeps.d.ts.map +1 -0
- package/lib/typescript/src/collision2d.d.ts +7 -0
- package/lib/typescript/src/collision2d.d.ts.map +1 -0
- package/lib/typescript/src/core/input/buttonPad.d.ts +59 -0
- package/lib/typescript/src/core/input/buttonPad.d.ts.map +1 -0
- package/lib/typescript/src/core/input/createInputBuffer.d.ts +1 -1
- package/lib/typescript/src/core/input/createInputBuffer.d.ts.map +1 -1
- package/lib/typescript/src/core/input/types.d.ts +7 -0
- package/lib/typescript/src/core/input/types.d.ts.map +1 -1
- package/lib/typescript/src/core/session/createGameSession.d.ts +4 -2
- package/lib/typescript/src/core/session/createGameSession.d.ts.map +1 -1
- package/lib/typescript/src/core/session/deepFreeze.d.ts +21 -1
- package/lib/typescript/src/core/session/deepFreeze.d.ts.map +1 -1
- package/lib/typescript/src/core/session/diagnostics.d.ts +2 -0
- package/lib/typescript/src/core/session/diagnostics.d.ts.map +1 -1
- package/lib/typescript/src/core/session/types.d.ts +69 -4
- package/lib/typescript/src/core/session/types.d.ts.map +1 -1
- package/lib/typescript/src/definition/defineGame.d.ts +12 -1
- package/lib/typescript/src/definition/defineGame.d.ts.map +1 -1
- package/lib/typescript/src/definition/types.d.ts +10 -1
- package/lib/typescript/src/definition/types.d.ts.map +1 -1
- package/lib/typescript/src/events/defineGameEvents.d.ts +26 -0
- package/lib/typescript/src/events/defineGameEvents.d.ts.map +1 -0
- package/lib/typescript/src/events/errors.d.ts +12 -0
- package/lib/typescript/src/events/errors.d.ts.map +1 -0
- package/lib/typescript/src/events/index.d.ts +6 -0
- package/lib/typescript/src/events/index.d.ts.map +1 -0
- package/lib/typescript/src/events/payload.d.ts +21 -0
- package/lib/typescript/src/events/payload.d.ts.map +1 -0
- package/lib/typescript/src/events/seed.d.ts +3 -0
- package/lib/typescript/src/events/seed.d.ts.map +1 -0
- package/lib/typescript/src/events/types.d.ts +42 -0
- package/lib/typescript/src/events/types.d.ts.map +1 -0
- package/lib/typescript/src/events.d.ts +12 -0
- package/lib/typescript/src/events.d.ts.map +1 -0
- package/lib/typescript/src/geometry/helpers.d.ts +35 -0
- package/lib/typescript/src/geometry/helpers.d.ts.map +1 -0
- package/lib/typescript/src/geometry/index.d.ts +4 -0
- package/lib/typescript/src/geometry/index.d.ts.map +1 -0
- package/lib/typescript/src/geometry/types.d.ts +49 -0
- package/lib/typescript/src/geometry/types.d.ts.map +1 -1
- package/lib/typescript/src/geometry/validation.d.ts +44 -0
- package/lib/typescript/src/geometry/validation.d.ts.map +1 -0
- package/lib/typescript/src/geometry.d.ts +7 -0
- package/lib/typescript/src/geometry.d.ts.map +1 -0
- package/lib/typescript/src/haptics/createGameHaptics.d.ts +3 -0
- package/lib/typescript/src/haptics/createGameHaptics.d.ts.map +1 -0
- package/lib/typescript/src/haptics/errors.d.ts +6 -0
- package/lib/typescript/src/haptics/errors.d.ts.map +1 -0
- package/lib/typescript/src/haptics/index.d.ts +4 -0
- package/lib/typescript/src/haptics/index.d.ts.map +1 -0
- package/lib/typescript/src/haptics/resolver.d.ts +22 -0
- package/lib/typescript/src/haptics/resolver.d.ts.map +1 -0
- package/lib/typescript/src/haptics/types.d.ts +37 -0
- package/lib/typescript/src/haptics/types.d.ts.map +1 -0
- package/lib/typescript/src/haptics.d.ts +8 -0
- package/lib/typescript/src/haptics.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +10 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/particles/createParticleSystem.d.ts +5 -0
- package/lib/typescript/src/particles/createParticleSystem.d.ts.map +1 -0
- package/lib/typescript/src/particles/defineParticleEffect.d.ts +3 -0
- package/lib/typescript/src/particles/defineParticleEffect.d.ts.map +1 -0
- package/lib/typescript/src/particles/errors.d.ts +5 -0
- package/lib/typescript/src/particles/errors.d.ts.map +1 -0
- package/lib/typescript/src/particles/index.d.ts +6 -0
- package/lib/typescript/src/particles/index.d.ts.map +1 -0
- package/lib/typescript/src/particles/sampling.d.ts +54 -0
- package/lib/typescript/src/particles/sampling.d.ts.map +1 -0
- package/lib/typescript/src/particles/types.d.ts +292 -0
- package/lib/typescript/src/particles/types.d.ts.map +1 -0
- package/lib/typescript/src/particles.d.ts +2 -0
- package/lib/typescript/src/particles.d.ts.map +1 -0
- package/lib/typescript/src/react/GameButtonPad.d.ts +84 -0
- package/lib/typescript/src/react/GameButtonPad.d.ts.map +1 -0
- package/lib/typescript/src/react/GamePointerInput.d.ts.map +1 -1
- package/lib/typescript/src/react/GameView.d.ts +27 -1
- package/lib/typescript/src/react/GameView.d.ts.map +1 -1
- package/lib/typescript/src/react/assets/createGameAssetStore.d.ts.map +1 -1
- package/lib/typescript/src/react/assets/useGameAssets.d.ts.map +1 -1
- package/lib/typescript/src/react/bindAppLifecycle.d.ts +7 -1
- package/lib/typescript/src/react/bindAppLifecycle.d.ts.map +1 -1
- package/lib/typescript/src/react/bindGameSession.d.ts.map +1 -1
- package/lib/typescript/src/react/camera2d/GameLayer2D.d.ts +24 -0
- package/lib/typescript/src/react/camera2d/GameLayer2D.d.ts.map +1 -0
- package/lib/typescript/src/react/camera2d/defineGameCamera2D.d.ts +44 -0
- package/lib/typescript/src/react/camera2d/defineGameCamera2D.d.ts.map +1 -0
- package/lib/typescript/src/react/camera2d/usePresentedCameraBinding.d.ts +22 -0
- package/lib/typescript/src/react/camera2d/usePresentedCameraBinding.d.ts.map +1 -0
- package/lib/typescript/src/react/cleanupList.d.ts +21 -0
- package/lib/typescript/src/react/cleanupList.d.ts.map +1 -0
- package/lib/typescript/src/react/instrumentation.d.ts +33 -3
- package/lib/typescript/src/react/instrumentation.d.ts.map +1 -1
- package/lib/typescript/src/react/lifecycleSource.d.ts +21 -0
- package/lib/typescript/src/react/lifecycleSource.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/ParticleView.d.ts +65 -0
- package/lib/typescript/src/react/particles/ParticleView.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/culling.d.ts +70 -0
- package/lib/typescript/src/react/particles/culling.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/index.d.ts +7 -0
- package/lib/typescript/src/react/particles/index.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/spriteXForm.d.ts +28 -0
- package/lib/typescript/src/react/particles/spriteXForm.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/useParticlePresentation.d.ts +48 -0
- package/lib/typescript/src/react/particles/useParticlePresentation.d.ts.map +1 -0
- package/lib/typescript/src/react/pointerBinding.d.ts +38 -8
- package/lib/typescript/src/react/pointerBinding.d.ts.map +1 -1
- package/lib/typescript/src/react/pointerCamera.d.ts +20 -0
- package/lib/typescript/src/react/pointerCamera.d.ts.map +1 -0
- package/lib/typescript/src/react/pointerCoalescer.d.ts +17 -1
- package/lib/typescript/src/react/pointerCoalescer.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/GameSprite.d.ts +3 -10
- package/lib/typescript/src/react/sprites/GameSprite.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/GameWorld2D.d.ts +51 -6
- package/lib/typescript/src/react/sprites/GameWorld2D.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/Sprite.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/SpriteBatch.d.ts +22 -1
- package/lib/typescript/src/react/sprites/SpriteBatch.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/batchVisibility.d.ts +28 -0
- package/lib/typescript/src/react/sprites/batchVisibility.d.ts.map +1 -0
- package/lib/typescript/src/react/sprites/spriteSelection.d.ts +58 -0
- package/lib/typescript/src/react/sprites/spriteSelection.d.ts.map +1 -0
- package/lib/typescript/src/react/sprites/spriteTransform.d.ts +27 -12
- package/lib/typescript/src/react/sprites/spriteTransform.d.ts.map +1 -1
- package/lib/typescript/src/react/tilemap/TileMapLayer2D.d.ts +69 -0
- package/lib/typescript/src/react/tilemap/TileMapLayer2D.d.ts.map +1 -0
- package/lib/typescript/src/react/tilemap/tilePresentation.d.ts +217 -0
- package/lib/typescript/src/react/tilemap/tilePresentation.d.ts.map +1 -0
- package/lib/typescript/src/react/useGameSession.d.ts +48 -0
- package/lib/typescript/src/react/useGameSession.d.ts.map +1 -0
- package/lib/typescript/src/react/useGameSessionStatus.d.ts +23 -0
- package/lib/typescript/src/react/useGameSessionStatus.d.ts.map +1 -0
- package/lib/typescript/src/react/viewportBinding.d.ts +5 -1
- package/lib/typescript/src/react/viewportBinding.d.ts.map +1 -1
- package/lib/typescript/src/react.d.ts +18 -1
- package/lib/typescript/src/react.d.ts.map +1 -1
- package/lib/typescript/src/scene/defineScene.d.ts +22 -2
- package/lib/typescript/src/scene/defineScene.d.ts.map +1 -1
- package/lib/typescript/src/scene/types.d.ts +24 -4
- package/lib/typescript/src/scene/types.d.ts.map +1 -1
- package/lib/typescript/src/sprites/sampleSpriteClip.d.ts +26 -2
- package/lib/typescript/src/sprites/sampleSpriteClip.d.ts.map +1 -1
- package/lib/typescript/src/sprites/spriteAnimationState.d.ts +6 -7
- package/lib/typescript/src/sprites/spriteAnimationState.d.ts.map +1 -1
- package/lib/typescript/src/sprites.d.ts +10 -0
- package/lib/typescript/src/sprites.d.ts.map +1 -0
- package/lib/typescript/src/storage/adapters/asyncStorage.d.ts +18 -0
- package/lib/typescript/src/storage/adapters/asyncStorage.d.ts.map +1 -0
- package/lib/typescript/src/storage/adapters/memory.d.ts +16 -0
- package/lib/typescript/src/storage/adapters/memory.d.ts.map +1 -0
- package/lib/typescript/src/storage/errors.d.ts +37 -0
- package/lib/typescript/src/storage/errors.d.ts.map +1 -0
- package/lib/typescript/src/storage/index.d.ts +11 -0
- package/lib/typescript/src/storage/index.d.ts.map +1 -0
- package/lib/typescript/src/storage/schema.d.ts +22 -0
- package/lib/typescript/src/storage/schema.d.ts.map +1 -0
- package/lib/typescript/src/storage/serialization.d.ts +23 -0
- package/lib/typescript/src/storage/serialization.d.ts.map +1 -0
- package/lib/typescript/src/storage/store.d.ts +3 -0
- package/lib/typescript/src/storage/store.d.ts.map +1 -0
- package/lib/typescript/src/storage/types.d.ts +69 -0
- package/lib/typescript/src/storage/types.d.ts.map +1 -0
- package/lib/typescript/src/storage/validation.d.ts +24 -0
- package/lib/typescript/src/storage/validation.d.ts.map +1 -0
- package/lib/typescript/src/storage.d.ts +2 -0
- package/lib/typescript/src/storage.d.ts.map +1 -0
- package/lib/typescript/src/testing.d.ts +1 -0
- package/lib/typescript/src/testing.d.ts.map +1 -1
- package/lib/typescript/src/tilemap/chunkStats.d.ts +14 -0
- package/lib/typescript/src/tilemap/chunkStats.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/definitions.d.ts +38 -0
- package/lib/typescript/src/tilemap/definitions.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/errors.d.ts +7 -0
- package/lib/typescript/src/tilemap/errors.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/index.d.ts +8 -0
- package/lib/typescript/src/tilemap/index.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/movement.d.ts +52 -0
- package/lib/typescript/src/tilemap/movement.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/queries.d.ts +21 -0
- package/lib/typescript/src/tilemap/queries.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/tiledAdapter.d.ts +32 -0
- package/lib/typescript/src/tilemap/tiledAdapter.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/types.d.ts +127 -0
- package/lib/typescript/src/tilemap/types.d.ts.map +1 -0
- package/lib/typescript/src/tilemap.d.ts +2 -0
- package/lib/typescript/src/tilemap.d.ts.map +1 -0
- package/package.json +94 -4
- package/src/assets/defineAssets.ts +31 -5
- package/src/assets.ts +27 -0
- package/src/audio/createGameAudio.ts +749 -0
- package/src/audio/errors.ts +12 -0
- package/src/audio/index.ts +9 -0
- package/src/audio/resolver.ts +74 -0
- package/src/audio/types.ts +47 -0
- package/src/audio.ts +13 -0
- package/src/camera2d/bounds.ts +69 -0
- package/src/camera2d/extents.ts +25 -0
- package/src/camera2d/follow.ts +165 -0
- package/src/camera2d/index.ts +29 -0
- package/src/camera2d/interpolation.ts +113 -0
- package/src/camera2d/shake.ts +90 -0
- package/src/camera2d/transform.ts +148 -0
- package/src/camera2d/types.ts +73 -0
- package/src/camera2d/validation.ts +126 -0
- package/src/camera2d/visibility.ts +181 -0
- package/src/camera2d.ts +6 -0
- package/src/collision2d/colliders.ts +292 -0
- package/src/collision2d/debug.ts +133 -0
- package/src/collision2d/filters.ts +48 -0
- package/src/collision2d/index.ts +74 -0
- package/src/collision2d/intersections.ts +82 -0
- package/src/collision2d/manifolds.ts +191 -0
- package/src/collision2d/segments.ts +176 -0
- package/src/collision2d/spatialHash.ts +211 -0
- package/src/collision2d/sweeps.ts +269 -0
- package/src/collision2d.ts +6 -0
- package/src/core/input/buttonPad.ts +235 -0
- package/src/core/input/createInputBuffer.ts +95 -14
- package/src/core/input/types.ts +7 -0
- package/src/core/session/createGameSession.ts +480 -53
- package/src/core/session/deepFreeze.ts +104 -3
- package/src/core/session/diagnostics.ts +2 -0
- package/src/core/session/types.ts +77 -4
- package/src/definition/defineGame.ts +61 -3
- package/src/definition/types.ts +10 -0
- package/src/events/defineGameEvents.ts +46 -0
- package/src/events/errors.ts +14 -0
- package/src/events/index.ts +14 -0
- package/src/events/payload.ts +234 -0
- package/src/events/seed.ts +33 -0
- package/src/events/types.ts +53 -0
- package/src/events.ts +20 -0
- package/src/geometry/helpers.ts +136 -0
- package/src/geometry/index.ts +14 -0
- package/src/geometry/types.ts +54 -0
- package/src/geometry/validation.ts +131 -0
- package/src/geometry.ts +6 -0
- package/src/haptics/createGameHaptics.ts +214 -0
- package/src/haptics/errors.ts +12 -0
- package/src/haptics/index.ts +3 -0
- package/src/haptics/resolver.ts +58 -0
- package/src/haptics/types.ts +48 -0
- package/src/haptics.ts +7 -0
- package/src/index.ts +37 -1
- package/src/particles/createParticleSystem.ts +505 -0
- package/src/particles/defineParticleEffect.ts +164 -0
- package/src/particles/errors.ts +6 -0
- package/src/particles/index.ts +5 -0
- package/src/particles/sampling.ts +141 -0
- package/src/particles/types.ts +327 -0
- package/src/particles.ts +1 -0
- package/src/react/GameButtonPad.tsx +436 -0
- package/src/react/GamePointerInput.tsx +73 -8
- package/src/react/GameView.tsx +160 -61
- package/src/react/assets/createGameAssetStore.ts +140 -107
- package/src/react/assets/useGameAssets.ts +63 -31
- package/src/react/bindAppLifecycle.ts +55 -19
- package/src/react/bindGameSession.ts +12 -2
- package/src/react/camera2d/GameLayer2D.tsx +43 -0
- package/src/react/camera2d/defineGameCamera2D.ts +59 -0
- package/src/react/camera2d/usePresentedCameraBinding.ts +185 -0
- package/src/react/cleanupList.ts +48 -0
- package/src/react/instrumentation.ts +31 -3
- package/src/react/lifecycleSource.ts +58 -0
- package/src/react/particles/ParticleView.tsx +358 -0
- package/src/react/particles/culling.ts +145 -0
- package/src/react/particles/index.ts +6 -0
- package/src/react/particles/spriteXForm.ts +72 -0
- package/src/react/particles/useParticlePresentation.ts +261 -0
- package/src/react/pointerBinding.ts +74 -16
- package/src/react/pointerCamera.ts +33 -0
- package/src/react/pointerCoalescer.ts +36 -10
- package/src/react/sprites/GameSprite.tsx +4 -33
- package/src/react/sprites/GameWorld2D.tsx +113 -7
- package/src/react/sprites/Sprite.tsx +51 -72
- package/src/react/sprites/SpriteBatch.tsx +74 -22
- package/src/react/sprites/batchVisibility.ts +76 -0
- package/src/react/sprites/spriteSelection.ts +133 -0
- package/src/react/sprites/spriteTransform.ts +46 -26
- package/src/react/tilemap/TileMapLayer2D.tsx +274 -0
- package/src/react/tilemap/tilePresentation.ts +491 -0
- package/src/react/useGameSession.ts +90 -0
- package/src/react/useGameSessionStatus.ts +53 -0
- package/src/react/viewportBinding.ts +5 -1
- package/src/react.ts +18 -1
- package/src/scene/defineScene.ts +47 -5
- package/src/scene/types.ts +37 -3
- package/src/sprites/sampleSpriteClip.ts +82 -14
- package/src/sprites/spriteAnimationState.ts +29 -25
- package/src/sprites.ts +22 -0
- package/src/storage/adapters/asyncStorage.ts +77 -0
- package/src/storage/adapters/memory.ts +58 -0
- package/src/storage/errors.ts +88 -0
- package/src/storage/index.ts +18 -0
- package/src/storage/schema.ts +147 -0
- package/src/storage/serialization.ts +248 -0
- package/src/storage/store.ts +380 -0
- package/src/storage/types.ts +76 -0
- package/src/storage/validation.ts +102 -0
- package/src/storage.ts +1 -0
- package/src/testing.ts +4 -0
- package/src/tilemap/chunkStats.ts +24 -0
- package/src/tilemap/definitions.ts +327 -0
- package/src/tilemap/errors.ts +11 -0
- package/src/tilemap/index.ts +10 -0
- package/src/tilemap/movement.ts +368 -0
- package/src/tilemap/queries.ts +136 -0
- package/src/tilemap/tiledAdapter.ts +165 -0
- package/src/tilemap/types.ts +119 -0
- package/src/tilemap.ts +1 -0
|
@@ -10,12 +10,22 @@
|
|
|
10
10
|
* - `acquire` resolves only with a complete usable lease.
|
|
11
11
|
* - Reference counts keep a shared source alive across leases; the native
|
|
12
12
|
* handle is disposed exactly once when the final lease releases it.
|
|
13
|
+
* - Each reference token releases exactly once, decrements its captured
|
|
14
|
+
* entry (never a fresh URI lookup), and only removes the cache mapping
|
|
15
|
+
* when the mapping still holds that exact entry (GS-ASSET-01/02).
|
|
16
|
+
* - Each acquisition stage has one cleanup owner: a reference transfers to
|
|
17
|
+
* the attempt only after successful validation, so a failed validation
|
|
18
|
+
* releases exactly once and never touches another owner's reference.
|
|
13
19
|
* - A failed/abandoned attempt releases every handle it acquired; entries
|
|
14
20
|
* still leased elsewhere are preserved.
|
|
15
|
-
* -
|
|
16
|
-
*
|
|
21
|
+
* - Stale completion after retry/unmount is rejected by the caller's abort
|
|
22
|
+
* signal and the store's disposed flag; late decodes dispose their own
|
|
23
|
+
* handle without touching a successor entry.
|
|
17
24
|
* - `AbortSignal` detaches an imperative caller immediately; late results
|
|
18
25
|
* from the underlying work are ignored.
|
|
26
|
+
* - Abort/disposed state is checked after the final awaited step and before
|
|
27
|
+
* the lease is published, so an abort racing completion never surfaces
|
|
28
|
+
* a lease for a cancelled request.
|
|
19
29
|
* - Progress is monotonic and counts requested logical resources (a
|
|
20
30
|
* deduplicated source still counts once per logical descriptor).
|
|
21
31
|
* - The store rejects acquisitions after disposal; disposal is idempotent.
|
|
@@ -67,13 +77,12 @@ interface ResourceEntry {
|
|
|
67
77
|
readonly uri: string;
|
|
68
78
|
handle: NativeImageHandle | undefined;
|
|
69
79
|
inFlight: Promise<NativeImageHandle> | undefined;
|
|
70
|
-
/** Logical descriptor keys sharing this resolved source. */
|
|
71
|
-
readonly logicalKeys: Set<string>;
|
|
72
80
|
refCount: number;
|
|
73
81
|
}
|
|
74
82
|
|
|
83
|
+
/** References owned by one in-progress acquisition (GS-ASSET-04: no epoch
|
|
84
|
+
* token — staleness is decided by the caller's abort signal, not a counter). */
|
|
75
85
|
interface Attempt {
|
|
76
|
-
readonly token: number;
|
|
77
86
|
/** Idempotent release closures for every reference this attempt owns. */
|
|
78
87
|
readonly acquired: ResourceRef[];
|
|
79
88
|
}
|
|
@@ -138,10 +147,8 @@ export function createGameAssetStoreCore<TManifest extends AssetGroupMap>(
|
|
|
138
147
|
} {
|
|
139
148
|
const groups = new Set<string>(Object.keys(manifest));
|
|
140
149
|
const logical = logicalAssetsOf(manifest);
|
|
141
|
-
const byKey = new Map<string, LogicalAsset>(logical.map((asset) => [asset.key, asset]));
|
|
142
150
|
const resources = new Map<string, ResourceEntry>();
|
|
143
151
|
let disposed = false;
|
|
144
|
-
let nextAttemptToken = 1;
|
|
145
152
|
/** Per-attempt ownership is explicit: the attempt object is passed through
|
|
146
153
|
* every resolve/decode/validate operation; no shared singleton (R4). */
|
|
147
154
|
|
|
@@ -175,67 +182,63 @@ export function createGameAssetStoreCore<TManifest extends AssetGroupMap>(
|
|
|
175
182
|
});
|
|
176
183
|
}
|
|
177
184
|
|
|
178
|
-
/**
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Drop one reference to the captured entry (GS-ASSET-01/02). The entry
|
|
187
|
+
* object — not a fresh URI lookup — is decremented, and the cache mapping
|
|
188
|
+
* is removed only when it still holds this exact entry, so a stale token
|
|
189
|
+
* can never affect a successor generation for the same URI.
|
|
190
|
+
*/
|
|
191
|
+
function dropResourceRef(entry: ResourceEntry): void {
|
|
184
192
|
entry.refCount -= 1;
|
|
185
193
|
if (entry.refCount <= 0) {
|
|
186
194
|
if (entry.handle !== undefined) {
|
|
187
195
|
entry.handle.dispose();
|
|
188
196
|
}
|
|
189
|
-
resources.
|
|
197
|
+
if (resources.get(entry.uri) === entry) {
|
|
198
|
+
resources.delete(entry.uri);
|
|
199
|
+
}
|
|
190
200
|
}
|
|
191
201
|
}
|
|
192
202
|
|
|
193
203
|
/**
|
|
194
|
-
* Begin one owned reference to a resource. Every waiter —
|
|
195
|
-
* in-flight share, or completed cache hit — goes through this
|
|
196
|
-
* accounting path and receives
|
|
197
|
-
*
|
|
198
|
-
*
|
|
204
|
+
* Begin one owned reference to a resource (GS-ASSET-01). Every waiter —
|
|
205
|
+
* cache miss, in-flight share, or completed cache hit — goes through this
|
|
206
|
+
* single accounting path and receives a token bound to the exact entry
|
|
207
|
+
* object. The token releases exactly once: a flag guards the decrement,
|
|
208
|
+
* so a validation failure (released by its stage) followed by attempt
|
|
209
|
+
* cleanup (releasing the attempt's tokens) can never double-release.
|
|
210
|
+
* The caller must either transfer the token to the attempt or let its
|
|
211
|
+
* owning stage release it exactly once; the final release disposes the
|
|
212
|
+
* native handle.
|
|
199
213
|
*/
|
|
200
|
-
function beginResourceRef(uri: string): ResourceRef {
|
|
214
|
+
function beginResourceRef(uri: string): { readonly ref: ResourceRef; readonly entry: ResourceEntry } {
|
|
201
215
|
const existing = resources.get(uri);
|
|
202
|
-
let entry: ResourceEntry;
|
|
203
216
|
if (existing !== undefined && existing.handle !== undefined) {
|
|
204
217
|
// Completed cache hit.
|
|
205
|
-
|
|
206
|
-
entry
|
|
207
|
-
const handle = existing.handle;
|
|
208
|
-
return {
|
|
209
|
-
release: () => dropResourceRef(uri),
|
|
210
|
-
ready: async () => handle,
|
|
211
|
-
};
|
|
218
|
+
existing.refCount += 1;
|
|
219
|
+
return { ref: idempotentRef(existing), entry: existing };
|
|
212
220
|
}
|
|
213
221
|
if (existing !== undefined && existing.inFlight !== undefined) {
|
|
214
222
|
// Shared in-flight decode.
|
|
215
|
-
|
|
216
|
-
entry
|
|
217
|
-
const shared = existing.inFlight;
|
|
218
|
-
return {
|
|
219
|
-
release: () => dropResourceRef(uri),
|
|
220
|
-
ready: async () => shared,
|
|
221
|
-
};
|
|
223
|
+
existing.refCount += 1;
|
|
224
|
+
return { ref: idempotentRef(existing), entry: existing };
|
|
222
225
|
}
|
|
223
226
|
// Cache miss: this waiter starts the decode.
|
|
224
|
-
entry = {
|
|
227
|
+
const entry: ResourceEntry = {
|
|
225
228
|
uri,
|
|
226
229
|
handle: undefined,
|
|
227
230
|
inFlight: undefined,
|
|
228
|
-
logicalKeys: new Set(),
|
|
229
231
|
refCount: 1,
|
|
230
232
|
};
|
|
231
233
|
resources.set(uri, entry);
|
|
232
234
|
const promise = (async () => {
|
|
233
235
|
const handle = await pipelines.decode(uri);
|
|
234
236
|
// A late completion must never resurrect a disposed store or an entry
|
|
235
|
-
// whose last waiter aborted while the decode was in flight.
|
|
237
|
+
// whose last waiter aborted while the decode was in flight. Identity
|
|
238
|
+
// matters here too: the mapping may now hold a successor entry.
|
|
236
239
|
if (disposed || entry.refCount <= 0) {
|
|
237
240
|
handle.dispose();
|
|
238
|
-
if (entry.refCount <= 0) {
|
|
241
|
+
if (entry.refCount <= 0 && resources.get(uri) === entry) {
|
|
239
242
|
resources.delete(uri);
|
|
240
243
|
}
|
|
241
244
|
throw new AssetStoreError('ASSET_ABORTED', [], 'asset acquisition aborted');
|
|
@@ -244,36 +247,63 @@ export function createGameAssetStoreCore<TManifest extends AssetGroupMap>(
|
|
|
244
247
|
return handle;
|
|
245
248
|
})();
|
|
246
249
|
entry.inFlight = promise;
|
|
247
|
-
void
|
|
248
|
-
()
|
|
249
|
-
entry.inFlight = undefined;
|
|
250
|
-
},
|
|
251
|
-
() => {
|
|
250
|
+
const cleanup = (): void => {
|
|
251
|
+
if (entry.inFlight === promise) {
|
|
252
252
|
entry.inFlight = undefined;
|
|
253
|
-
}
|
|
254
|
-
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
promise.then(cleanup, cleanup);
|
|
256
|
+
const ref = idempotentRef(entry);
|
|
257
|
+
return { ref, entry };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** One release closure bound to its entry; safe to call repeatedly. */
|
|
261
|
+
function idempotentRef(entry: ResourceEntry): ResourceRef {
|
|
262
|
+
let released = false;
|
|
263
|
+
const ready = async (): Promise<NativeImageHandle> => {
|
|
264
|
+
if (entry.handle !== undefined) {
|
|
265
|
+
return entry.handle;
|
|
266
|
+
}
|
|
267
|
+
const inFlight = entry.inFlight;
|
|
268
|
+
if (inFlight === undefined) {
|
|
269
|
+
throw new AssetStoreError(
|
|
270
|
+
'ASSET_DECODE_FAILED',
|
|
271
|
+
[],
|
|
272
|
+
`resource ${JSON.stringify(entry.uri)} has no decoded handle`,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
return inFlight;
|
|
276
|
+
};
|
|
255
277
|
return {
|
|
256
|
-
release: () =>
|
|
257
|
-
|
|
278
|
+
release: () => {
|
|
279
|
+
if (released) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
released = true;
|
|
283
|
+
dropResourceRef(entry);
|
|
284
|
+
},
|
|
285
|
+
ready,
|
|
258
286
|
};
|
|
259
287
|
}
|
|
260
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Acquire one logical asset (GS-ASSET-01). This stage owns its reference
|
|
291
|
+
* until successful validation transfers it to the attempt: on any
|
|
292
|
+
* failure the stage releases exactly once and the token never enters
|
|
293
|
+
* `attempt.acquired`, so attempt cleanup can never release it again.
|
|
294
|
+
* Returns the exact entry backing this asset for the lease table.
|
|
295
|
+
*/
|
|
261
296
|
async function acquireOne(
|
|
262
297
|
asset: LogicalAsset,
|
|
263
298
|
attempt: Attempt,
|
|
264
299
|
signal: AbortSignal | undefined,
|
|
265
|
-
): Promise<
|
|
300
|
+
): Promise<ResourceEntry> {
|
|
266
301
|
const uri = await raceWithAbort(pipelines.resolve(asset.descriptor.source), signal);
|
|
267
302
|
// RF5: the reference token exists before any cancellable await; abort
|
|
268
303
|
// can never leave a positive reference behind.
|
|
269
|
-
const ref = beginResourceRef(uri);
|
|
304
|
+
const { ref, entry } = beginResourceRef(uri);
|
|
270
305
|
try {
|
|
271
306
|
const handle = await raceWithAbort(ref.ready(), signal);
|
|
272
|
-
attempt.acquired.push(ref);
|
|
273
|
-
const entry = resources.get(uri);
|
|
274
|
-
if (entry !== undefined) {
|
|
275
|
-
entry.logicalKeys.add(asset.key);
|
|
276
|
-
}
|
|
277
307
|
if (asset.descriptor.kind === 'sprite-sheet') {
|
|
278
308
|
validateFrames(
|
|
279
309
|
[asset.group, asset.name, 'frames'],
|
|
@@ -282,9 +312,11 @@ export function createGameAssetStoreCore<TManifest extends AssetGroupMap>(
|
|
|
282
312
|
handle.height(),
|
|
283
313
|
);
|
|
284
314
|
}
|
|
315
|
+
// Transfer ownership to the attempt only after validation succeeds.
|
|
316
|
+
attempt.acquired.push(ref);
|
|
317
|
+
return entry;
|
|
285
318
|
} catch (error) {
|
|
286
|
-
//
|
|
287
|
-
// reference exactly once; surviving owners keep theirs.
|
|
319
|
+
// The single owner releases exactly once; surviving owners keep theirs.
|
|
288
320
|
ref.release();
|
|
289
321
|
throw error;
|
|
290
322
|
}
|
|
@@ -321,21 +353,22 @@ export function createGameAssetStoreCore<TManifest extends AssetGroupMap>(
|
|
|
321
353
|
return createLease(new Map(), () => undefined);
|
|
322
354
|
}
|
|
323
355
|
|
|
324
|
-
const
|
|
325
|
-
nextAttemptToken += 1;
|
|
326
|
-
const attempt: Attempt = { token, acquired: [] };
|
|
356
|
+
const attempt: Attempt = { acquired: [] };
|
|
327
357
|
|
|
328
|
-
const loaded = new Map<string,
|
|
358
|
+
const loaded = new Map<string, { readonly asset: LogicalAsset; readonly entry: ResourceEntry }>();
|
|
329
359
|
try {
|
|
330
360
|
let completed = 0;
|
|
331
361
|
const total = requested.length;
|
|
332
362
|
for (const asset of requested) {
|
|
333
363
|
throwIfAborted();
|
|
334
|
-
await acquireOne(asset, attempt, signal);
|
|
335
|
-
loaded.set(asset.key, asset
|
|
364
|
+
const entry = await acquireOne(asset, attempt, signal);
|
|
365
|
+
loaded.set(asset.key, { asset, entry });
|
|
336
366
|
completed += 1;
|
|
337
367
|
options.onProgress?.(completed / total);
|
|
338
368
|
}
|
|
369
|
+
// GS-ASSET-02: an abort racing the final step must surface instead of
|
|
370
|
+
// publishing a lease for a cancelled request.
|
|
371
|
+
throwIfAborted();
|
|
339
372
|
return createLease(loaded, () => {
|
|
340
373
|
for (const ref of attempt.acquired) {
|
|
341
374
|
ref.release();
|
|
@@ -351,17 +384,51 @@ export function createGameAssetStoreCore<TManifest extends AssetGroupMap>(
|
|
|
351
384
|
}
|
|
352
385
|
};
|
|
353
386
|
|
|
387
|
+
/**
|
|
388
|
+
* Build one validated loaded value from the exact entry that backed the
|
|
389
|
+
* acquisition (GS-ASSET-04). The handle is always present: `ready()` only
|
|
390
|
+
* resolves after the entry's handle is set.
|
|
391
|
+
*/
|
|
392
|
+
function loadedValueFor(asset: LogicalAsset, entry: ResourceEntry): LoadedImage | LoadedSpriteSheet {
|
|
393
|
+
const handle = entry.handle;
|
|
394
|
+
if (handle === undefined) {
|
|
395
|
+
// Defensive: reachable only if the store's own accounting is broken.
|
|
396
|
+
// Fail clearly rather than publishing an imageless loaded value.
|
|
397
|
+
throw new AssetStoreError(
|
|
398
|
+
'ASSET_DECODE_FAILED',
|
|
399
|
+
[asset.group, asset.name],
|
|
400
|
+
`resource ${JSON.stringify(entry.uri)} resolved without a decoded handle`,
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
if (asset.descriptor.kind === 'image') {
|
|
404
|
+
return {
|
|
405
|
+
descriptor: asset.descriptor,
|
|
406
|
+
width: handle.width(),
|
|
407
|
+
height: handle.height(),
|
|
408
|
+
image: handle,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
return {
|
|
412
|
+
descriptor: asset.descriptor,
|
|
413
|
+
frames: asset.descriptor.frames,
|
|
414
|
+
width: handle.width(),
|
|
415
|
+
height: handle.height(),
|
|
416
|
+
image: handle,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
354
420
|
function createLease(
|
|
355
|
-
|
|
421
|
+
loaded: ReadonlyMap<string, { readonly asset: LogicalAsset; readonly entry: ResourceEntry }>,
|
|
356
422
|
onDispose: () => void,
|
|
357
423
|
): GameAssetLease<TManifest> {
|
|
358
424
|
let leaseDisposed = false;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
425
|
+
// GS-ASSET-04: the lease holds a direct descriptor→validated value
|
|
426
|
+
// table built once from the captured entries. Lookup is a single map
|
|
427
|
+
// hit: no per-get scans of loaded descriptors or resource key sets,
|
|
428
|
+
// and no wrapper allocated per call.
|
|
429
|
+
const table = new Map<ImageDescriptor | SpriteSheetDescriptor, LoadedImage | LoadedSpriteSheet>();
|
|
430
|
+
for (const { asset, entry } of loaded.values()) {
|
|
431
|
+
table.set(asset.descriptor, loadedValueFor(asset, entry));
|
|
365
432
|
}
|
|
366
433
|
const assets: LoadedAssets<TManifest> = {
|
|
367
434
|
manifest,
|
|
@@ -372,8 +439,8 @@ export function createGameAssetStoreCore<TManifest extends AssetGroupMap>(
|
|
|
372
439
|
if (leaseDisposed) {
|
|
373
440
|
throw new AssetStoreError('ASSET_STORE_DISPOSED', [], 'lease is disposed');
|
|
374
441
|
}
|
|
375
|
-
const
|
|
376
|
-
if (
|
|
442
|
+
const value = table.get(descriptor as ImageDescriptor | SpriteSheetDescriptor);
|
|
443
|
+
if (value === undefined) {
|
|
377
444
|
// R9: v1 lookup is descriptor-reference membership — the exact
|
|
378
445
|
// descriptor object the manifest declared — not a nominal manifest
|
|
379
446
|
// identity. Identically shaped manifests share the structural type,
|
|
@@ -385,7 +452,7 @@ export function createGameAssetStoreCore<TManifest extends AssetGroupMap>(
|
|
|
385
452
|
'descriptor is not a reference declared by this manifest and group selection',
|
|
386
453
|
);
|
|
387
454
|
}
|
|
388
|
-
return
|
|
455
|
+
return value as TDescriptor extends { readonly kind: 'sprite-sheet' }
|
|
389
456
|
? LoadedSpriteSheet
|
|
390
457
|
: LoadedImage;
|
|
391
458
|
},
|
|
@@ -402,40 +469,6 @@ export function createGameAssetStoreCore<TManifest extends AssetGroupMap>(
|
|
|
402
469
|
};
|
|
403
470
|
}
|
|
404
471
|
|
|
405
|
-
function findLoadedFor(
|
|
406
|
-
descriptor: ImageDescriptor | SpriteSheetDescriptor,
|
|
407
|
-
loaded: ReadonlyMap<string, LogicalAsset>,
|
|
408
|
-
): unknown {
|
|
409
|
-
for (const asset of loaded.values()) {
|
|
410
|
-
if (asset.descriptor === descriptor) {
|
|
411
|
-
const entry = entryFor(asset.key);
|
|
412
|
-
const handle = entry?.handle;
|
|
413
|
-
const width = handle?.width() ?? 0;
|
|
414
|
-
const height = handle?.height() ?? 0;
|
|
415
|
-
if (asset.descriptor.kind === 'image') {
|
|
416
|
-
return { descriptor: asset.descriptor, width, height, image: handle };
|
|
417
|
-
}
|
|
418
|
-
return {
|
|
419
|
-
descriptor: asset.descriptor,
|
|
420
|
-
frames: asset.descriptor.frames,
|
|
421
|
-
width,
|
|
422
|
-
height,
|
|
423
|
-
image: handle,
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
return undefined;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
function entryFor(logicalKey: string): ResourceEntry | undefined {
|
|
431
|
-
for (const entry of resources.values()) {
|
|
432
|
-
if (entry.logicalKeys.has(logicalKey)) {
|
|
433
|
-
return entry;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
return undefined;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
472
|
return {
|
|
440
473
|
acquire,
|
|
441
474
|
dispose: () => {
|
|
@@ -13,12 +13,18 @@
|
|
|
13
13
|
* Lifecycle:
|
|
14
14
|
* - The requested group list is normalized (sorted) so a recreated
|
|
15
15
|
* equivalent array does not reload.
|
|
16
|
+
* - Every render executes all hooks unconditionally; when the rendered
|
|
17
|
+
* request differs from the state's request, the hook exposes a fresh
|
|
18
|
+
* loading view synchronously instead of a stale ready lease (GS-ASSET-03).
|
|
19
|
+
* - Request identity combines manifest identity, factory identity,
|
|
20
|
+
* normalized groups, and retry attempt, so a new manifest with identical
|
|
21
|
+
* group names can never expose the previous manifest's lease.
|
|
16
22
|
* - Retry starts a new attempt; late completion from an older attempt can
|
|
17
23
|
* never replace the new state.
|
|
18
24
|
* - Unmount invalidates the attempt, releases the lease, and disposes the
|
|
19
25
|
* store — hook-owned resources are released exactly once.
|
|
20
26
|
*/
|
|
21
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
27
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
22
28
|
|
|
23
29
|
import { GameAssetError } from '../../assets/errors';
|
|
24
30
|
import type { AssetGroupMap, GameAssetLease, LoadedAssets } from '../../assets/types';
|
|
@@ -59,6 +65,23 @@ export function dedupeGroups(groups: readonly string[]): readonly string[] {
|
|
|
59
65
|
return [...new Set(groups)].sort();
|
|
60
66
|
}
|
|
61
67
|
|
|
68
|
+
/** Stable numeric identities for request participants (GS-ASSET-03): object
|
|
69
|
+
* identity, so a new manifest object with identical group names is a new
|
|
70
|
+
* request even when every group string matches. */
|
|
71
|
+
const manifestIdentities = new WeakMap<object, number>();
|
|
72
|
+
const factoryIdentities = new WeakMap<object, number>();
|
|
73
|
+
let nextParticipantId = 1;
|
|
74
|
+
|
|
75
|
+
function participantId(table: WeakMap<object, number>, value: object): number {
|
|
76
|
+
let id = table.get(value);
|
|
77
|
+
if (id === undefined) {
|
|
78
|
+
id = nextParticipantId;
|
|
79
|
+
nextParticipantId += 1;
|
|
80
|
+
table.set(value, id);
|
|
81
|
+
}
|
|
82
|
+
return id;
|
|
83
|
+
}
|
|
84
|
+
|
|
62
85
|
/** Order-independent group key: equivalent arrays map to one key. */
|
|
63
86
|
export function stableGroupsKey(groups: readonly string[]): string {
|
|
64
87
|
return dedupeGroups(groups).join('\u0000');
|
|
@@ -71,11 +94,22 @@ export function useGameAssets<TManifest extends AssetGroupMap>(
|
|
|
71
94
|
): GameAssetsState<TManifest> {
|
|
72
95
|
const groupsKey = stableGroupsKey(options.groups);
|
|
73
96
|
const [attempt, setAttempt] = useState(0);
|
|
97
|
+
// A memoized normalized array: stable across equivalent recreated group
|
|
98
|
+
// arrays, so the effect below never reloads for one (R6).
|
|
99
|
+
const normalizedGroups = useMemo(() => dedupeGroups(options.groups), [groupsKey]);
|
|
100
|
+
// `??` selects a reference, never a new closure, so the default factory
|
|
101
|
+
// keeps a stable identity across renders.
|
|
102
|
+
const factory = storeFactory ?? defaultStoreFactory;
|
|
103
|
+
// GS-ASSET-03/04: the full request identity. Manifest and factory use
|
|
104
|
+
// object identity; groups are normalized; the attempt drives retries.
|
|
105
|
+
const requestKey =
|
|
106
|
+
`${participantId(manifestIdentities, manifest)}:` +
|
|
107
|
+
`${participantId(factoryIdentities, factory)}:${groupsKey}:${attempt}`;
|
|
74
108
|
const [state, setState] = useState<GameAssetsState<TManifest>>({
|
|
75
109
|
status: 'loading',
|
|
76
110
|
progress: 0,
|
|
77
111
|
retry: () => undefined,
|
|
78
|
-
requestKey
|
|
112
|
+
requestKey,
|
|
79
113
|
});
|
|
80
114
|
const storeRef = useRef<HookStore<TManifest> | undefined>(undefined);
|
|
81
115
|
const leaseRef = useRef<GameAssetLease<TManifest> | undefined>(undefined);
|
|
@@ -85,27 +119,17 @@ export function useGameAssets<TManifest extends AssetGroupMap>(
|
|
|
85
119
|
setAttempt((current) => current + 1);
|
|
86
120
|
}, []);
|
|
87
121
|
|
|
88
|
-
// Ref mirror of the attempt so stale-effect completions are rejected
|
|
89
|
-
// after a retry re-renders with a higher attempt.
|
|
90
|
-
const attemptRef = useRef(attempt);
|
|
91
|
-
attemptRef.current = attempt;
|
|
92
|
-
|
|
93
|
-
// RF7: if the rendered request differs from the state's request, expose
|
|
94
|
-
// loading synchronously instead of the previous ready lease — the old
|
|
95
|
-
// lease is disposed by the effect cleanup, so no consumer can observe it
|
|
96
|
-
// under the new request.
|
|
97
|
-
if (state.requestKey !== groupsKey && state.status === 'ready') {
|
|
98
|
-
return { status: 'loading', progress: 0, retry, requestKey: groupsKey };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
122
|
useEffect(() => {
|
|
102
|
-
const store = (
|
|
123
|
+
const store = factory(manifest);
|
|
103
124
|
storeRef.current = store;
|
|
125
|
+
// Per-effect invalidation (GS-ASSET-03): cleanup sets `disposed` before
|
|
126
|
+
// any newer effect runs, so stale completions are rejected without a
|
|
127
|
+
// render-time ref mutation standing in for ownership.
|
|
104
128
|
let disposed = false;
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (!disposed
|
|
129
|
+
const setIfCurrent = (
|
|
130
|
+
updater: (previous: GameAssetsState<TManifest>) => GameAssetsState<TManifest>,
|
|
131
|
+
): void => {
|
|
132
|
+
if (!disposed) {
|
|
109
133
|
setState(updater);
|
|
110
134
|
}
|
|
111
135
|
};
|
|
@@ -118,38 +142,40 @@ export function useGameAssets<TManifest extends AssetGroupMap>(
|
|
|
118
142
|
status: 'loading',
|
|
119
143
|
progress: 0,
|
|
120
144
|
retry: retry,
|
|
121
|
-
requestKey
|
|
145
|
+
requestKey,
|
|
122
146
|
});
|
|
123
147
|
|
|
124
148
|
store
|
|
125
149
|
.acquire({
|
|
126
|
-
groups:
|
|
150
|
+
groups: normalizedGroups,
|
|
127
151
|
signal: controller.signal,
|
|
128
152
|
onProgress: (progress) => {
|
|
129
153
|
setIfCurrent((previous) =>
|
|
130
|
-
previous.status === 'loading'
|
|
154
|
+
previous.status === 'loading' && previous.requestKey === requestKey
|
|
155
|
+
? { ...previous, progress }
|
|
156
|
+
: previous,
|
|
131
157
|
);
|
|
132
158
|
},
|
|
133
159
|
})
|
|
134
160
|
.then((lease) => {
|
|
135
|
-
if (disposed
|
|
161
|
+
if (disposed) {
|
|
136
162
|
// Stale completion (retry/unmount): release immediately.
|
|
137
163
|
lease.dispose();
|
|
138
164
|
return;
|
|
139
165
|
}
|
|
140
166
|
leaseRef.current?.dispose();
|
|
141
167
|
leaseRef.current = lease;
|
|
142
|
-
setState({ status: 'ready', assets: lease.assets, requestKey
|
|
168
|
+
setState({ status: 'ready', assets: lease.assets, requestKey });
|
|
143
169
|
})
|
|
144
170
|
.catch((error: unknown) => {
|
|
145
|
-
if (disposed
|
|
171
|
+
if (disposed) {
|
|
146
172
|
return;
|
|
147
173
|
}
|
|
148
174
|
const structured =
|
|
149
175
|
error instanceof GameAssetError
|
|
150
176
|
? error
|
|
151
177
|
: new GameAssetError('ASSET_DECODE_FAILED', [], error instanceof Error ? error.message : String(error));
|
|
152
|
-
setState({ status: 'error', error: structured, retry, requestKey
|
|
178
|
+
setState({ status: 'error', error: structured, retry, requestKey });
|
|
153
179
|
});
|
|
154
180
|
|
|
155
181
|
return () => {
|
|
@@ -162,10 +188,16 @@ export function useGameAssets<TManifest extends AssetGroupMap>(
|
|
|
162
188
|
storeRef.current = undefined;
|
|
163
189
|
store.dispose();
|
|
164
190
|
};
|
|
165
|
-
// The
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
|
|
191
|
+
// The effect re-runs only when the request identity (or its stable
|
|
192
|
+
// derivatives) changes; equivalent recreated group arrays do not reload.
|
|
193
|
+
}, [requestKey, manifest, factory, normalizedGroups, groupsKey, retry]);
|
|
194
|
+
|
|
195
|
+
// GS-ASSET-03: every hook above runs unconditionally. When the rendered
|
|
196
|
+
// request differs from the state's request, expose a fresh loading view
|
|
197
|
+
// synchronously — never a stale ready lease, error, or progress.
|
|
198
|
+
if (state.requestKey !== requestKey) {
|
|
199
|
+
return { status: 'loading', progress: 0, retry, requestKey };
|
|
200
|
+
}
|
|
169
201
|
|
|
170
202
|
return state;
|
|
171
203
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { GameSessionStatus } from '../core/session/types';
|
|
1
|
+
import type { GameSessionStatus, GameSubscription } from '../core/session/types';
|
|
2
|
+
import { createCleanupList } from './cleanupList';
|
|
2
3
|
|
|
3
4
|
/** Minimal AppState-like source used to keep this seam platform-neutral. */
|
|
4
5
|
export interface AppLifecycleSource {
|
|
@@ -18,6 +19,12 @@ export interface AppLifecycleSession {
|
|
|
18
19
|
pause(): void;
|
|
19
20
|
/** Resume a paused session. */
|
|
20
21
|
resume(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Optional status observation (T10.6): when present, the binder also
|
|
24
|
+
* guards against an external `start()` while the host is inactive, so a
|
|
25
|
+
* frame loop can never escape into the background.
|
|
26
|
+
*/
|
|
27
|
+
addStatusListener?(listener: (status: GameSessionStatus) => void): GameSubscription;
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
/**
|
|
@@ -36,7 +43,14 @@ export function bindAppLifecycle(
|
|
|
36
43
|
source: AppLifecycleSource,
|
|
37
44
|
session: AppLifecycleSession,
|
|
38
45
|
): () => void {
|
|
46
|
+
// GS-REACT-02: setup is transactional — every stage registers its release
|
|
47
|
+
// as it completes, so a later failure unwinds everything acquired so far.
|
|
48
|
+
const cleanups = createCleanupList();
|
|
39
49
|
let pausedByLifecycle = false;
|
|
50
|
+
let currentState = source.currentState ?? 'active';
|
|
51
|
+
|
|
52
|
+
const isInactive = (state: string | null | undefined): boolean =>
|
|
53
|
+
state === 'inactive' || state === 'background';
|
|
40
54
|
|
|
41
55
|
const pauseForBackground = () => {
|
|
42
56
|
if (session.getStatus() === 'running') {
|
|
@@ -45,27 +59,49 @@ export function bindAppLifecycle(
|
|
|
45
59
|
}
|
|
46
60
|
};
|
|
47
61
|
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (session.getStatus() === 'paused') {
|
|
60
|
-
session.resume();
|
|
62
|
+
// T10.6: an external start() while the host is inactive is deterministically
|
|
63
|
+
// returned to paused. The binder observes status transitions and re-pauses
|
|
64
|
+
// any running transition that happens while the app is not active, so a
|
|
65
|
+
// frame loop cannot escape into the background.
|
|
66
|
+
let statusSubscription: GameSubscription | undefined;
|
|
67
|
+
try {
|
|
68
|
+
if (session.addStatusListener !== undefined) {
|
|
69
|
+
statusSubscription = session.addStatusListener((status) => {
|
|
70
|
+
if (status === 'running' && isInactive(currentState)) {
|
|
71
|
+
session.pause();
|
|
72
|
+
pausedByLifecycle = true;
|
|
61
73
|
}
|
|
62
|
-
}
|
|
63
|
-
|
|
74
|
+
});
|
|
75
|
+
cleanups.add(() => statusSubscription?.remove());
|
|
64
76
|
}
|
|
65
|
-
|
|
77
|
+
|
|
78
|
+
// Synchronize the initial app state before any change event arrives.
|
|
79
|
+
if (isInactive(source.currentState)) {
|
|
66
80
|
pauseForBackground();
|
|
67
81
|
}
|
|
68
|
-
|
|
82
|
+
|
|
83
|
+
const subscription = source.addEventListener('change', (next) => {
|
|
84
|
+
currentState = next;
|
|
85
|
+
if (next === 'active') {
|
|
86
|
+
if (pausedByLifecycle) {
|
|
87
|
+
pausedByLifecycle = false;
|
|
88
|
+
// Resume only if the session is still paused; a different actor may
|
|
89
|
+
// have resumed or disposed it while the app was backgrounded.
|
|
90
|
+
if (session.getStatus() === 'paused') {
|
|
91
|
+
session.resume();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (isInactive(next)) {
|
|
97
|
+
pauseForBackground();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
cleanups.add(() => subscription.remove());
|
|
101
|
+
} catch (error) {
|
|
102
|
+
cleanups.releaseAll();
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
69
105
|
|
|
70
106
|
let cleanedUp = false;
|
|
71
107
|
return () => {
|
|
@@ -73,7 +109,7 @@ export function bindAppLifecycle(
|
|
|
73
109
|
return;
|
|
74
110
|
}
|
|
75
111
|
cleanedUp = true;
|
|
76
|
-
|
|
112
|
+
cleanups.releaseAll();
|
|
77
113
|
pausedByLifecycle = false;
|
|
78
114
|
};
|
|
79
115
|
}
|