@jgengine/core 0.10.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 +13 -2
- 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 +7 -2
- package/dist/ai/spawnDirector.js +18 -15
- package/dist/ai/spawnPoint.d.ts +3 -1
- package/dist/ai/spawnPoint.js +3 -1
- 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/authoring.d.ts +1 -0
- package/dist/authoring.js +1 -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 +5 -1
- package/dist/combat/dotField.js +5 -1
- 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 +5 -0
- package/dist/combat/projectiles.js +32 -14
- package/dist/combat/receivedDamage.d.ts +117 -0
- package/dist/combat/receivedDamage.js +92 -0
- package/dist/combat/regenShield.d.ts +5 -1
- package/dist/combat/regenShield.js +5 -1
- 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 +18 -1
- package/dist/combat/shotOrigin.js +39 -0
- 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 +190 -7
- package/dist/editor/commands.js +727 -55
- package/dist/editor/document.d.ts +159 -13
- package/dist/editor/document.js +750 -19
- 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 +73 -6
- package/dist/editor/index.js +6 -2
- 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 +107 -1
- 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 +6 -4
- package/dist/game/connectedPlayers.js +2 -2
- package/dist/game/cosmetics.d.ts +9 -0
- package/dist/game/cosmetics.js +16 -0
- package/dist/game/defineGame.d.ts +100 -2
- package/dist/game/defineGame.js +39 -2
- 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 +35 -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/leaderboard.d.ts +5 -0
- package/dist/game/leaderboard.js +5 -0
- 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 +19 -2
- package/dist/game/lootTable.js +15 -5
- 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 +92 -7
- 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 +3 -1
- 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 -14
- package/dist/index.js +5 -14
- package/dist/input/actionBindings.d.ts +23 -6
- package/dist/input/actionBindings.js +23 -6
- package/dist/input/axisInput.d.ts +7 -2
- package/dist/input/axisInput.js +7 -2
- 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/lockpick.d.ts +61 -0
- package/dist/interaction/lockpick.js +168 -0
- package/dist/interaction/proximityPrompt.d.ts +2 -0
- package/dist/interaction/proximityPrompt.js +2 -0
- 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 +16 -2
- 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 +35 -8
- package/dist/movement/movementModel.js +42 -14
- package/dist/movement/playerMovement.js +65 -10
- 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 +22 -0
- package/dist/random/rng.js +28 -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 +20 -0
- package/dist/render/postProcessing.js +21 -1
- 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 +42 -3
- package/dist/runtime/adapter.js +44 -1
- 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 +114 -13
- package/dist/runtime/gameContext.js +303 -395
- 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 +8 -3
- package/dist/runtime/hostedGameRunner.js +26 -3
- package/dist/runtime/hostedWorldSession.d.ts +12 -4
- package/dist/runtime/hostedWorldSession.js +11 -4
- package/dist/runtime/inputSnapshot.d.ts +8 -3
- package/dist/runtime/inputSnapshot.js +6 -2
- package/dist/runtime/motionIntents.d.ts +11 -2
- package/dist/runtime/motionIntents.js +16 -2
- 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 +7 -3
- package/dist/runtime/worldChannel.js +51 -6
- package/dist/runtime/worldMirror.d.ts +14 -2
- package/dist/runtime/worldMirror.js +15 -2
- package/dist/runtime/worldProjection.d.ts +47 -0
- package/dist/runtime/worldProjection.js +52 -0
- package/dist/runtime/worldReplication.d.ts +30 -7
- package/dist/runtime/worldReplication.js +41 -9
- package/dist/runtime/worldSnapshot.d.ts +30 -3
- package/dist/runtime/worldSnapshot.js +20 -5
- package/dist/scene/assetCatalog.d.ts +21 -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 +13 -1
- package/dist/scene/colliders.js +37 -1
- package/dist/scene/entityStats.d.ts +11 -2
- package/dist/scene/entityStats.js +11 -2
- package/dist/scene/entityStore.d.ts +12 -1
- package/dist/scene/entityStore.js +15 -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 +5 -0
- package/dist/store/observableKeyedStore.js +34 -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 +4 -2
- package/dist/tactics/fallingGrid.js +4 -2
- 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 +30 -11
- package/dist/ui/gameLayout.js +30 -11
- 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/selectionModel.d.ts +92 -0
- package/dist/ui/selectionModel.js +88 -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/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/features.d.ts +115 -7
- package/dist/world/features.js +56 -5
- 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 +8 -0
- package/dist/world/roads.js +38 -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/terraform.d.ts +213 -1
- package/dist/world/terraform.js +655 -20
- package/dist/world/terrain.d.ts +119 -20
- package/dist/world/terrain.js +247 -41
- 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 -5389
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scene ownership boundary — gives every editor-visible object an explicit
|
|
3
|
+
* provenance and a single verdict (expose / bake / reject) so the editor never
|
|
4
|
+
* presents unauthored content as broken authored content.
|
|
5
|
+
*
|
|
6
|
+
* The product invariant is "author world content in the editor": the scene
|
|
7
|
+
* document is the source of truth. Runtime code, procedural generators, and
|
|
8
|
+
* simulation still put objects in front of the player that the document never
|
|
9
|
+
* described. This module classifies each such object by where it comes from and
|
|
10
|
+
* decides whether the editor may author it, may offer to bake it into the
|
|
11
|
+
* document, or must reject it as read-only runtime content — with a diagnostic
|
|
12
|
+
* that explains the decision. Genuinely runtime-only content is then declared
|
|
13
|
+
* with a reason rather than silently tolerated or exempted by game name.
|
|
14
|
+
*
|
|
15
|
+
* Everything here is plain serializable data and pure functions, so a
|
|
16
|
+
* {@link SceneOwnershipManifest} round-trips through JSON and the verdict for an
|
|
17
|
+
* object is deterministic given its declaration.
|
|
18
|
+
*/
|
|
19
|
+
/** Current {@link SceneOwnershipManifest} schema version. */
|
|
20
|
+
export const SCENE_OWNERSHIP_MANIFEST_VERSION = 1;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve one declaration into a single boundary verdict.
|
|
23
|
+
*
|
|
24
|
+
* - `authored` and `generated` provenance -> **expose** (generated objects are
|
|
25
|
+
* read-only; edit their source document object).
|
|
26
|
+
* - `runtime`/`transient` with a `bake` capability -> **bake** (offer import).
|
|
27
|
+
* - `runtime`/`transient` without `bake` -> **reject** (read-only); a missing
|
|
28
|
+
* `reason` marks it a boundary violation — content bypassing the document with
|
|
29
|
+
* no authored home, no way to bake, and no declared justification.
|
|
30
|
+
*
|
|
31
|
+
* @capability scene-ownership classify an editor-visible object as expose/bake/reject with a diagnostic
|
|
32
|
+
*/
|
|
33
|
+
export function classifyOwnership(declaration) {
|
|
34
|
+
const { provenance, capabilities, reason } = declaration;
|
|
35
|
+
const kind = provenance.kind;
|
|
36
|
+
if (kind === "authored") {
|
|
37
|
+
return {
|
|
38
|
+
decision: "expose",
|
|
39
|
+
provenance: kind,
|
|
40
|
+
readOnly: false,
|
|
41
|
+
bakeable: false,
|
|
42
|
+
reason: `authored document object "${provenance.documentId}"`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (kind === "generated") {
|
|
46
|
+
return {
|
|
47
|
+
decision: "expose",
|
|
48
|
+
provenance: kind,
|
|
49
|
+
readOnly: true,
|
|
50
|
+
bakeable: false,
|
|
51
|
+
reason: `generated from authored object "${provenance.sourceDocumentId}"; edit the source`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const canBake = capabilities?.bake === true;
|
|
55
|
+
if (canBake) {
|
|
56
|
+
return {
|
|
57
|
+
decision: "bake",
|
|
58
|
+
provenance: kind,
|
|
59
|
+
readOnly: true,
|
|
60
|
+
bakeable: true,
|
|
61
|
+
reason: reason ?? `runtime provider "${provenance.providerId}" can bake this into the document`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const hasReason = reason !== undefined && reason.trim() !== "";
|
|
65
|
+
const violation = hasReason
|
|
66
|
+
? undefined
|
|
67
|
+
: `${kind} object "${provenance.instanceId}" from provider "${provenance.providerId}" has no authored ` +
|
|
68
|
+
`document entry, no bake capability, and no declared reason — it bypasses the scene-ownership boundary`;
|
|
69
|
+
return {
|
|
70
|
+
decision: "reject",
|
|
71
|
+
provenance: kind,
|
|
72
|
+
readOnly: true,
|
|
73
|
+
bakeable: false,
|
|
74
|
+
reason: hasReason ? reason : `runtime-only content owned by provider "${provenance.providerId}"`,
|
|
75
|
+
violation,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Stable id string for a provenance — used to key diagnostics deterministically. */
|
|
79
|
+
function provenanceKey(provenance) {
|
|
80
|
+
switch (provenance.kind) {
|
|
81
|
+
case "authored":
|
|
82
|
+
return `authored:${provenance.documentId}`;
|
|
83
|
+
case "generated":
|
|
84
|
+
return `generated:${provenance.sourceDocumentId}/${provenance.instanceId}`;
|
|
85
|
+
default:
|
|
86
|
+
return `${provenance.kind}:${provenance.providerId}/${provenance.instanceId}`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Stable identity string for a provenance (e.g. `runtime:town/building-3`), suitable
|
|
91
|
+
* for keying an object in an editor tree or a diagnostics table.
|
|
92
|
+
*
|
|
93
|
+
* @capability scene-ownership derive a stable object key from its provenance
|
|
94
|
+
*/
|
|
95
|
+
export function ownershipKey(provenance) {
|
|
96
|
+
return provenanceKey(provenance);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Audit a keyed set of declarations and return one diagnostic per object that
|
|
100
|
+
* breaks the boundary contract (a `reject` verdict carrying a `violation`).
|
|
101
|
+
* Deterministic: diagnostics come back in the iteration order of `entries`.
|
|
102
|
+
*
|
|
103
|
+
* @capability scene-ownership audit editor-visible objects and report boundary violations
|
|
104
|
+
*/
|
|
105
|
+
export function collectOwnershipDiagnostics(entries) {
|
|
106
|
+
const out = [];
|
|
107
|
+
for (const [key, declaration] of entries) {
|
|
108
|
+
const verdict = classifyOwnership(declaration);
|
|
109
|
+
if (verdict.violation !== undefined) {
|
|
110
|
+
out.push({
|
|
111
|
+
key,
|
|
112
|
+
provenance: verdict.provenance,
|
|
113
|
+
decision: verdict.decision,
|
|
114
|
+
message: `${key}: ${verdict.violation}`,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Audit every declaration in a manifest, keying diagnostics by each object's
|
|
122
|
+
* provenance id. An empty result means the manifest declares all of its content
|
|
123
|
+
* cleanly — every object is authored, generated, bakeable, or a reasoned
|
|
124
|
+
* runtime/transient object.
|
|
125
|
+
*
|
|
126
|
+
* @capability scene-ownership audit a whole ownership manifest for boundary violations
|
|
127
|
+
*/
|
|
128
|
+
export function auditManifest(manifest) {
|
|
129
|
+
return collectOwnershipDiagnostics(manifest.declarations.map((declaration) => [provenanceKey(declaration.provenance), declaration]));
|
|
130
|
+
}
|
|
131
|
+
function isProvenance(value) {
|
|
132
|
+
if (typeof value !== "object" || value === null)
|
|
133
|
+
return false;
|
|
134
|
+
const record = value;
|
|
135
|
+
switch (record.kind) {
|
|
136
|
+
case "authored":
|
|
137
|
+
return typeof record.documentId === "string";
|
|
138
|
+
case "generated":
|
|
139
|
+
return typeof record.sourceDocumentId === "string" && typeof record.instanceId === "string";
|
|
140
|
+
case "runtime":
|
|
141
|
+
case "transient":
|
|
142
|
+
return typeof record.providerId === "string" && typeof record.instanceId === "string";
|
|
143
|
+
default:
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function isDeclaration(value) {
|
|
148
|
+
if (typeof value !== "object" || value === null)
|
|
149
|
+
return false;
|
|
150
|
+
const record = value;
|
|
151
|
+
if (!isProvenance(record.provenance))
|
|
152
|
+
return false;
|
|
153
|
+
if (record.reason !== undefined && typeof record.reason !== "string")
|
|
154
|
+
return false;
|
|
155
|
+
if (record.capabilities !== undefined && (typeof record.capabilities !== "object" || record.capabilities === null)) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Narrow unknown parsed JSON to a {@link SceneOwnershipManifest}. Structural only —
|
|
162
|
+
* verifies the version, the declarations array, and each declaration's provenance
|
|
163
|
+
* shape; it does not judge whether declarations satisfy the boundary (use
|
|
164
|
+
* {@link auditManifest} for that).
|
|
165
|
+
*
|
|
166
|
+
* @capability scene-ownership validate a serialized ownership manifest loaded from disk
|
|
167
|
+
*/
|
|
168
|
+
export function isSceneOwnershipManifest(value) {
|
|
169
|
+
if (typeof value !== "object" || value === null)
|
|
170
|
+
return false;
|
|
171
|
+
const record = value;
|
|
172
|
+
if (record.version !== SCENE_OWNERSHIP_MANIFEST_VERSION)
|
|
173
|
+
return false;
|
|
174
|
+
if (record.provider !== undefined && typeof record.provider !== "string")
|
|
175
|
+
return false;
|
|
176
|
+
if (!Array.isArray(record.declarations))
|
|
177
|
+
return false;
|
|
178
|
+
return record.declarations.every(isDeclaration);
|
|
179
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { SelectionSet } from "./selection.js";
|
|
2
|
+
/**
|
|
3
|
+
* The serializable shape of a {@link SelectionBookmarks} store: each key maps to
|
|
4
|
+
* its ordered, deduplicated id list. Plain data — safe to persist in a save file
|
|
5
|
+
* or replicate over the wire, and the exact input {@link createSelectionBookmarks}
|
|
6
|
+
* restores.
|
|
7
|
+
*/
|
|
8
|
+
export interface SelectionBookmarkSnapshot {
|
|
9
|
+
bookmarks: Record<string, readonly string[]>;
|
|
10
|
+
}
|
|
11
|
+
/** Outcome of a {@link SelectionBookmarks.prune} pass — what the validity predicate removed. */
|
|
12
|
+
export interface SelectionPruneResult {
|
|
13
|
+
/** Ids dropped from at least one bookmark because the predicate rejected them. */
|
|
14
|
+
removedIds: string[];
|
|
15
|
+
/** Bookmark keys deleted because pruning emptied them. */
|
|
16
|
+
clearedKeys: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A generic, keyed store of saved id sets ("bookmarks") over stable string ids —
|
|
20
|
+
* the reusable layer under RTS control groups, camera bookmarks, saved squads,
|
|
21
|
+
* editor selection presets, and accessibility recall. It owns storage only:
|
|
22
|
+
* binding, recall, enumeration, pruning, and serialization. It never touches the
|
|
23
|
+
* active {@link SelectionSet} or the camera — replacement/merge and focus stay
|
|
24
|
+
* caller hooks (see {@link recallSelectionBookmark}) so one store serves any
|
|
25
|
+
* genre, input scheme, or focus policy.
|
|
26
|
+
*
|
|
27
|
+
* Keys are opaque strings, so numbered control groups (`"1"`…`"9"`), named
|
|
28
|
+
* bookmarks (`"home"`, `"base"`), or per-owner namespaces all coexist. Each
|
|
29
|
+
* bookmark preserves insertion order and dedupes, matching {@link SelectionSet}.
|
|
30
|
+
*/
|
|
31
|
+
export interface SelectionBookmarks {
|
|
32
|
+
/** Replace the set under `key` with `ids` (ordered, deduped). Binding an empty set removes the key, so `has(key)` is then false and it drops out of {@link serialize}. */
|
|
33
|
+
bind(key: string, ids: Iterable<string>): void;
|
|
34
|
+
/** Add `ids` to the set under `key` (creating it if absent), skipping ones already present so order is stable. */
|
|
35
|
+
append(key: string, ids: Iterable<string>): void;
|
|
36
|
+
/** Remove `ids` from the set under `key`; if that empties the set, the key is deleted. No-op when the key is absent. */
|
|
37
|
+
remove(key: string, ids: Iterable<string>): void;
|
|
38
|
+
/** The ordered ids saved under `key`, or an empty array when the key is absent. The returned array is a fresh copy — mutating it never touches the store. */
|
|
39
|
+
recall(key: string): string[];
|
|
40
|
+
/** True when `key` holds a non-empty set. */
|
|
41
|
+
has(key: string): boolean;
|
|
42
|
+
/** Delete `key`; returns true when a set was removed. */
|
|
43
|
+
clear(key: string): boolean;
|
|
44
|
+
/** Delete every bookmark. */
|
|
45
|
+
clearAll(): void;
|
|
46
|
+
/** All bookmark keys in insertion order. */
|
|
47
|
+
keys(): string[];
|
|
48
|
+
/** Count of ids saved under `key`, or 0 when absent. */
|
|
49
|
+
size(key: string): number;
|
|
50
|
+
/**
|
|
51
|
+
* Drop every id the `isValid` predicate rejects from all bookmarks — the seam
|
|
52
|
+
* for destroyed entities, cross-scene ids, and ownership changes: the caller
|
|
53
|
+
* supplies validity, the store applies it. Bookmarks emptied by pruning are
|
|
54
|
+
* removed. Returns what was removed so callers can surface it.
|
|
55
|
+
*/
|
|
56
|
+
prune(isValid: (id: string) => boolean): SelectionPruneResult;
|
|
57
|
+
/** A plain-data copy of every bookmark — the exact input {@link createSelectionBookmarks} restores. */
|
|
58
|
+
serialize(): SelectionBookmarkSnapshot;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create a keyed bookmark store, optionally restored from a {@link serialize}
|
|
62
|
+
* snapshot. Restoration re-dedupes and drops empty sets, so a hand-authored or
|
|
63
|
+
* migrated snapshot always normalizes to the same invariants a live store holds.
|
|
64
|
+
*
|
|
65
|
+
* @capability selection-bookmarks keyed saved-set store (RTS control groups, camera bookmarks, saved squads) with prune + serialize
|
|
66
|
+
*/
|
|
67
|
+
export declare function createSelectionBookmarks(snapshot?: SelectionBookmarkSnapshot): SelectionBookmarks;
|
|
68
|
+
/** How a recalled bookmark folds into the active selection. */
|
|
69
|
+
export type BookmarkRecallMode = "replace" | "merge";
|
|
70
|
+
/** Caller hooks for {@link recallSelectionBookmark} — kept out of the store so focus and validity stay genre-owned. */
|
|
71
|
+
export interface RecallBookmarkOptions {
|
|
72
|
+
/** `"replace"` (default) swaps the active selection for the bookmark; `"merge"` unions it in. */
|
|
73
|
+
mode?: BookmarkRecallMode;
|
|
74
|
+
/**
|
|
75
|
+
* Validity predicate applied to the bookmark before it reaches the selection —
|
|
76
|
+
* stale ids (destroyed entities, wrong scene, lost ownership) are pruned from
|
|
77
|
+
* the stored bookmark in place, so recall self-heals. Omit to recall verbatim.
|
|
78
|
+
*/
|
|
79
|
+
isValid?: (id: string) => boolean;
|
|
80
|
+
/** Focus hook fired with the surviving ids (e.g. center/follow the camera). Never called when recall yields nothing. */
|
|
81
|
+
onFocus?: (ids: readonly string[]) => void;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Compose a bookmark recall onto an active {@link SelectionSet}: optionally prune
|
|
85
|
+
* stale ids (updating the stored bookmark), fold the survivors into the selection
|
|
86
|
+
* by `mode`, then fire the caller's focus hook. This is the one place the store,
|
|
87
|
+
* the selection, and the camera meet — kept as an explicit helper, not a store
|
|
88
|
+
* side effect, so games opt into the exact replacement/merge and focus policy
|
|
89
|
+
* they want. Returns the surviving ids that were applied.
|
|
90
|
+
*
|
|
91
|
+
* @capability selection-bookmark-recall fold a saved set into the active selection with stale-ref pruning and a caller focus hook
|
|
92
|
+
*/
|
|
93
|
+
export declare function recallSelectionBookmark(bookmarks: SelectionBookmarks, key: string, selection: SelectionSet, options?: RecallBookmarkOptions): string[];
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
function dedupe(ids) {
|
|
2
|
+
const out = [];
|
|
3
|
+
const seen = new Set();
|
|
4
|
+
for (const id of ids) {
|
|
5
|
+
if (seen.has(id))
|
|
6
|
+
continue;
|
|
7
|
+
seen.add(id);
|
|
8
|
+
out.push(id);
|
|
9
|
+
}
|
|
10
|
+
return out;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Create a keyed bookmark store, optionally restored from a {@link serialize}
|
|
14
|
+
* snapshot. Restoration re-dedupes and drops empty sets, so a hand-authored or
|
|
15
|
+
* migrated snapshot always normalizes to the same invariants a live store holds.
|
|
16
|
+
*
|
|
17
|
+
* @capability selection-bookmarks keyed saved-set store (RTS control groups, camera bookmarks, saved squads) with prune + serialize
|
|
18
|
+
*/
|
|
19
|
+
export function createSelectionBookmarks(snapshot) {
|
|
20
|
+
const groups = new Map();
|
|
21
|
+
if (snapshot !== undefined) {
|
|
22
|
+
for (const [key, ids] of Object.entries(snapshot.bookmarks)) {
|
|
23
|
+
const list = dedupe(ids);
|
|
24
|
+
if (list.length > 0)
|
|
25
|
+
groups.set(key, list);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
bind(key, ids) {
|
|
30
|
+
const list = dedupe(ids);
|
|
31
|
+
if (list.length === 0)
|
|
32
|
+
groups.delete(key);
|
|
33
|
+
else
|
|
34
|
+
groups.set(key, list);
|
|
35
|
+
},
|
|
36
|
+
append(key, ids) {
|
|
37
|
+
const existing = groups.get(key);
|
|
38
|
+
if (existing === undefined) {
|
|
39
|
+
const list = dedupe(ids);
|
|
40
|
+
if (list.length > 0)
|
|
41
|
+
groups.set(key, list);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const seen = new Set(existing);
|
|
45
|
+
for (const id of ids) {
|
|
46
|
+
if (seen.has(id))
|
|
47
|
+
continue;
|
|
48
|
+
seen.add(id);
|
|
49
|
+
existing.push(id);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
remove(key, ids) {
|
|
53
|
+
const existing = groups.get(key);
|
|
54
|
+
if (existing === undefined)
|
|
55
|
+
return;
|
|
56
|
+
const drop = new Set(ids);
|
|
57
|
+
const next = existing.filter((id) => !drop.has(id));
|
|
58
|
+
if (next.length === 0)
|
|
59
|
+
groups.delete(key);
|
|
60
|
+
else
|
|
61
|
+
groups.set(key, next);
|
|
62
|
+
},
|
|
63
|
+
recall(key) {
|
|
64
|
+
const existing = groups.get(key);
|
|
65
|
+
return existing === undefined ? [] : [...existing];
|
|
66
|
+
},
|
|
67
|
+
has: (key) => (groups.get(key)?.length ?? 0) > 0,
|
|
68
|
+
clear: (key) => groups.delete(key),
|
|
69
|
+
clearAll: () => groups.clear(),
|
|
70
|
+
keys: () => [...groups.keys()],
|
|
71
|
+
size: (key) => groups.get(key)?.length ?? 0,
|
|
72
|
+
prune(isValid) {
|
|
73
|
+
const removedIds = new Set();
|
|
74
|
+
const clearedKeys = [];
|
|
75
|
+
for (const [key, list] of [...groups]) {
|
|
76
|
+
const next = list.filter((id) => {
|
|
77
|
+
const keep = isValid(id);
|
|
78
|
+
if (!keep)
|
|
79
|
+
removedIds.add(id);
|
|
80
|
+
return keep;
|
|
81
|
+
});
|
|
82
|
+
if (next.length === list.length)
|
|
83
|
+
continue;
|
|
84
|
+
if (next.length === 0) {
|
|
85
|
+
groups.delete(key);
|
|
86
|
+
clearedKeys.push(key);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
groups.set(key, next);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { removedIds: [...removedIds], clearedKeys };
|
|
93
|
+
},
|
|
94
|
+
serialize: () => ({
|
|
95
|
+
bookmarks: Object.fromEntries([...groups].map(([key, list]) => [key, [...list]])),
|
|
96
|
+
}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Compose a bookmark recall onto an active {@link SelectionSet}: optionally prune
|
|
101
|
+
* stale ids (updating the stored bookmark), fold the survivors into the selection
|
|
102
|
+
* by `mode`, then fire the caller's focus hook. This is the one place the store,
|
|
103
|
+
* the selection, and the camera meet — kept as an explicit helper, not a store
|
|
104
|
+
* side effect, so games opt into the exact replacement/merge and focus policy
|
|
105
|
+
* they want. Returns the surviving ids that were applied.
|
|
106
|
+
*
|
|
107
|
+
* @capability selection-bookmark-recall fold a saved set into the active selection with stale-ref pruning and a caller focus hook
|
|
108
|
+
*/
|
|
109
|
+
export function recallSelectionBookmark(bookmarks, key, selection, options = {}) {
|
|
110
|
+
const { mode = "replace", isValid, onFocus } = options;
|
|
111
|
+
if (isValid !== undefined)
|
|
112
|
+
bookmarks.prune(isValid);
|
|
113
|
+
const ids = bookmarks.recall(key);
|
|
114
|
+
if (mode === "replace")
|
|
115
|
+
selection.replace(ids);
|
|
116
|
+
else
|
|
117
|
+
for (const id of ids)
|
|
118
|
+
selection.add(id);
|
|
119
|
+
if (ids.length > 0)
|
|
120
|
+
onFocus?.(ids);
|
|
121
|
+
return ids;
|
|
122
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { MountController, type MountSeat, type RideableConfig } from "./mount.js";
|
|
2
|
+
/** World-space `[x, y, z]` for a vehicle's current position. */
|
|
3
|
+
export type VehiclePosition = readonly [number, number, number];
|
|
4
|
+
/** A vehicle's world-space position and heading, used for {@link VehicleSeats.exit}'s dismount placement math. */
|
|
5
|
+
export interface VehiclePose {
|
|
6
|
+
position: VehiclePosition;
|
|
7
|
+
rotationY: number;
|
|
8
|
+
}
|
|
9
|
+
/** Options for {@link VehicleSeats.enter}. */
|
|
10
|
+
export interface EnterVehicleOptions {
|
|
11
|
+
/** Specific seat to board; omit to take the first free control seat, else the first free seat. */
|
|
12
|
+
seatId?: string;
|
|
13
|
+
}
|
|
14
|
+
/** Movement-lock patch for `entities.update(riderId, { movement: { ...current, ...patch } })` (#286.gameplay `movement.frozen`). */
|
|
15
|
+
export interface RiderMovementPatch {
|
|
16
|
+
frozen: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Result of {@link VehicleSeats.enter} — the resolved seat plus the camera/drive/movement patches to apply. */
|
|
19
|
+
export type EnterVehicleResult = {
|
|
20
|
+
ok: true;
|
|
21
|
+
seat: MountSeat;
|
|
22
|
+
/** Feed straight into `ctx.camera.follow(...)` — the vehicle while a control seat is taken, else the rider's own id. */
|
|
23
|
+
cameraTarget: string;
|
|
24
|
+
/** Entity this rider's axis input should now drive (`scene/mount`'s `driveTarget`); `null` for a passenger seat. */
|
|
25
|
+
driveTarget: string | null;
|
|
26
|
+
riderMovementPatch: RiderMovementPatch;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
reason: string;
|
|
30
|
+
};
|
|
31
|
+
/** Result of {@link VehicleSeats.exit} — the side-door placement plus the camera/movement patches to apply. */
|
|
32
|
+
export type ExitVehicleResult = {
|
|
33
|
+
ok: true;
|
|
34
|
+
vehicleId: string;
|
|
35
|
+
/** Where to `setPose` the rider — alongside the vehicle's side door, facing its heading. */
|
|
36
|
+
placement: VehiclePose;
|
|
37
|
+
cameraTarget: string;
|
|
38
|
+
riderMovementPatch: RiderMovementPatch;
|
|
39
|
+
} | {
|
|
40
|
+
ok: false;
|
|
41
|
+
reason: "not_seated";
|
|
42
|
+
};
|
|
43
|
+
/** Where {@link VehicleSeats.exit} steps the rider out, relative to the vehicle's heading. */
|
|
44
|
+
export interface DismountOffset {
|
|
45
|
+
/** Lateral distance from the vehicle's centerline; default 2.2. */
|
|
46
|
+
distance?: number;
|
|
47
|
+
/** Which side of the vehicle to step out on, relative to its heading; default `"right"`. */
|
|
48
|
+
side?: "left" | "right";
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Composes `scene/mount`'s control-transfer bookkeeping with the seat/camera/movement-mode transition
|
|
52
|
+
* every enter/exit-vehicle flow needs (#533.2): boarding resolves a free seat and reports the camera
|
|
53
|
+
* target, drive target, and rider movement-lock patch in one call; leaving computes a side-door
|
|
54
|
+
* placement next to the vehicle and reports the same triad in reverse. Pure — no entity/camera side
|
|
55
|
+
* effects — the caller applies `riderMovementPatch`/`placement`/`cameraTarget` via its own `ctx`.
|
|
56
|
+
*/
|
|
57
|
+
export declare class VehicleSeats {
|
|
58
|
+
private readonly controller;
|
|
59
|
+
constructor(controller?: MountController);
|
|
60
|
+
register(config: RideableConfig): void;
|
|
61
|
+
enter(riderId: string, vehicleId: string, options?: EnterVehicleOptions): EnterVehicleResult;
|
|
62
|
+
exit(riderId: string, vehiclePose: VehiclePose, offset?: DismountOffset): ExitVehicleResult;
|
|
63
|
+
isSeated(riderId: string): boolean;
|
|
64
|
+
driverOf(vehicleId: string): string | null;
|
|
65
|
+
get mounts(): MountController;
|
|
66
|
+
}
|
|
67
|
+
/** Builds a {@link VehicleSeats}, optionally over an existing `MountController` to share its occupancy. */
|
|
68
|
+
export declare function createVehicleSeats(controller?: MountController): VehicleSeats;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createMountController, MountController } from "./mount.js";
|
|
2
|
+
/**
|
|
3
|
+
* Composes `scene/mount`'s control-transfer bookkeeping with the seat/camera/movement-mode transition
|
|
4
|
+
* every enter/exit-vehicle flow needs (#533.2): boarding resolves a free seat and reports the camera
|
|
5
|
+
* target, drive target, and rider movement-lock patch in one call; leaving computes a side-door
|
|
6
|
+
* placement next to the vehicle and reports the same triad in reverse. Pure — no entity/camera side
|
|
7
|
+
* effects — the caller applies `riderMovementPatch`/`placement`/`cameraTarget` via its own `ctx`.
|
|
8
|
+
*/
|
|
9
|
+
export class VehicleSeats {
|
|
10
|
+
controller;
|
|
11
|
+
constructor(controller) {
|
|
12
|
+
this.controller = controller ?? createMountController();
|
|
13
|
+
}
|
|
14
|
+
register(config) {
|
|
15
|
+
this.controller.register(config);
|
|
16
|
+
}
|
|
17
|
+
enter(riderId, vehicleId, options = {}) {
|
|
18
|
+
const result = this.controller.mount(riderId, vehicleId, options.seatId);
|
|
19
|
+
if (!result.ok)
|
|
20
|
+
return { ok: false, reason: result.reason };
|
|
21
|
+
return {
|
|
22
|
+
ok: true,
|
|
23
|
+
seat: result.seat,
|
|
24
|
+
cameraTarget: this.controller.cameraTarget(riderId),
|
|
25
|
+
driveTarget: this.controller.driveTarget(riderId),
|
|
26
|
+
riderMovementPatch: { frozen: true },
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
exit(riderId, vehiclePose, offset = {}) {
|
|
30
|
+
const vehicleId = this.controller.dismount(riderId);
|
|
31
|
+
if (vehicleId === null)
|
|
32
|
+
return { ok: false, reason: "not_seated" };
|
|
33
|
+
const distance = offset.distance ?? 2.2;
|
|
34
|
+
const sign = offset.side === "left" ? -1 : 1;
|
|
35
|
+
const side = vehiclePose.rotationY + (Math.PI / 2) * sign;
|
|
36
|
+
const x = vehiclePose.position[0] + Math.sin(side) * distance;
|
|
37
|
+
const z = vehiclePose.position[2] + Math.cos(side) * distance;
|
|
38
|
+
return {
|
|
39
|
+
ok: true,
|
|
40
|
+
vehicleId,
|
|
41
|
+
placement: { position: [x, vehiclePose.position[1], z], rotationY: vehiclePose.rotationY },
|
|
42
|
+
cameraTarget: riderId,
|
|
43
|
+
riderMovementPatch: { frozen: false },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
isSeated(riderId) {
|
|
47
|
+
return this.controller.isSeated(riderId);
|
|
48
|
+
}
|
|
49
|
+
driverOf(vehicleId) {
|
|
50
|
+
return this.controller.driver(vehicleId);
|
|
51
|
+
}
|
|
52
|
+
get mounts() {
|
|
53
|
+
return this.controller;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Builds a {@link VehicleSeats}, optionally over an existing `MountController` to share its occupancy. */
|
|
57
|
+
export function createVehicleSeats(controller) {
|
|
58
|
+
return new VehicleSeats(controller);
|
|
59
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export type ColorHex = string;
|
|
2
|
+
/** @internal */
|
|
2
3
|
export declare function colorDistance(a: ColorHex, b: ColorHex): number;
|
|
4
|
+
/** @internal */
|
|
3
5
|
export declare function concealmentScore(entityColors: readonly ColorHex[], backgroundColors: readonly ColorHex[]): number;
|
|
4
6
|
export interface ConcealmentTarget {
|
|
5
7
|
id: string;
|
|
@@ -16,6 +18,7 @@ export interface ConcealmentSensor {
|
|
|
16
18
|
tick(targets: readonly ConcealmentTarget[], dt: number): ConcealmentSample[];
|
|
17
19
|
reset(id?: string): void;
|
|
18
20
|
}
|
|
21
|
+
/** @internal */
|
|
19
22
|
export declare function createConcealmentSensor(config?: {
|
|
20
23
|
threshold?: number;
|
|
21
24
|
}): ConcealmentSensor;
|
|
@@ -13,10 +13,12 @@ function redmean(a, b) {
|
|
|
13
13
|
return Math.sqrt((2 + rmean / 256) * dr * dr + 4 * dg * dg + (2 + (255 - rmean) / 256) * db * db);
|
|
14
14
|
}
|
|
15
15
|
const REDMEAN_MAX = redmean([0, 0, 0], [255, 255, 255]);
|
|
16
|
+
/** @internal */
|
|
16
17
|
export function colorDistance(a, b) {
|
|
17
18
|
const distance = redmean(parseHex(a), parseHex(b));
|
|
18
19
|
return REDMEAN_MAX === 0 ? 0 : Math.min(1, distance / REDMEAN_MAX);
|
|
19
20
|
}
|
|
21
|
+
/** @internal */
|
|
20
22
|
export function concealmentScore(entityColors, backgroundColors) {
|
|
21
23
|
if (entityColors.length === 0 || backgroundColors.length === 0)
|
|
22
24
|
return 0;
|
|
@@ -32,6 +34,7 @@ export function concealmentScore(entityColors, backgroundColors) {
|
|
|
32
34
|
}
|
|
33
35
|
return 1 - total / entityColors.length;
|
|
34
36
|
}
|
|
37
|
+
/** @internal */
|
|
35
38
|
export function createConcealmentSensor(config) {
|
|
36
39
|
const threshold = config?.threshold ?? 0.7;
|
|
37
40
|
const dwell = new Map();
|
|
@@ -11,6 +11,7 @@ export interface FreezeMonitor {
|
|
|
11
11
|
tick(subjects: readonly FreezeSubject[], frozenIds: ReadonlySet<string>, dt: number): FreezeViolation[];
|
|
12
12
|
reset(id?: string): void;
|
|
13
13
|
}
|
|
14
|
+
/** @internal */
|
|
14
15
|
export declare function createFreezeMonitor(config?: {
|
|
15
16
|
toleranceSpeed?: number;
|
|
16
17
|
graceSeconds?: number;
|
|
@@ -26,7 +26,8 @@ export interface FrustumProjection {
|
|
|
26
26
|
* Project a world point into the camera's view. Pure geometry — no three.js —
|
|
27
27
|
* so a game can run "is this framed?" checks headlessly (photo-mode scoring,
|
|
28
28
|
* server-side kill-cam validation) as well as from the live render camera.
|
|
29
|
-
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
30
31
|
export declare function projectToView(camera: FrustumCamera, point: EntityPosition): FrustumProjection;
|
|
31
32
|
export interface FramingConfig {
|
|
32
33
|
/** World-unit distance from camera that reads as "ideally framed" size. Default 6. */
|
|
@@ -36,7 +37,9 @@ export interface FramingConfig {
|
|
|
36
37
|
/** Weight of subject size (distance-to-ideal) in the framing score. Default 0.4. */
|
|
37
38
|
sizeWeight?: number;
|
|
38
39
|
}
|
|
39
|
-
/** 0 (not framed) .. 1 (dead-center, ideal distance) framing quality for an in-view projection.
|
|
40
|
+
/** 0 (not framed) .. 1 (dead-center, ideal distance) framing quality for an in-view projection.
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
40
43
|
export declare function framingScore(projection: FrustumProjection, config?: FramingConfig): number;
|
|
41
44
|
export interface FrustumSample {
|
|
42
45
|
id: string;
|
|
@@ -56,5 +59,6 @@ export interface FrustumSensor {
|
|
|
56
59
|
* A view-frustum sensor on a held camera object: which entities are in frame,
|
|
57
60
|
* how well framed they are, and how long they've stayed on-screen (photo-mode
|
|
58
61
|
* "is this subject framed", Content Warning-style monster-filming scoring).
|
|
59
|
-
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
60
64
|
export declare function createFrustumSensor(config?: FramingConfig): FrustumSensor;
|
|
@@ -19,7 +19,8 @@ const WORLD_UP = [0, 1, 0];
|
|
|
19
19
|
* Project a world point into the camera's view. Pure geometry — no three.js —
|
|
20
20
|
* so a game can run "is this framed?" checks headlessly (photo-mode scoring,
|
|
21
21
|
* server-side kill-cam validation) as well as from the live render camera.
|
|
22
|
-
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
23
24
|
export function projectToView(camera, point) {
|
|
24
25
|
const forward = normalize(subtract(camera.lookAt, camera.position));
|
|
25
26
|
const relative = subtract(point, camera.position);
|
|
@@ -47,7 +48,9 @@ export function projectToView(camera, point) {
|
|
|
47
48
|
const inView = Math.abs(screenX) <= 1 && Math.abs(screenY) <= 1;
|
|
48
49
|
return { inView, distance, screenX, screenY };
|
|
49
50
|
}
|
|
50
|
-
/** 0 (not framed) .. 1 (dead-center, ideal distance) framing quality for an in-view projection.
|
|
51
|
+
/** 0 (not framed) .. 1 (dead-center, ideal distance) framing quality for an in-view projection.
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
51
54
|
export function framingScore(projection, config) {
|
|
52
55
|
if (!projection.inView)
|
|
53
56
|
return 0;
|
|
@@ -65,7 +68,8 @@ export function framingScore(projection, config) {
|
|
|
65
68
|
* A view-frustum sensor on a held camera object: which entities are in frame,
|
|
66
69
|
* how well framed they are, and how long they've stayed on-screen (photo-mode
|
|
67
70
|
* "is this subject framed", Content Warning-style monster-filming scoring).
|
|
68
|
-
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
69
73
|
export function createFrustumSensor(config) {
|
|
70
74
|
const dwell = new Map();
|
|
71
75
|
return {
|
|
@@ -25,7 +25,10 @@ export interface SensorReading {
|
|
|
25
25
|
* `proximityPrompt` (a UI affordance), this reads world state the player has no
|
|
26
26
|
* other way to see — the strongest in-range reading wins, mirroring how a real
|
|
27
27
|
* handheld sensor needle settles on the loudest nearby source.
|
|
28
|
-
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
29
30
|
export declare function probeHiddenState(origin: EntityPosition, sources: readonly HiddenStateSource[], options: SensorProbeOptions): SensorReading | null;
|
|
30
|
-
/** All in-range readings for `variableId`, strongest first.
|
|
31
|
+
/** All in-range readings for `variableId`, strongest first.
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
31
34
|
export declare function probeHiddenStateAll(origin: EntityPosition, sources: readonly HiddenStateSource[], options: SensorProbeOptions): SensorReading[];
|
|
@@ -12,12 +12,15 @@ function strengthAt(distance, range, falloff) {
|
|
|
12
12
|
* `proximityPrompt` (a UI affordance), this reads world state the player has no
|
|
13
13
|
* other way to see — the strongest in-range reading wins, mirroring how a real
|
|
14
14
|
* handheld sensor needle settles on the loudest nearby source.
|
|
15
|
-
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
16
17
|
export function probeHiddenState(origin, sources, options) {
|
|
17
18
|
const readings = probeHiddenStateAll(origin, sources, options);
|
|
18
19
|
return readings.length === 0 ? null : readings[0];
|
|
19
20
|
}
|
|
20
|
-
/** All in-range readings for `variableId`, strongest first.
|
|
21
|
+
/** All in-range readings for `variableId`, strongest first.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
21
24
|
export function probeHiddenStateAll(origin, sources, options) {
|
|
22
25
|
const { range, variableId, falloff = "linear" } = options;
|
|
23
26
|
const readings = [];
|