@jgengine/core 0.9.0 → 0.11.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 +34 -3
- package/LICENSE +203 -661
- package/README.md +1 -1
- package/dist/ai/crowd.d.ts +55 -0
- package/dist/ai/crowd.js +114 -0
- package/dist/ai/flock.d.ts +5 -2
- package/dist/ai/flock.js +5 -2
- package/dist/ai/groupAssist.d.ts +1 -0
- package/dist/ai/groupAssist.js +1 -0
- package/dist/ai/heatSystem.d.ts +76 -0
- package/dist/ai/heatSystem.js +97 -0
- package/dist/ai/interestScheduler.d.ts +107 -0
- package/dist/ai/interestScheduler.js +118 -0
- package/dist/ai/jobBoard.d.ts +1 -0
- package/dist/ai/jobBoard.js +1 -0
- package/dist/ai/laneSelect.d.ts +5 -2
- package/dist/ai/laneSelect.js +5 -2
- package/dist/ai/mobBrain.d.ts +1 -0
- package/dist/ai/mobBrain.js +1 -0
- package/dist/ai/spawnDirector.d.ts +19 -1
- package/dist/ai/spawnDirector.js +53 -26
- package/dist/ai/spawnPoint.d.ts +7 -0
- package/dist/ai/spawnPoint.js +7 -0
- package/dist/ai/targetAcquisition.d.ts +84 -0
- package/dist/ai/targetAcquisition.js +92 -0
- package/dist/anim/easing.d.ts +19 -0
- package/dist/anim/easing.js +19 -0
- package/dist/anim/oscillator.d.ts +12 -0
- package/dist/anim/oscillator.js +25 -0
- package/dist/area/areaEffectField.d.ts +127 -0
- package/dist/area/areaEffectField.js +175 -0
- package/dist/area/stackPolicy.d.ts +47 -0
- package/dist/area/stackPolicy.js +99 -0
- package/dist/audio/audioFalloff.d.ts +5 -2
- package/dist/audio/music.d.ts +53 -0
- package/dist/audio/music.js +34 -0
- package/dist/audio/synth.d.ts +60 -0
- package/dist/audio/synth.js +8 -0
- package/dist/authoring.d.ts +15 -0
- package/dist/authoring.js +15 -0
- package/dist/board/laneBoard.d.ts +13 -0
- package/dist/board/laneBoard.js +13 -0
- package/dist/board/timelineBoard.d.ts +10 -0
- package/dist/board/timelineBoard.js +10 -0
- package/dist/combat/abilityKit.d.ts +18 -0
- package/dist/combat/abilityKit.js +24 -9
- package/dist/combat/animationState.d.ts +5 -0
- package/dist/combat/animationState.js +5 -0
- package/dist/combat/breakMeters.d.ts +10 -0
- package/dist/combat/breakMeters.js +10 -0
- package/dist/combat/castRunner.d.ts +5 -0
- package/dist/combat/castRunner.js +5 -0
- package/dist/combat/comboPoints.d.ts +5 -0
- package/dist/combat/comboPoints.js +5 -0
- package/dist/combat/comboString.d.ts +5 -0
- package/dist/combat/comboString.js +5 -0
- package/dist/combat/damageInterceptors.d.ts +192 -0
- package/dist/combat/damageInterceptors.js +251 -0
- package/dist/combat/damageMatchup.d.ts +68 -0
- package/dist/combat/damageMatchup.js +42 -0
- package/dist/combat/damageResolution.d.ts +63 -0
- package/dist/combat/damageResolution.js +50 -0
- package/dist/combat/death.d.ts +7 -1
- package/dist/combat/death.js +5 -0
- package/dist/combat/deathReason.d.ts +14 -0
- package/dist/combat/deathReason.js +1 -0
- package/dist/combat/defensiveWindow.d.ts +5 -0
- package/dist/combat/defensiveWindow.js +5 -0
- package/dist/combat/dotField.d.ts +47 -0
- package/dist/combat/dotField.js +52 -0
- package/dist/combat/downed.d.ts +5 -0
- package/dist/combat/downed.js +5 -0
- package/dist/combat/effects.d.ts +5 -0
- package/dist/combat/effects.js +5 -0
- package/dist/combat/encounterSequence.d.ts +258 -0
- package/dist/combat/encounterSequence.js +426 -0
- package/dist/combat/hitReaction.d.ts +57 -1
- package/dist/combat/hitReaction.js +45 -5
- package/dist/combat/magazine.d.ts +54 -0
- package/dist/combat/magazine.js +96 -0
- package/dist/combat/projectiles.d.ts +7 -2
- package/dist/combat/projectiles.js +48 -17
- package/dist/combat/receivedDamage.d.ts +117 -0
- package/dist/combat/receivedDamage.js +92 -0
- package/dist/combat/regenShield.d.ts +39 -0
- package/dist/combat/regenShield.js +49 -0
- package/dist/combat/renderCues.d.ts +51 -0
- package/dist/combat/renderCues.js +44 -0
- package/dist/combat/resourcePool.d.ts +5 -0
- package/dist/combat/resourcePool.js +5 -0
- package/dist/combat/rewardAllocation.d.ts +121 -0
- package/dist/combat/rewardAllocation.js +251 -0
- package/dist/combat/shotOrigin.d.ts +30 -1
- package/dist/combat/shotOrigin.js +70 -2
- package/dist/combat/statusApplication.d.ts +96 -0
- package/dist/combat/statusApplication.js +81 -0
- package/dist/combat/telegraph.d.ts +11 -2
- package/dist/combat/telegraph.js +11 -2
- package/dist/combat/thresholdCrossings.d.ts +85 -0
- package/dist/combat/thresholdCrossings.js +116 -0
- package/dist/combat.d.ts +34 -0
- package/dist/combat.js +34 -0
- package/dist/commands/commandRegistry.d.ts +11 -0
- package/dist/commands/commandRegistry.js +9 -2
- package/dist/crafting/crop.d.ts +18 -0
- package/dist/crafting/crop.js +18 -0
- package/dist/crafting/production.d.ts +5 -0
- package/dist/crafting/production.js +5 -0
- package/dist/devtools/rewriteTunables.d.ts +17 -0
- package/dist/devtools/rewriteTunables.js +276 -0
- package/dist/devtools/saveEndpoint.d.ts +46 -0
- package/dist/devtools/saveEndpoint.js +48 -0
- package/dist/devtools/transformTunables.d.ts +3 -0
- package/dist/devtools/transformTunables.js +3 -0
- package/dist/devtools/tunableSchema.d.ts +31 -0
- package/dist/devtools/tunableSchema.js +31 -0
- package/dist/economy/currency.d.ts +12 -1
- package/dist/economy/currency.js +12 -1
- package/dist/economy/listingBook.d.ts +91 -0
- package/dist/economy/listingBook.js +144 -0
- package/dist/economy/resourceLedger.d.ts +222 -0
- package/dist/economy/resourceLedger.js +353 -0
- package/dist/economy/sharedWallet.d.ts +14 -0
- package/dist/economy/sharedWallet.js +14 -0
- package/dist/economy/techTree.d.ts +12 -0
- package/dist/economy/techTree.js +12 -0
- package/dist/economy/wallet.d.ts +26 -2
- package/dist/economy/wallet.js +35 -6
- package/dist/editor/commands.d.ts +248 -0
- package/dist/editor/commands.js +865 -0
- package/dist/editor/document.d.ts +186 -0
- package/dist/editor/document.js +884 -0
- package/dist/editor/grid.d.ts +229 -0
- package/dist/editor/grid.js +366 -0
- package/dist/editor/gridAdapters.d.ts +80 -0
- package/dist/editor/gridAdapters.js +134 -0
- package/dist/editor/index.d.ts +97 -0
- package/dist/editor/index.js +10 -0
- package/dist/editor/liveSync.d.ts +127 -0
- package/dist/editor/liveSync.js +249 -0
- package/dist/editor/runtimeInspector.d.ts +88 -0
- package/dist/editor/runtimeInspector.js +239 -0
- package/dist/editor/types.d.ts +175 -0
- package/dist/editor/types.js +29 -0
- package/dist/faction/reputation.d.ts +5 -0
- package/dist/faction/reputation.js +5 -0
- package/dist/format/distance.d.ts +17 -0
- package/dist/format/distance.js +18 -0
- package/dist/format/duration.d.ts +27 -0
- package/dist/format/duration.js +45 -0
- package/dist/format/speed.d.ts +17 -0
- package/dist/format/speed.js +25 -0
- package/dist/game/connectedPlayers.d.ts +30 -0
- package/dist/game/connectedPlayers.js +21 -0
- package/dist/game/cosmetics.d.ts +9 -0
- package/dist/game/cosmetics.js +16 -0
- package/dist/game/defineGame.d.ts +141 -2
- package/dist/game/defineGame.js +39 -1
- package/dist/game/defineSystem.d.ts +88 -0
- package/dist/game/defineSystem.js +45 -0
- package/dist/game/dialogue.d.ts +33 -0
- package/dist/game/dialogue.js +21 -0
- package/dist/game/events.d.ts +50 -13
- package/dist/game/events.js +5 -0
- package/dist/game/feed.d.ts +33 -0
- package/dist/game/feed.js +35 -2
- package/dist/game/gamePhase.d.ts +11 -0
- package/dist/game/gamePhase.js +16 -0
- package/dist/game/keyValueStore.d.ts +25 -0
- package/dist/game/keyValueStore.js +61 -0
- package/dist/game/leaderboard.d.ts +5 -0
- package/dist/game/leaderboard.js +5 -0
- package/dist/game/levelSequence.d.ts +24 -2
- package/dist/game/levelSequence.js +51 -2
- package/dist/game/loadout.d.ts +5 -0
- package/dist/game/loadout.js +5 -0
- package/dist/game/lootFilter.d.ts +2 -0
- package/dist/game/lootFilter.js +2 -0
- package/dist/game/lootPipeline.d.ts +164 -0
- package/dist/game/lootPipeline.js +216 -0
- package/dist/game/lootTable.d.ts +21 -0
- package/dist/game/lootTable.js +15 -4
- package/dist/game/modelAnimation.d.ts +8 -0
- package/dist/game/modelAnimation.js +18 -0
- package/dist/game/objectives.d.ts +43 -0
- package/dist/game/objectives.js +36 -0
- package/dist/game/paramLayers.d.ts +148 -0
- package/dist/game/paramLayers.js +185 -0
- package/dist/game/ping.d.ts +5 -0
- package/dist/game/ping.js +5 -0
- package/dist/game/playableGame.d.ts +160 -12
- package/dist/game/quest.d.ts +8 -0
- package/dist/game/quest.js +29 -0
- package/dist/game/race.d.ts +141 -0
- package/dist/game/race.js +169 -0
- package/dist/game/recordBook.d.ts +5 -5
- package/dist/game/recordBook.js +4 -1
- package/dist/game/ruleSelection.d.ts +75 -0
- package/dist/game/ruleSelection.js +127 -0
- package/dist/game/runDraft.d.ts +5 -0
- package/dist/game/runDraft.js +5 -0
- package/dist/game/saveStore.d.ts +111 -0
- package/dist/game/saveStore.js +312 -0
- package/dist/game/snapshotHistory.d.ts +67 -0
- package/dist/game/snapshotHistory.js +95 -0
- package/dist/game/social.d.ts +38 -1
- package/dist/game/social.js +71 -0
- package/dist/game/spawnPoints.d.ts +5 -0
- package/dist/game/spawnPoints.js +5 -0
- package/dist/game/systemRuntime.d.ts +50 -0
- package/dist/game/systemRuntime.js +157 -0
- package/dist/game/systemSchedule.d.ts +72 -0
- package/dist/game/systemSchedule.js +242 -0
- package/dist/game/toasts.d.ts +43 -0
- package/dist/game/toasts.js +44 -0
- package/dist/game/trade.d.ts +10 -0
- package/dist/game/trade.js +10 -0
- package/dist/game/unlocks.d.ts +8 -0
- package/dist/game/unlocks.js +16 -0
- package/dist/game/vfxInstance.d.ts +138 -0
- package/dist/game/vfxInstance.js +96 -0
- package/dist/game/worldItem.d.ts +17 -4
- package/dist/game/worldItem.js +17 -4
- package/dist/gameplay.d.ts +91 -0
- package/dist/gameplay.js +91 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.js +5 -7
- package/dist/input/actionBindings.d.ts +24 -5
- package/dist/input/actionBindings.js +23 -5
- package/dist/input/axisInput.d.ts +13 -1
- package/dist/input/axisInput.js +22 -1
- package/dist/input/controlGroups.d.ts +67 -0
- package/dist/input/controlGroups.js +41 -0
- package/dist/input/touchScheme.d.ts +82 -6
- package/dist/input/touchScheme.js +123 -10
- package/dist/interaction/contextMenu.d.ts +1 -0
- package/dist/interaction/contextMenu.js +1 -0
- package/dist/interaction/lockpick.d.ts +61 -0
- package/dist/interaction/lockpick.js +168 -0
- package/dist/interaction/proximityPrompt.d.ts +5 -1
- package/dist/interaction/proximityPrompt.js +5 -3
- package/dist/interaction/qte.d.ts +5 -0
- package/dist/interaction/qte.js +5 -0
- package/dist/interaction/skillCheck.d.ts +5 -0
- package/dist/interaction/skillCheck.js +5 -0
- package/dist/inventory/inventoryModel.d.ts +12 -0
- package/dist/inventory/inventoryModel.js +12 -0
- package/dist/inventory/shapedGrid.d.ts +16 -0
- package/dist/inventory/shapedGrid.js +16 -0
- package/dist/inventory/slotModel.d.ts +10 -0
- package/dist/inventory/slotModel.js +10 -0
- package/dist/item/durability.d.ts +5 -0
- package/dist/item/durability.js +5 -0
- package/dist/item/itemIdentity.d.ts +171 -0
- package/dist/item/itemIdentity.js +138 -0
- package/dist/item/itemInstanceRegistry.d.ts +32 -0
- package/dist/item/itemInstanceRegistry.js +34 -0
- package/dist/item/itemgen.d.ts +163 -0
- package/dist/item/itemgen.js +151 -0
- package/dist/item/modularItem.d.ts +5 -0
- package/dist/item/modularItem.js +5 -0
- package/dist/item/use.d.ts +5 -0
- package/dist/item/use.js +5 -0
- package/dist/item/useBehavior.d.ts +142 -0
- package/dist/item/useBehavior.js +105 -0
- package/dist/item/weapon.d.ts +5 -0
- package/dist/item/weapon.js +5 -0
- package/dist/math/scalar.d.ts +25 -0
- package/dist/math/scalar.js +47 -0
- package/dist/meta/changelog.d.ts +4 -1
- package/dist/meta/changelog.js +36 -1
- package/dist/movement/avoidance.d.ts +45 -0
- package/dist/movement/avoidance.js +123 -0
- package/dist/movement/cameraRig.d.ts +8 -0
- package/dist/movement/cameraRig.js +8 -0
- package/dist/movement/dash.d.ts +11 -0
- package/dist/movement/dash.js +11 -0
- package/dist/movement/formation.d.ts +135 -0
- package/dist/movement/formation.js +194 -0
- package/dist/movement/glideModel.d.ts +5 -0
- package/dist/movement/glideModel.js +5 -0
- package/dist/movement/grappleSwing.d.ts +5 -0
- package/dist/movement/grappleSwing.js +5 -0
- package/dist/movement/leaderTrail.d.ts +5 -0
- package/dist/movement/leaderTrail.js +5 -0
- package/dist/movement/movementModel.d.ts +38 -7
- package/dist/movement/movementModel.js +54 -13
- package/dist/movement/playerMovement.d.ts +41 -0
- package/dist/movement/playerMovement.js +236 -0
- package/dist/movement/poseState.d.ts +13 -0
- package/dist/movement/poseState.js +16 -0
- package/dist/movement/steering.d.ts +8 -0
- package/dist/movement/steering.js +18 -0
- package/dist/multiplayer/combatSnapshot.d.ts +3 -0
- package/dist/multiplayer/combatSnapshot.js +3 -0
- package/dist/multiplayer/lagCompensation.d.ts +5 -0
- package/dist/multiplayer/lagCompensation.js +5 -0
- package/dist/multiplayer/presenceModel.d.ts +9 -1
- package/dist/multiplayer/presenceModel.js +9 -1
- package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
- package/dist/multiplayer/simultaneousCommit.js +3 -0
- package/dist/multiplayer.d.ts +11 -0
- package/dist/multiplayer.js +11 -0
- package/dist/nav/pathFollow.d.ts +57 -0
- package/dist/nav/pathFollow.js +109 -0
- package/dist/orders/orderKinds.d.ts +156 -0
- package/dist/orders/orderKinds.js +197 -0
- package/dist/orders/orderQueue.d.ts +208 -0
- package/dist/orders/orderQueue.js +211 -0
- package/dist/physics/drivableVehicle.d.ts +29 -0
- package/dist/physics/drivableVehicle.js +16 -0
- package/dist/physics/kinematicVehicle.d.ts +21 -1
- package/dist/physics/kinematicVehicle.js +23 -8
- package/dist/physics/physicsWorld.d.ts +24 -12
- package/dist/physics/physicsWorld.js +11 -5
- package/dist/physics/radialImpulse.d.ts +25 -0
- package/dist/physics/radialImpulse.js +27 -0
- package/dist/procedural.d.ts +3 -0
- package/dist/procedural.js +3 -0
- package/dist/progression/statGraph.d.ts +116 -0
- package/dist/progression/statGraph.js +318 -0
- package/dist/puzzle/cellGrid.d.ts +9 -0
- package/dist/puzzle/cellGrid.js +9 -0
- package/dist/puzzle/fallingPiece.d.ts +9 -0
- package/dist/puzzle/fallingPiece.js +9 -0
- package/dist/puzzle/nonogram.d.ts +39 -0
- package/dist/puzzle/nonogram.js +136 -0
- package/dist/random/nameGen.d.ts +5 -0
- package/dist/random/nameGen.js +5 -0
- package/dist/random/pick.d.ts +8 -0
- package/dist/random/pick.js +31 -0
- package/dist/random/rng.d.ts +24 -0
- package/dist/random/rng.js +30 -8
- package/dist/random/seedLink.d.ts +4 -0
- package/dist/random/seedLink.js +4 -0
- package/dist/relation/keyedValues.d.ts +54 -0
- package/dist/relation/keyedValues.js +115 -0
- package/dist/relation/thresholds.d.ts +62 -0
- package/dist/relation/thresholds.js +62 -0
- package/dist/render/color.d.ts +12 -0
- package/dist/render/color.js +26 -0
- package/dist/render/lookPreset.d.ts +41 -0
- package/dist/render/lookPreset.js +29 -0
- package/dist/render/postProcessing.d.ts +76 -0
- package/dist/render/postProcessing.js +21 -0
- package/dist/rules/predicate.d.ts +53 -0
- package/dist/rules/predicate.js +64 -0
- package/dist/rules/ruleEffects.d.ts +38 -0
- package/dist/rules/ruleEffects.js +37 -0
- package/dist/rules/triggeredRules.d.ts +160 -0
- package/dist/rules/triggeredRules.js +241 -0
- package/dist/runtime/adapter.d.ts +58 -0
- package/dist/runtime/adapter.js +54 -5
- package/dist/runtime/cameraDirector.d.ts +1 -0
- package/dist/runtime/cameraDirector.js +1 -0
- package/dist/runtime/commandRunner.d.ts +1 -0
- package/dist/runtime/commandRunner.js +1 -0
- package/dist/runtime/context/combatFx.d.ts +23 -0
- package/dist/runtime/context/combatFx.js +161 -0
- package/dist/runtime/context/registries.d.ts +13 -0
- package/dist/runtime/context/registries.js +84 -0
- package/dist/runtime/context/worldItems.d.ts +21 -0
- package/dist/runtime/context/worldItems.js +37 -0
- package/dist/runtime/descriptors/baseline.d.ts +48 -0
- package/dist/runtime/descriptors/baseline.js +134 -0
- package/dist/runtime/descriptors/features.d.ts +74 -0
- package/dist/runtime/descriptors/features.js +281 -0
- package/dist/runtime/gameContext.d.ts +163 -19
- package/dist/runtime/gameContext.js +385 -339
- package/dist/runtime/gameRuntime.d.ts +1 -0
- package/dist/runtime/gameRuntime.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +60 -0
- package/dist/runtime/headlessRunner.js +44 -0
- package/dist/runtime/hostPersistence.d.ts +12 -0
- package/dist/runtime/hostPersistence.js +12 -0
- package/dist/runtime/hostedGameRunner.d.ts +54 -0
- package/dist/runtime/hostedGameRunner.js +85 -0
- package/dist/runtime/hostedWorldSession.d.ts +73 -0
- package/dist/runtime/hostedWorldSession.js +64 -0
- package/dist/runtime/inputSnapshot.d.ts +21 -3
- package/dist/runtime/inputSnapshot.js +8 -2
- package/dist/runtime/motionIntents.d.ts +12 -1
- package/dist/runtime/motionIntents.js +26 -1
- package/dist/runtime/perContext.d.ts +15 -0
- package/dist/runtime/perContext.js +21 -0
- package/dist/runtime/runtimeSave.d.ts +79 -0
- package/dist/runtime/runtimeSave.js +105 -0
- package/dist/runtime/save.d.ts +4 -0
- package/dist/runtime/save.js +4 -0
- package/dist/runtime/snapshot.d.ts +7 -0
- package/dist/runtime/snapshot.js +7 -0
- package/dist/runtime/visibility.d.ts +2 -1
- package/dist/runtime/visibility.js +2 -1
- package/dist/runtime/worldChannel.d.ts +62 -0
- package/dist/runtime/worldChannel.js +114 -0
- package/dist/runtime/worldMirror.d.ts +36 -0
- package/dist/runtime/worldMirror.js +44 -0
- package/dist/runtime/worldProjection.d.ts +47 -0
- package/dist/runtime/worldProjection.js +52 -0
- package/dist/runtime/worldReplication.d.ts +69 -0
- package/dist/runtime/worldReplication.js +217 -0
- package/dist/runtime/worldSnapshot.d.ts +44 -0
- package/dist/runtime/worldSnapshot.js +30 -0
- package/dist/scene/assetCatalog.d.ts +22 -0
- package/dist/scene/assetCatalog.js +4 -0
- package/dist/scene/assetDiagnostics.d.ts +69 -0
- package/dist/scene/assetDiagnostics.js +110 -0
- package/dist/scene/assetGenerator.d.ts +65 -0
- package/dist/scene/assetGenerator.js +64 -0
- package/dist/scene/assetSpace.d.ts +137 -0
- package/dist/scene/assetSpace.js +259 -0
- package/dist/scene/authoredTriggers.d.ts +169 -0
- package/dist/scene/authoredTriggers.js +340 -0
- package/dist/scene/behaviorRuntime.d.ts +75 -0
- package/dist/scene/behaviorRuntime.js +217 -0
- package/dist/scene/behaviors.d.ts +14 -2
- package/dist/scene/behaviors.js +7 -2
- package/dist/scene/bodyBind.d.ts +60 -0
- package/dist/scene/bodyBind.js +51 -0
- package/dist/scene/builtinSceneKinds.d.ts +5 -0
- package/dist/scene/builtinSceneKinds.js +62 -0
- package/dist/scene/colliders.d.ts +18 -0
- package/dist/scene/colliders.js +61 -1
- package/dist/scene/entityStats.d.ts +13 -0
- package/dist/scene/entityStats.js +30 -0
- package/dist/scene/entityStore.d.ts +41 -1
- package/dist/scene/entityStore.js +75 -0
- package/dist/scene/facing.d.ts +18 -0
- package/dist/scene/facing.js +26 -0
- package/dist/scene/modelSockets.d.ts +33 -0
- package/dist/scene/modelSockets.js +29 -0
- package/dist/scene/objectQuery.d.ts +2 -0
- package/dist/scene/objectQuery.js +2 -0
- package/dist/scene/objectStore.d.ts +4 -0
- package/dist/scene/objectStore.js +6 -0
- package/dist/scene/possession.d.ts +8 -0
- package/dist/scene/possession.js +14 -0
- package/dist/scene/roster.d.ts +3 -0
- package/dist/scene/roster.js +12 -0
- package/dist/scene/sceneKinds.d.ts +240 -0
- package/dist/scene/sceneKinds.js +214 -0
- package/dist/scene/sceneOwnership.d.ts +169 -0
- package/dist/scene/sceneOwnership.js +179 -0
- package/dist/scene/selectionBookmarks.d.ts +93 -0
- package/dist/scene/selectionBookmarks.js +122 -0
- package/dist/scene/vehicleSeat.d.ts +68 -0
- package/dist/scene/vehicleSeat.js +59 -0
- package/dist/sensor/concealment.d.ts +3 -0
- package/dist/sensor/concealment.js +3 -0
- package/dist/sensor/freezeMonitor.d.ts +1 -0
- package/dist/sensor/freezeMonitor.js +1 -0
- package/dist/sensor/frustumSensor.d.ts +7 -3
- package/dist/sensor/frustumSensor.js +7 -3
- package/dist/sensor/hiddenStateProbe.d.ts +5 -2
- package/dist/sensor/hiddenStateProbe.js +5 -2
- package/dist/sensor/recordingBuffer.d.ts +2 -1
- package/dist/sensor/recordingBuffer.js +2 -1
- package/dist/sensor/replayLoop.d.ts +6 -2
- package/dist/sensor/replayLoop.js +6 -2
- package/dist/sensor/revealQuery.d.ts +2 -1
- package/dist/sensor/revealQuery.js +2 -1
- package/dist/sensor/visionCone.d.ts +10 -3
- package/dist/sensor/visionCone.js +10 -3
- package/dist/session/contestedChannel.d.ts +1 -0
- package/dist/session/contestedChannel.js +1 -0
- package/dist/session/extraction.d.ts +1 -0
- package/dist/session/extraction.js +1 -0
- package/dist/session/roles.d.ts +6 -0
- package/dist/session/roles.js +6 -0
- package/dist/session/roundState.d.ts +8 -0
- package/dist/session/roundState.js +2 -0
- package/dist/settings/settingsModel.d.ts +1 -0
- package/dist/settings/settingsModel.js +1 -0
- package/dist/stats/accumulatorMeter.d.ts +6 -0
- package/dist/stats/accumulatorMeter.js +6 -0
- package/dist/stats/eventMeter.d.ts +5 -0
- package/dist/stats/eventMeter.js +5 -0
- package/dist/stats/rollCheck.d.ts +5 -0
- package/dist/stats/rollCheck.js +5 -0
- package/dist/stats/statModifiers.d.ts +5 -0
- package/dist/stats/statModifiers.js +5 -0
- package/dist/store/defineKeyedStore.d.ts +38 -0
- package/dist/store/defineKeyedStore.js +42 -0
- package/dist/store/defineStore.d.ts +33 -0
- package/dist/store/defineStore.js +35 -0
- package/dist/store/observableKeyedStore.d.ts +9 -0
- package/dist/store/observableKeyedStore.js +43 -2
- package/dist/survival/decayMeter.d.ts +55 -0
- package/dist/survival/decayMeter.js +130 -55
- package/dist/survival/moodle.d.ts +2 -0
- package/dist/survival/regionHealth.d.ts +6 -0
- package/dist/survival/regionHealth.js +5 -0
- package/dist/tactics/fallingGrid.d.ts +6 -4
- package/dist/tactics/fallingGrid.js +6 -4
- package/dist/tactics/predictiveQuery.d.ts +3 -0
- package/dist/tactics/predictiveQuery.js +3 -0
- package/dist/tactics/snapshot.d.ts +2 -0
- package/dist/tactics/snapshot.js +2 -0
- package/dist/tactics/surface.d.ts +1 -0
- package/dist/tactics/surface.js +1 -0
- package/dist/tactics/tacticalGrid.d.ts +1 -0
- package/dist/tactics/tacticalGrid.js +1 -0
- package/dist/time/beatClock.d.ts +14 -4
- package/dist/time/beatClock.js +14 -4
- package/dist/time/calendarClock.d.ts +3 -0
- package/dist/time/calendarClock.js +3 -0
- package/dist/time/idleProgress.d.ts +4 -0
- package/dist/time/idleProgress.js +4 -0
- package/dist/time/simClock.d.ts +2 -0
- package/dist/time/simClock.js +20 -5
- package/dist/ui/actionModel.d.ts +110 -0
- package/dist/ui/actionModel.js +159 -0
- package/dist/ui/gameLayout.d.ts +144 -0
- package/dist/ui/gameLayout.js +148 -0
- package/dist/ui/hudDocument.d.ts +114 -0
- package/dist/ui/hudDocument.js +220 -0
- package/dist/ui/hudLayout.d.ts +33 -1
- package/dist/ui/hudLayout.js +204 -17
- package/dist/ui/orientation.d.ts +39 -0
- package/dist/ui/orientation.js +49 -0
- package/dist/ui/selectionModel.d.ts +92 -0
- package/dist/ui/selectionModel.js +88 -0
- package/dist/ui/swingTimer.d.ts +42 -0
- package/dist/ui/swingTimer.js +38 -0
- package/dist/ui/tooltipModel.d.ts +63 -0
- package/dist/ui/tooltipModel.js +82 -0
- package/dist/ui.d.ts +15 -0
- package/dist/ui.js +15 -0
- package/dist/visibility/bounds.d.ts +8 -1
- package/dist/visibility/bounds.js +8 -1
- package/dist/visibility/frustum.d.ts +12 -3
- package/dist/visibility/frustum.js +12 -3
- package/dist/visibility/spatialIndex.js +34 -20
- package/dist/work/jobQueue.d.ts +201 -0
- package/dist/work/jobQueue.js +253 -0
- package/dist/work/unitTraining.d.ts +58 -0
- package/dist/work/unitTraining.js +52 -0
- package/dist/world/authoredObjects.d.ts +58 -0
- package/dist/world/authoredObjects.js +69 -0
- package/dist/world/buildingGenerator.d.ts +18 -0
- package/dist/world/buildingGenerator.js +62 -0
- package/dist/world/buildings.d.ts +5 -0
- package/dist/world/buildings.js +5 -0
- package/dist/world/catenary.d.ts +22 -0
- package/dist/world/catenary.js +69 -0
- package/dist/world/environmentSummary.d.ts +11 -2
- package/dist/world/environmentSummary.js +11 -1
- package/dist/world/features.d.ts +244 -7
- package/dist/world/features.js +92 -4
- package/dist/world/footprintGrid.d.ts +59 -0
- package/dist/world/footprintGrid.js +141 -0
- package/dist/world/geometry.d.ts +64 -0
- package/dist/world/geometry.js +94 -0
- package/dist/world/grassKind.d.ts +51 -0
- package/dist/world/grassKind.js +101 -0
- package/dist/world/pathInstances.d.ts +27 -0
- package/dist/world/pathInstances.js +27 -0
- package/dist/world/pathTerrain.d.ts +80 -0
- package/dist/world/pathTerrain.js +142 -0
- package/dist/world/placeAsset.d.ts +81 -0
- package/dist/world/placeAsset.js +77 -0
- package/dist/world/placement.d.ts +4 -0
- package/dist/world/placement.js +4 -0
- package/dist/world/placementController.d.ts +6 -0
- package/dist/world/placementController.js +6 -0
- package/dist/world/polyline.d.ts +34 -0
- package/dist/world/polyline.js +81 -0
- package/dist/world/roads.d.ts +55 -0
- package/dist/world/roads.js +184 -0
- package/dist/world/scatterRegion.d.ts +164 -0
- package/dist/world/scatterRegion.js +409 -0
- package/dist/world/sceneShapes.d.ts +43 -0
- package/dist/world/sceneShapes.js +1 -0
- package/dist/world/segment.d.ts +27 -0
- package/dist/world/segment.js +43 -0
- package/dist/world/soilKind.d.ts +48 -0
- package/dist/world/soilKind.js +92 -0
- package/dist/world/spatialSample.d.ts +241 -0
- package/dist/world/spatialSample.js +465 -0
- package/dist/world/streets.d.ts +80 -0
- package/dist/world/streets.js +144 -0
- package/dist/world/terraform.d.ts +213 -1
- package/dist/world/terraform.js +655 -20
- package/dist/world/terrain.d.ts +138 -12
- package/dist/world/terrain.js +346 -28
- package/dist/world/terrainGuides.d.ts +182 -0
- package/dist/world/terrainGuides.js +343 -0
- package/dist/world/vec2.d.ts +81 -0
- package/dist/world/vec2.js +128 -0
- package/dist/world/vec3.d.ts +49 -0
- package/dist/world/vec3.js +76 -0
- package/dist/world/vegetation.d.ts +71 -0
- package/dist/world/vegetation.js +151 -0
- package/dist/world/visibilityField.d.ts +154 -0
- package/dist/world/visibilityField.js +271 -0
- package/dist/world/volumetricClouds.d.ts +52 -0
- package/dist/world/volumetricClouds.js +43 -0
- package/dist/world/walls.d.ts +9 -0
- package/dist/world/walls.js +9 -0
- package/dist/world/waterKind.d.ts +55 -0
- package/dist/world/waterKind.js +99 -0
- package/dist/world.d.ts +132 -0
- package/dist/world.js +132 -0
- package/package.json +32 -8
- package/skills/jgengine/SKILL.md +51 -0
- package/skills/jgengine/api.md +434 -0
- package/skills/jgengine/capabilities.md +29 -0
- package/skills/jgengine/reference-cartridge.md +72 -0
- package/skills/jgengine-combat/SKILL.md +34 -0
- package/skills/jgengine-combat/api.md +549 -0
- package/skills/jgengine-combat/capabilities.md +169 -0
- package/skills/jgengine-combat/reference.md +98 -0
- package/skills/jgengine-gameplay/SKILL.md +39 -0
- package/skills/jgengine-gameplay/api.md +1794 -0
- package/skills/jgengine-gameplay/capabilities.md +378 -0
- package/skills/jgengine-gameplay/reference-systems.md +60 -0
- package/skills/jgengine-world/SKILL.md +38 -0
- package/skills/jgengine-world/api.md +2652 -0
- package/skills/jgengine-world/capabilities.md +370 -0
- package/skills/jgengine-world/reference.md +222 -0
- package/dist/cartridge/runtime.d.ts +0 -15
- package/dist/cartridge/runtime.js +0 -556
- package/dist/cartridge/spec.d.ts +0 -188
- package/dist/cartridge/spec.js +0 -19
- package/dist/cartridge/validate.d.ts +0 -2
- package/dist/cartridge/validate.js +0 -78
- package/dist/store/engineStore.d.ts +0 -22
- package/dist/store/engineStore.js +0 -50
- package/dist/store/features.d.ts +0 -10
- package/dist/store/features.js +0 -23
- package/llms.txt +0 -4983
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { seededRng } from "../random/rng.js";
|
|
2
|
+
import { advancePathFollow, createPathFollow, pathFollowSeek, } from "../nav/pathFollow.js";
|
|
3
|
+
import { perContext } from "../runtime/perContext.js";
|
|
4
|
+
const DEFAULT_WANDER_SPEED = 1.5;
|
|
5
|
+
const WANDER_ARRIVAL = 0.6;
|
|
6
|
+
function patrolOf(entity) {
|
|
7
|
+
return entity.behaviors.find((b) => b.kind === "patrol") ?? null;
|
|
8
|
+
}
|
|
9
|
+
function wanderOf(entity) {
|
|
10
|
+
return entity.behaviors.find((b) => b.kind === "wander") ?? null;
|
|
11
|
+
}
|
|
12
|
+
const runtimeOf = perContext((ctx) => {
|
|
13
|
+
const nav = new Map();
|
|
14
|
+
const refresh = () => {
|
|
15
|
+
const live = new Set();
|
|
16
|
+
for (const entity of ctx.scene.entity.list()) {
|
|
17
|
+
live.add(entity.id);
|
|
18
|
+
if (nav.has(entity.id))
|
|
19
|
+
continue;
|
|
20
|
+
const patrol = patrolOf(entity);
|
|
21
|
+
if (patrol !== null) {
|
|
22
|
+
const config = { waypoints: patrol.waypoints, speed: patrol.speed, loop: patrol.loop };
|
|
23
|
+
nav.set(entity.id, {
|
|
24
|
+
kind: "patrol",
|
|
25
|
+
config,
|
|
26
|
+
state: patrol.startProgress !== undefined ? pathFollowSeek(config, patrol.startProgress) : createPathFollow(config),
|
|
27
|
+
groundClamp: patrol.groundClamp ?? false,
|
|
28
|
+
status: "active",
|
|
29
|
+
reason: null,
|
|
30
|
+
pausedElapsed: 0,
|
|
31
|
+
});
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const wander = wanderOf(entity);
|
|
35
|
+
if (wander !== null) {
|
|
36
|
+
nav.set(entity.id, {
|
|
37
|
+
kind: "wander",
|
|
38
|
+
radius: wander.radius,
|
|
39
|
+
origin: entity.position,
|
|
40
|
+
target: null,
|
|
41
|
+
roll: seededRng(`wander:${entity.id}`),
|
|
42
|
+
status: "active",
|
|
43
|
+
reason: null,
|
|
44
|
+
pausedElapsed: 0,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const id of nav.keys())
|
|
49
|
+
if (!live.has(id))
|
|
50
|
+
nav.delete(id);
|
|
51
|
+
};
|
|
52
|
+
ctx.scene.entity.subscribeMembership(refresh);
|
|
53
|
+
refresh();
|
|
54
|
+
return { nav };
|
|
55
|
+
});
|
|
56
|
+
function stepWander(ctx, id, nav, dt) {
|
|
57
|
+
const entity = ctx.scene.entity.get(id);
|
|
58
|
+
if (entity === null)
|
|
59
|
+
return;
|
|
60
|
+
const [px, , pz] = entity.position;
|
|
61
|
+
if (nav.target === null || Math.hypot(px - nav.target[0], pz - nav.target[2]) < WANDER_ARRIVAL) {
|
|
62
|
+
const angle = nav.roll() * Math.PI * 2;
|
|
63
|
+
const distance = Math.sqrt(nav.roll()) * nav.radius;
|
|
64
|
+
const tx = nav.origin[0] + Math.cos(angle) * distance;
|
|
65
|
+
const tz = nav.origin[2] + Math.sin(angle) * distance;
|
|
66
|
+
nav.target = [tx, ctx.world.groundHeightAt(tx, tz), tz];
|
|
67
|
+
}
|
|
68
|
+
const speed = entity.movement.walkSpeed ?? DEFAULT_WANDER_SPEED;
|
|
69
|
+
const dx = nav.target[0] - px;
|
|
70
|
+
const dz = nav.target[2] - pz;
|
|
71
|
+
const dist = Math.hypot(dx, dz);
|
|
72
|
+
if (dist < 1e-6)
|
|
73
|
+
return;
|
|
74
|
+
const step = Math.min(dist, speed * dt);
|
|
75
|
+
const nx = px + (dx / dist) * step;
|
|
76
|
+
const nz = pz + (dz / dist) * step;
|
|
77
|
+
ctx.scene.entity.setPose(id, {
|
|
78
|
+
position: [nx, ctx.world.groundHeightAt(nx, nz), nz],
|
|
79
|
+
rotationY: Math.atan2(dx, dz),
|
|
80
|
+
dt,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function posePatrol(ctx, id, nav, dt) {
|
|
84
|
+
const [x, y, z] = nav.state.position;
|
|
85
|
+
ctx.scene.entity.setPose(id, {
|
|
86
|
+
position: nav.groundClamp ? [x, ctx.world.groundHeightAt(x, z), z] : [x, y, z],
|
|
87
|
+
rotationY: nav.state.heading,
|
|
88
|
+
dt,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Advance every spawned entity carrying a `patrol` or `wander` {@link BehaviorDescriptor} one tick — the
|
|
93
|
+
* engine reads the descriptor, keeps the per-entity nav state itself, and poses the entity, so ambient
|
|
94
|
+
* traffic and idle NPC routes are register-once (attach the behavior at spawn) instead of a per-game
|
|
95
|
+
* per-frame `advancePathFollow` + `setPose` loop. Instances that are paused or disabled through
|
|
96
|
+
* {@link behaviorControl} retain their state and are skipped. The shell/host call this each frame; a game never does.
|
|
97
|
+
*
|
|
98
|
+
* @capability behavior-tick auto-advance patrol/wander behaviors on spawned entities, no per-game route loop
|
|
99
|
+
*/
|
|
100
|
+
export function advanceBehaviors(ctx, dt) {
|
|
101
|
+
if (dt <= 0)
|
|
102
|
+
return;
|
|
103
|
+
const { nav } = runtimeOf(ctx);
|
|
104
|
+
if (nav.size === 0)
|
|
105
|
+
return;
|
|
106
|
+
for (const [id, entry] of nav) {
|
|
107
|
+
if (entry.status !== "active") {
|
|
108
|
+
if (entry.status === "paused")
|
|
109
|
+
entry.pausedElapsed += dt;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (entry.kind === "patrol") {
|
|
113
|
+
entry.state = advancePathFollow(entry.config, entry.state, dt);
|
|
114
|
+
posePatrol(ctx, id, entry, dt);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
stepWander(ctx, id, entry, dt);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Obtain the per-context {@link BehaviorControl} surface for suspending, resuming, seeking, serializing,
|
|
123
|
+
* and inspecting behavior instances by entity id — the lifecycle contract games use to hand pose
|
|
124
|
+
* ownership to possession/streaming/staggering code instead of bypassing the behavior runtime.
|
|
125
|
+
*
|
|
126
|
+
* @capability behavior-control pause/disable/resume/seek/inspect behavior instances per entity
|
|
127
|
+
*/
|
|
128
|
+
export function behaviorControl(ctx) {
|
|
129
|
+
const { nav } = runtimeOf(ctx);
|
|
130
|
+
const setStatus = (id, status, reason) => {
|
|
131
|
+
const entry = nav.get(id);
|
|
132
|
+
if (entry === undefined)
|
|
133
|
+
return false;
|
|
134
|
+
entry.status = status;
|
|
135
|
+
entry.reason = reason;
|
|
136
|
+
return true;
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
status: (id) => nav.get(id)?.status ?? null,
|
|
140
|
+
reason: (id) => nav.get(id)?.reason ?? null,
|
|
141
|
+
pause: (id, reason) => {
|
|
142
|
+
const entry = nav.get(id);
|
|
143
|
+
if (entry === undefined || entry.status !== "active")
|
|
144
|
+
return false;
|
|
145
|
+
entry.status = "paused";
|
|
146
|
+
entry.reason = reason ?? null;
|
|
147
|
+
entry.pausedElapsed = 0;
|
|
148
|
+
return true;
|
|
149
|
+
},
|
|
150
|
+
resume: (id, policy = "freeze") => {
|
|
151
|
+
const entry = nav.get(id);
|
|
152
|
+
if (entry === undefined || entry.status !== "paused")
|
|
153
|
+
return false;
|
|
154
|
+
if (policy === "advance" && entry.kind === "patrol" && entry.pausedElapsed > 0) {
|
|
155
|
+
entry.state = advancePathFollow(entry.config, entry.state, entry.pausedElapsed);
|
|
156
|
+
// Emit a single final pose at the caught-up position (no intermediate writes).
|
|
157
|
+
posePatrol(ctx, id, entry, entry.pausedElapsed);
|
|
158
|
+
}
|
|
159
|
+
entry.status = "active";
|
|
160
|
+
entry.reason = null;
|
|
161
|
+
entry.pausedElapsed = 0;
|
|
162
|
+
return true;
|
|
163
|
+
},
|
|
164
|
+
disable: (id, reason) => setStatus(id, "disabled", reason ?? null),
|
|
165
|
+
enable: (id) => {
|
|
166
|
+
const entry = nav.get(id);
|
|
167
|
+
if (entry === undefined || entry.status !== "disabled")
|
|
168
|
+
return false;
|
|
169
|
+
entry.status = "active";
|
|
170
|
+
entry.reason = null;
|
|
171
|
+
entry.pausedElapsed = 0;
|
|
172
|
+
return true;
|
|
173
|
+
},
|
|
174
|
+
seek: (id, progress) => {
|
|
175
|
+
const entry = nav.get(id);
|
|
176
|
+
if (entry === undefined || entry.kind !== "patrol")
|
|
177
|
+
return false;
|
|
178
|
+
entry.state = pathFollowSeek(entry.config, progress);
|
|
179
|
+
return true;
|
|
180
|
+
},
|
|
181
|
+
serialize: (id) => {
|
|
182
|
+
const entry = nav.get(id);
|
|
183
|
+
if (entry === undefined)
|
|
184
|
+
return null;
|
|
185
|
+
if (entry.kind === "patrol")
|
|
186
|
+
return { kind: "patrol", state: { ...entry.state } };
|
|
187
|
+
return { kind: "wander", origin: [...entry.origin], target: entry.target === null ? null : [...entry.target] };
|
|
188
|
+
},
|
|
189
|
+
restore: (id, snapshot) => {
|
|
190
|
+
const entry = nav.get(id);
|
|
191
|
+
if (entry === undefined || entry.kind !== snapshot.kind)
|
|
192
|
+
return false;
|
|
193
|
+
if (entry.kind === "patrol" && snapshot.kind === "patrol") {
|
|
194
|
+
entry.state = { ...snapshot.state };
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
if (entry.kind === "wander" && snapshot.kind === "wander") {
|
|
198
|
+
entry.origin = [...snapshot.origin];
|
|
199
|
+
entry.target = snapshot.target === null ? null : [...snapshot.target];
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
},
|
|
204
|
+
inspect: (id) => {
|
|
205
|
+
const entry = nav.get(id);
|
|
206
|
+
if (entry === undefined)
|
|
207
|
+
return null;
|
|
208
|
+
return { id, kind: entry.kind, status: entry.status, reason: entry.reason };
|
|
209
|
+
},
|
|
210
|
+
list: () => {
|
|
211
|
+
const out = [];
|
|
212
|
+
for (const [id, entry] of nav)
|
|
213
|
+
out.push({ id, kind: entry.kind, status: entry.status, reason: entry.reason });
|
|
214
|
+
return out;
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ProximityPrompt } from "../interaction/proximityPrompt.js";
|
|
2
|
-
import type { Waypoint } from "../nav/pathFollow.js";
|
|
2
|
+
import type { PathProgress, Waypoint } from "../nav/pathFollow.js";
|
|
3
3
|
export interface WanderBehavior {
|
|
4
4
|
kind: "wander";
|
|
5
5
|
radius: number;
|
|
@@ -9,6 +9,16 @@ export interface PatrolBehavior {
|
|
|
9
9
|
waypoints: readonly Waypoint[];
|
|
10
10
|
speed: number;
|
|
11
11
|
loop: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Optional initial progress the follower is seeded at instead of waypoint zero — lets a fleet of
|
|
14
|
+
* route followers start at distributed phases. Round-trips through the behavior lifecycle seek/serialize.
|
|
15
|
+
*/
|
|
16
|
+
startProgress?: PathProgress;
|
|
17
|
+
/**
|
|
18
|
+
* Sample world ground height for the pose Y each tick, so a route authored in the XZ plane rides
|
|
19
|
+
* uneven terrain. Default false (waypoint Y is used verbatim).
|
|
20
|
+
*/
|
|
21
|
+
groundClamp?: boolean;
|
|
12
22
|
}
|
|
13
23
|
export interface PromptableBehavior {
|
|
14
24
|
kind: "promptable";
|
|
@@ -21,10 +31,12 @@ export type BehaviorDescriptor = WanderBehavior | PatrolBehavior | PromptableBeh
|
|
|
21
31
|
export declare function wander({ radius }: {
|
|
22
32
|
radius: number;
|
|
23
33
|
}): WanderBehavior;
|
|
24
|
-
export declare function patrol({ waypoints, speed, loop, }: {
|
|
34
|
+
export declare function patrol({ waypoints, speed, loop, startProgress, groundClamp, }: {
|
|
25
35
|
waypoints: readonly Waypoint[];
|
|
26
36
|
speed: number;
|
|
27
37
|
loop?: boolean;
|
|
38
|
+
startProgress?: PathProgress;
|
|
39
|
+
groundClamp?: boolean;
|
|
28
40
|
}): PatrolBehavior;
|
|
29
41
|
export declare function promptable(prompt: ProximityPrompt): PromptableBehavior;
|
|
30
42
|
export declare function talkable(dialogueId: string): PromptableBehavior;
|
package/dist/scene/behaviors.js
CHANGED
|
@@ -2,8 +2,13 @@ import { command, keybind, proximityPrompt, } from "../interaction/proximityProm
|
|
|
2
2
|
export function wander({ radius }) {
|
|
3
3
|
return { kind: "wander", radius };
|
|
4
4
|
}
|
|
5
|
-
export function patrol({ waypoints, speed, loop = true, }) {
|
|
6
|
-
|
|
5
|
+
export function patrol({ waypoints, speed, loop = true, startProgress, groundClamp, }) {
|
|
6
|
+
const behavior = { kind: "patrol", waypoints, speed, loop };
|
|
7
|
+
if (startProgress !== undefined)
|
|
8
|
+
behavior.startProgress = startProgress;
|
|
9
|
+
if (groundClamp !== undefined)
|
|
10
|
+
behavior.groundClamp = groundClamp;
|
|
11
|
+
return behavior;
|
|
7
12
|
}
|
|
8
13
|
export function promptable(prompt) {
|
|
9
14
|
return { kind: "promptable", prompt };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { EntityRole, EntityUpdatePatch, SpawnPositionInput } from "./entityStore.js";
|
|
2
|
+
/**
|
|
3
|
+
* One sim body's per-tick pose, as the game's simulation computed it — the shape a game already builds
|
|
4
|
+
* to hand to `setPose`, just declared instead of imperatively pushed. `kind` is the entity catalog name
|
|
5
|
+
* used only the first time `id` is seen (a respawn/despawn never re-reads it).
|
|
6
|
+
*/
|
|
7
|
+
export interface BodySnapshot {
|
|
8
|
+
id: string;
|
|
9
|
+
kind: string;
|
|
10
|
+
position: SpawnPositionInput;
|
|
11
|
+
rotationY?: number;
|
|
12
|
+
rotationX?: number;
|
|
13
|
+
rotationZ?: number;
|
|
14
|
+
role?: EntityRole;
|
|
15
|
+
meta?: unknown;
|
|
16
|
+
}
|
|
17
|
+
/** The options a {@link BodyBindDeps.spawn} call receives for an id seen for the first time. */
|
|
18
|
+
export interface BodyBindSpawnInput {
|
|
19
|
+
id: string;
|
|
20
|
+
position: SpawnPositionInput;
|
|
21
|
+
rotationY?: number;
|
|
22
|
+
rotationX?: number;
|
|
23
|
+
rotationZ?: number;
|
|
24
|
+
role?: EntityRole;
|
|
25
|
+
meta?: unknown;
|
|
26
|
+
}
|
|
27
|
+
/** The pose a {@link BodyBindDeps.setPose} call receives for an id already bound. */
|
|
28
|
+
export interface BodyBindPose {
|
|
29
|
+
position: SpawnPositionInput;
|
|
30
|
+
rotationY?: number;
|
|
31
|
+
rotationX?: number;
|
|
32
|
+
rotationZ?: number;
|
|
33
|
+
dt?: number;
|
|
34
|
+
}
|
|
35
|
+
/** Structural entity-store seam a {@link BodyBind} mirrors onto — satisfied by `ctx.scene.entity` itself. */
|
|
36
|
+
export interface BodyBindDeps {
|
|
37
|
+
has(id: string): boolean;
|
|
38
|
+
spawn(kind: string, options: BodyBindSpawnInput): string;
|
|
39
|
+
despawn(id: string): boolean;
|
|
40
|
+
setPose(id: string, pose: BodyBindPose): boolean;
|
|
41
|
+
update(id: string, patch: EntityUpdatePatch): boolean;
|
|
42
|
+
}
|
|
43
|
+
/** The lazily-keyed handle `ctx.scene.entity.bind(key)` returns. */
|
|
44
|
+
export interface BodyBind {
|
|
45
|
+
/**
|
|
46
|
+
* Mirror this tick's `bodies` onto scene entities: spawns an id seen for the first time (catalog
|
|
47
|
+
* `kind` from its snapshot), poses one already bound, despawns one this bind previously spawned that
|
|
48
|
+
* is now absent from `bodies`. `dt` (when given) derives `velocity` the same as a direct `setPose`.
|
|
49
|
+
*/
|
|
50
|
+
sync(bodies: Iterable<BodySnapshot>, dt?: number): void;
|
|
51
|
+
/** Ids this bind currently considers itself responsible for (spawned by, and not yet despawned by, `sync`). */
|
|
52
|
+
boundIds(): ReadonlySet<string>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Mirror a sim's body snapshots onto scene entities each tick — spawn on first sight, pose while bound,
|
|
56
|
+
* despawn on drop — replacing a per-body `setPose` loop plus its `despawn`/`spawn` respawn dance.
|
|
57
|
+
*
|
|
58
|
+
* @capability body-bind mirror sim-body snapshots onto scene entities each tick, no per-body setPose
|
|
59
|
+
*/
|
|
60
|
+
export declare function createBodyBind(deps: BodyBindDeps): BodyBind;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirror a sim's body snapshots onto scene entities each tick — spawn on first sight, pose while bound,
|
|
3
|
+
* despawn on drop — replacing a per-body `setPose` loop plus its `despawn`/`spawn` respawn dance.
|
|
4
|
+
*
|
|
5
|
+
* @capability body-bind mirror sim-body snapshots onto scene entities each tick, no per-body setPose
|
|
6
|
+
*/
|
|
7
|
+
export function createBodyBind(deps) {
|
|
8
|
+
const bound = new Set();
|
|
9
|
+
return {
|
|
10
|
+
sync(bodies, dt) {
|
|
11
|
+
const seen = new Set();
|
|
12
|
+
for (const body of bodies) {
|
|
13
|
+
seen.add(body.id);
|
|
14
|
+
const alreadyBound = bound.has(body.id);
|
|
15
|
+
if (!alreadyBound && !deps.has(body.id)) {
|
|
16
|
+
deps.spawn(body.kind, {
|
|
17
|
+
id: body.id,
|
|
18
|
+
position: body.position,
|
|
19
|
+
rotationY: body.rotationY,
|
|
20
|
+
rotationX: body.rotationX,
|
|
21
|
+
rotationZ: body.rotationZ,
|
|
22
|
+
role: body.role,
|
|
23
|
+
meta: body.meta,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
deps.setPose(body.id, {
|
|
28
|
+
position: body.position,
|
|
29
|
+
rotationY: body.rotationY,
|
|
30
|
+
rotationX: body.rotationX,
|
|
31
|
+
rotationZ: body.rotationZ,
|
|
32
|
+
...(dt === undefined ? {} : { dt }),
|
|
33
|
+
});
|
|
34
|
+
if (body.role !== undefined || body.meta !== undefined) {
|
|
35
|
+
deps.update(body.id, { role: body.role, meta: body.meta });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
bound.add(body.id);
|
|
39
|
+
}
|
|
40
|
+
for (const id of bound) {
|
|
41
|
+
if (seen.has(id))
|
|
42
|
+
continue;
|
|
43
|
+
deps.despawn(id);
|
|
44
|
+
bound.delete(id);
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
boundIds() {
|
|
48
|
+
return bound;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type ParamSchema } from "./sceneKinds.js";
|
|
2
|
+
/** The scatter/foliage region schema — the fields the inspector exposed as hand-written `ScatterFields`. */
|
|
3
|
+
export declare const SCATTER_SCHEMA: ParamSchema;
|
|
4
|
+
/** Idempotently registers the engine's built-in environment scene kinds + generators. @internal */
|
|
5
|
+
export declare function registerBuiltinSceneKinds(): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers the engine's built-in *environment* scene kinds against the {@link registerSceneKind}
|
|
3
|
+
* seam: `scatter` (the proof adopter — its inspector, `+ Add` entry, and parse now come from the
|
|
4
|
+
* registry), `water` (a reusable parametric water surface), `grass_field` (GPU vertex-wind grass), and
|
|
5
|
+
* `soil` (crack/moss ground-variation patch). These are genre-agnostic engine primitives, like terrain.
|
|
6
|
+
* Domain studios (poles, bookcases, …) are NOT built in — they register themselves from example/game
|
|
7
|
+
* code via the same public seam, needing zero engine edits (see `examples/studios`). Call
|
|
8
|
+
* {@link registerBuiltinSceneKinds} once at startup (idempotent).
|
|
9
|
+
*/
|
|
10
|
+
import { SCATTER_PATH_KIND } from "../world/scatterRegion.js";
|
|
11
|
+
import { registerWaterKind } from "../world/waterKind.js";
|
|
12
|
+
import { registerGrassKind } from "../world/grassKind.js";
|
|
13
|
+
import { registerSoilKind } from "../world/soilKind.js";
|
|
14
|
+
import { registerBuildingGenerator } from "../world/buildingGenerator.js";
|
|
15
|
+
import { registerSceneKind } from "./sceneKinds.js";
|
|
16
|
+
/** The scatter/foliage region schema — the fields the inspector exposed as hand-written `ScatterFields`. */
|
|
17
|
+
export const SCATTER_SCHEMA = {
|
|
18
|
+
fields: [
|
|
19
|
+
{ type: "range", key: "density", label: "density", min: 0, max: 2, step: 0.01, default: 0.15, unit: "/m²" },
|
|
20
|
+
{ type: "number", key: "minSpacing", label: "spacing", step: 0.25, default: 1.5, min: 0 },
|
|
21
|
+
{ type: "number", key: "minScale", label: "min scale", step: 0.05, default: 0.8, min: 0 },
|
|
22
|
+
{ type: "number", key: "maxScale", label: "max scale", step: 0.05, default: 1.3, min: 0 },
|
|
23
|
+
{ type: "number", key: "maxSlope", label: "max slope", step: 0.05, default: 0, min: 0 },
|
|
24
|
+
{ type: "number", key: "edgeFalloff", label: "edge fade", step: 0.5, default: 0, min: 0 },
|
|
25
|
+
{ type: "bool", key: "alignToNormal", label: "align to slope", default: false },
|
|
26
|
+
{ type: "bool", key: "autoAvoid", label: "auto-avoid gameplay spots", default: true },
|
|
27
|
+
{ type: "weightedList", key: "palette", label: "species (weighted)", itemLabel: "grass / tree id", default: [{ item: "grass", weight: 1 }] },
|
|
28
|
+
{ type: "seed", key: "seed", label: "seed", default: "" },
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
let registered = false;
|
|
32
|
+
/** Idempotently registers the engine's built-in environment scene kinds + generators. @internal */
|
|
33
|
+
export function registerBuiltinSceneKinds() {
|
|
34
|
+
if (registered)
|
|
35
|
+
return;
|
|
36
|
+
registered = true;
|
|
37
|
+
registerSceneKind({
|
|
38
|
+
kind: SCATTER_PATH_KIND,
|
|
39
|
+
target: "path",
|
|
40
|
+
label: "Foliage / scatter",
|
|
41
|
+
pathShape: "area",
|
|
42
|
+
addCategory: "Studios",
|
|
43
|
+
accent: "#34d399",
|
|
44
|
+
schema: SCATTER_SCHEMA,
|
|
45
|
+
note: (object, params) => {
|
|
46
|
+
const points = object.points ?? [];
|
|
47
|
+
if (points.length < 3)
|
|
48
|
+
return "Draw at least 3 points to close the region.";
|
|
49
|
+
let area = 0;
|
|
50
|
+
for (let i = 0, j = points.length - 1; i < points.length; j = i, i += 1) {
|
|
51
|
+
area += points[j].x * points[i].z - points[i].x * points[j].z;
|
|
52
|
+
}
|
|
53
|
+
area = Math.abs(area) / 2;
|
|
54
|
+
const density = typeof params["density"] === "number" ? params["density"] : 0;
|
|
55
|
+
return `≈ ${Math.floor(area * density).toLocaleString()} placements over ${Math.round(area).toLocaleString()} m²`;
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
registerWaterKind();
|
|
59
|
+
registerGrassKind();
|
|
60
|
+
registerSoilKind();
|
|
61
|
+
registerBuildingGenerator();
|
|
62
|
+
}
|
|
@@ -33,11 +33,29 @@ export interface ResolvedCollider {
|
|
|
33
33
|
}
|
|
34
34
|
export declare const DEFAULT_ENTITY_HIT_RADIUS = 0.5;
|
|
35
35
|
export declare const DEFAULT_OBJECT_HALF_EXTENTS: EntityPosition;
|
|
36
|
+
/** Matches the shell's fallback actor capsule (~0.7m wide, feet at y=0 to head at ~1.8m). */
|
|
37
|
+
export declare const DEFAULT_ENTITY_BODY_HALF_EXTENTS: EntityPosition;
|
|
38
|
+
/** Entity-local center of the default body hitbox (half its height above the feet). */
|
|
39
|
+
export declare const DEFAULT_ENTITY_BODY_OFFSET: EntityPosition;
|
|
40
|
+
/** @internal */
|
|
36
41
|
export declare function defaultEntityColliders(): EntityColliderSet;
|
|
42
|
+
/** Humanoid damage box uniformly scaled to match a visually scaled mesh, kept grounded (offset stays half its height). At scale 1 this equals `defaultEntityColliders()`.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export declare function scaledEntityColliders(scale: number): EntityColliderSet;
|
|
46
|
+
/** @internal */
|
|
37
47
|
export declare function defaultObjectColliders(halfExtents?: EntityPosition): EntityColliderSet;
|
|
48
|
+
/** Blocking physical body derived from an object's rendered scale: a grounded box spanning the visual (base at y=0, matching the shell's fallback mesh).
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
export declare function scaledObjectColliders(scale: readonly [number, number, number]): EntityColliderSet;
|
|
52
|
+
/** @internal */
|
|
38
53
|
export declare function resolveColliders(set: EntityColliderSet | null | undefined): ResolvedCollider[];
|
|
54
|
+
/** @internal */
|
|
39
55
|
export declare function worldOffset(local: EntityPosition | undefined, position: EntityPosition, rotationY: number): EntityPosition;
|
|
56
|
+
/** @internal */
|
|
40
57
|
export declare function colliderWorldCenter(collider: ResolvedCollider, position: EntityPosition, rotationY: number): EntityPosition;
|
|
58
|
+
/** @internal */
|
|
41
59
|
export declare function colliderBounds(collider: ResolvedCollider, position: EntityPosition, rotationY: number): {
|
|
42
60
|
min: EntityPosition;
|
|
43
61
|
max: EntityPosition;
|
package/dist/scene/colliders.js
CHANGED
|
@@ -1,18 +1,56 @@
|
|
|
1
1
|
export const DEFAULT_ENTITY_HIT_RADIUS = 0.5;
|
|
2
2
|
export const DEFAULT_OBJECT_HALF_EXTENTS = [0.5, 0.5, 0.5];
|
|
3
|
+
/** Matches the shell's fallback actor capsule (~0.7m wide, feet at y=0 to head at ~1.8m). */
|
|
4
|
+
export const DEFAULT_ENTITY_BODY_HALF_EXTENTS = [0.35, 0.9, 0.35];
|
|
5
|
+
/** Entity-local center of the default body hitbox (half its height above the feet). */
|
|
6
|
+
export const DEFAULT_ENTITY_BODY_OFFSET = [0, 0.9, 0];
|
|
7
|
+
/** @internal */
|
|
3
8
|
export function defaultEntityColliders() {
|
|
4
9
|
return {
|
|
5
10
|
hitboxes: [
|
|
6
11
|
{
|
|
7
12
|
name: "body",
|
|
8
13
|
purpose: "damage",
|
|
9
|
-
shape: {
|
|
14
|
+
shape: {
|
|
15
|
+
kind: "aabb",
|
|
16
|
+
halfExtents: DEFAULT_ENTITY_BODY_HALF_EXTENTS,
|
|
17
|
+
offset: DEFAULT_ENTITY_BODY_OFFSET,
|
|
18
|
+
},
|
|
10
19
|
damageEligible: true,
|
|
11
20
|
blocks: false,
|
|
12
21
|
},
|
|
13
22
|
],
|
|
14
23
|
};
|
|
15
24
|
}
|
|
25
|
+
/** Humanoid damage box uniformly scaled to match a visually scaled mesh, kept grounded (offset stays half its height). At scale 1 this equals `defaultEntityColliders()`.
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export function scaledEntityColliders(scale) {
|
|
29
|
+
return {
|
|
30
|
+
hitboxes: [
|
|
31
|
+
{
|
|
32
|
+
name: "body",
|
|
33
|
+
purpose: "damage",
|
|
34
|
+
shape: {
|
|
35
|
+
kind: "aabb",
|
|
36
|
+
halfExtents: [
|
|
37
|
+
DEFAULT_ENTITY_BODY_HALF_EXTENTS[0] * scale,
|
|
38
|
+
DEFAULT_ENTITY_BODY_HALF_EXTENTS[1] * scale,
|
|
39
|
+
DEFAULT_ENTITY_BODY_HALF_EXTENTS[2] * scale,
|
|
40
|
+
],
|
|
41
|
+
offset: [
|
|
42
|
+
DEFAULT_ENTITY_BODY_OFFSET[0] * scale,
|
|
43
|
+
DEFAULT_ENTITY_BODY_OFFSET[1] * scale,
|
|
44
|
+
DEFAULT_ENTITY_BODY_OFFSET[2] * scale,
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
damageEligible: true,
|
|
48
|
+
blocks: false,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** @internal */
|
|
16
54
|
export function defaultObjectColliders(halfExtents = DEFAULT_OBJECT_HALF_EXTENTS) {
|
|
17
55
|
return {
|
|
18
56
|
body: {
|
|
@@ -24,6 +62,25 @@ export function defaultObjectColliders(halfExtents = DEFAULT_OBJECT_HALF_EXTENTS
|
|
|
24
62
|
},
|
|
25
63
|
};
|
|
26
64
|
}
|
|
65
|
+
/** Blocking physical body derived from an object's rendered scale: a grounded box spanning the visual (base at y=0, matching the shell's fallback mesh).
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
export function scaledObjectColliders(scale) {
|
|
69
|
+
return {
|
|
70
|
+
body: {
|
|
71
|
+
name: "body",
|
|
72
|
+
purpose: "physical",
|
|
73
|
+
shape: {
|
|
74
|
+
kind: "aabb",
|
|
75
|
+
halfExtents: [scale[0] / 2, scale[1] / 2, scale[2] / 2],
|
|
76
|
+
offset: [0, scale[1] / 2, 0],
|
|
77
|
+
},
|
|
78
|
+
damageEligible: false,
|
|
79
|
+
blocks: true,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** @internal */
|
|
27
84
|
export function resolveColliders(set) {
|
|
28
85
|
if (set === null || set === undefined)
|
|
29
86
|
return [];
|
|
@@ -47,6 +104,7 @@ function resolveOne(def) {
|
|
|
47
104
|
blocks,
|
|
48
105
|
};
|
|
49
106
|
}
|
|
107
|
+
/** @internal */
|
|
50
108
|
export function worldOffset(local, position, rotationY) {
|
|
51
109
|
if (local === undefined)
|
|
52
110
|
return position;
|
|
@@ -57,9 +115,11 @@ export function worldOffset(local, position, rotationY) {
|
|
|
57
115
|
const lz = local[2];
|
|
58
116
|
return [position[0] + lx * cos + lz * sin, position[1] + ly, position[2] - lx * sin + lz * cos];
|
|
59
117
|
}
|
|
118
|
+
/** @internal */
|
|
60
119
|
export function colliderWorldCenter(collider, position, rotationY) {
|
|
61
120
|
return worldOffset(collider.shape.offset, position, rotationY);
|
|
62
121
|
}
|
|
122
|
+
/** @internal */
|
|
63
123
|
export function colliderBounds(collider, position, rotationY) {
|
|
64
124
|
const center = colliderWorldCenter(collider, position, rotationY);
|
|
65
125
|
if (collider.shape.kind === "sphere") {
|
|
@@ -24,10 +24,22 @@ export type PoolDeltaResult = {
|
|
|
24
24
|
status: "rejected";
|
|
25
25
|
reason: string;
|
|
26
26
|
};
|
|
27
|
+
/** @internal */
|
|
27
28
|
export declare function getStatValue(map: StatValueMap, statId: string): StatValue | null;
|
|
29
|
+
/** @internal */
|
|
28
30
|
export declare function setStatValue(map: StatValueMap, statId: string, patch: StatValuePatch): StatValueMap;
|
|
31
|
+
/** @internal */
|
|
29
32
|
export declare function applyPoolDelta(map: StatValueMap, statId: string, amount: number): PoolDeltaResult;
|
|
33
|
+
/** @internal */
|
|
30
34
|
export declare function seedStatValues(catalogStats: StatCatalog): StatValueMap;
|
|
35
|
+
/** Deep-copy the per-entity stat maps into a serializable record — the transport counterpart of {@link hydrateEntityStats}.
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
export declare function snapshotEntityStats(store: ReadonlyMap<string, StatValueMap>): Record<string, StatValueMap>;
|
|
39
|
+
/** Replace a live stat store with deep copies of a snapshot, clearing entities absent from it.
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
export declare function hydrateEntityStats(store: Map<string, StatValueMap>, data: Record<string, StatValueMap>): void;
|
|
31
43
|
export interface EntityStatsApi {
|
|
32
44
|
get(instanceId: string, statId: string): StatValue | null;
|
|
33
45
|
set(instanceId: string, statId: string, patch: StatValuePatch): boolean;
|
|
@@ -35,4 +47,5 @@ export interface EntityStatsApi {
|
|
|
35
47
|
reason: string;
|
|
36
48
|
};
|
|
37
49
|
}
|
|
50
|
+
/** @internal */
|
|
38
51
|
export declare function createEntityStatsApi(resolve: (instanceId: string) => StatValueMap | undefined): EntityStatsApi;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
function clamp(value, min, max) {
|
|
2
2
|
return Math.min(max, Math.max(min, value));
|
|
3
3
|
}
|
|
4
|
+
/** @internal */
|
|
4
5
|
export function getStatValue(map, statId) {
|
|
5
6
|
return map[statId] ?? null;
|
|
6
7
|
}
|
|
8
|
+
/** @internal */
|
|
7
9
|
export function setStatValue(map, statId, patch) {
|
|
8
10
|
const existing = map[statId];
|
|
9
11
|
const max = patch.max ?? existing?.max ?? 0;
|
|
@@ -11,6 +13,7 @@ export function setStatValue(map, statId, patch) {
|
|
|
11
13
|
const current = clamp(patch.current ?? existing?.current ?? max, min, max);
|
|
12
14
|
return { ...map, [statId]: { current, max, min } };
|
|
13
15
|
}
|
|
16
|
+
/** @internal */
|
|
14
17
|
export function applyPoolDelta(map, statId, amount) {
|
|
15
18
|
const existing = map[statId];
|
|
16
19
|
if (existing === undefined) {
|
|
@@ -26,6 +29,7 @@ export function applyPoolDelta(map, statId, amount) {
|
|
|
26
29
|
hitMax: current === existing.max,
|
|
27
30
|
};
|
|
28
31
|
}
|
|
32
|
+
/** @internal */
|
|
29
33
|
export function seedStatValues(catalogStats) {
|
|
30
34
|
const map = {};
|
|
31
35
|
for (const [statId, declaration] of Object.entries(catalogStats)) {
|
|
@@ -35,6 +39,32 @@ export function seedStatValues(catalogStats) {
|
|
|
35
39
|
}
|
|
36
40
|
return map;
|
|
37
41
|
}
|
|
42
|
+
/** Deep-copy the per-entity stat maps into a serializable record — the transport counterpart of {@link hydrateEntityStats}.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export function snapshotEntityStats(store) {
|
|
46
|
+
const out = {};
|
|
47
|
+
for (const [instanceId, map] of store) {
|
|
48
|
+
const copy = {};
|
|
49
|
+
for (const [statId, value] of Object.entries(map))
|
|
50
|
+
copy[statId] = { ...value };
|
|
51
|
+
out[instanceId] = copy;
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
/** Replace a live stat store with deep copies of a snapshot, clearing entities absent from it.
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
58
|
+
export function hydrateEntityStats(store, data) {
|
|
59
|
+
store.clear();
|
|
60
|
+
for (const [instanceId, map] of Object.entries(data)) {
|
|
61
|
+
const copy = {};
|
|
62
|
+
for (const [statId, value] of Object.entries(map))
|
|
63
|
+
copy[statId] = { ...value };
|
|
64
|
+
store.set(instanceId, copy);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** @internal */
|
|
38
68
|
export function createEntityStatsApi(resolve) {
|
|
39
69
|
return {
|
|
40
70
|
get(instanceId, statId) {
|