@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,71 @@
|
|
|
1
|
+
import type { Aabb } from "./geometry.js";
|
|
2
|
+
import type { GrassEnvironmentConfig } from "./features.js";
|
|
3
|
+
import type { SceneDocumentLike, SceneVolumeLike } from "./sceneShapes.js";
|
|
4
|
+
/** The editor volume kind that marks an area as vegetation fill. */
|
|
5
|
+
export declare const VEGETATION_VOLUME_KIND = "vegetation";
|
|
6
|
+
/**
|
|
7
|
+
* How a vegetation volume fills its area, read from the volume's `meta`.
|
|
8
|
+
* `density` is items per square meter — the one slider number: grass blades,
|
|
9
|
+
* trees, bushes, rocks all scale with it. Every field has a default, so a
|
|
10
|
+
* freshly placed `kind: "vegetation"` volume already grows grass.
|
|
11
|
+
*/
|
|
12
|
+
export interface VegetationSettings {
|
|
13
|
+
/** `"grass"` for shell-rendered blades, otherwise an asset/catalog item id the game maps to a model. */
|
|
14
|
+
item: string;
|
|
15
|
+
/** Items per square meter (grass blades: ~4; trees: ~0.02; bushes: ~0.08). */
|
|
16
|
+
density: number;
|
|
17
|
+
/** Random uniform scale range applied per placement. */
|
|
18
|
+
minScale: number;
|
|
19
|
+
maxScale: number;
|
|
20
|
+
/** Minimum spacing between placements in meters; 0 allows clumping. */
|
|
21
|
+
minDistance: number;
|
|
22
|
+
/** Extra seed folded into the volume id so re-rolls are one string away. */
|
|
23
|
+
seed: string;
|
|
24
|
+
}
|
|
25
|
+
/** Defaults a bare `kind: "vegetation"` volume grows with: grass at 4 blades/m². */
|
|
26
|
+
export declare const VEGETATION_DEFAULTS: VegetationSettings;
|
|
27
|
+
/** True when an editor volume is a vegetation fill area.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export declare function isVegetationVolume(volume: SceneVolumeLike): boolean;
|
|
31
|
+
/** The volume's vegetation settings with defaults filled in; null for non-vegetation volumes.
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export declare function readVegetationSettings(volume: SceneVolumeLike): VegetationSettings | null;
|
|
35
|
+
/** The ground-plane footprint of a volume: box half-extents or sphere/cylinder radius.
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
export declare function vegetationFootprint(volume: SceneVolumeLike): Aabb;
|
|
39
|
+
/** One placed vegetation instance — position on the ground plane plus per-instance variation. */
|
|
40
|
+
export interface VegetationPlacement {
|
|
41
|
+
id: string;
|
|
42
|
+
volumeId: string;
|
|
43
|
+
item: string;
|
|
44
|
+
x: number;
|
|
45
|
+
z: number;
|
|
46
|
+
scale: number;
|
|
47
|
+
rotation: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Deterministic placements for one vegetation volume: scatter its footprint at
|
|
51
|
+
* `density` items/m² (respecting `minDistance`), clip round shapes to their
|
|
52
|
+
* radius, and derive per-instance scale/rotation from the volume id + seed, so
|
|
53
|
+
* the same saved scene always grows the same field.
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveVegetationVolume(volume: SceneVolumeLike): VegetationPlacement[];
|
|
57
|
+
/**
|
|
58
|
+
* All model-item placements in a document (every vegetation volume except
|
|
59
|
+
* `item: "grass"`, which the shell renders as blades — see
|
|
60
|
+
* `grassPatchesFromVegetation`). A game maps each placement's `item` to a
|
|
61
|
+
* mesh/entity via its render catalog and places it grounded.
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveVegetation(doc: SceneDocumentLike): VegetationPlacement[];
|
|
65
|
+
/**
|
|
66
|
+
* Grass-blade patches for every `item: "grass"` vegetation volume, ready to
|
|
67
|
+
* spread into `environment()`'s `grass` list — the volume's density number is
|
|
68
|
+
* the blades-per-m² the shell renders, so the editor slider drives it directly.
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
export declare function grassPatchesFromVegetation(doc: SceneDocumentLike): GrassEnvironmentConfig[];
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { scatter } from "./scatter.js";
|
|
2
|
+
/** The editor volume kind that marks an area as vegetation fill. */
|
|
3
|
+
export const VEGETATION_VOLUME_KIND = "vegetation";
|
|
4
|
+
/** Defaults a bare `kind: "vegetation"` volume grows with: grass at 4 blades/m². */
|
|
5
|
+
export const VEGETATION_DEFAULTS = {
|
|
6
|
+
item: "grass",
|
|
7
|
+
density: 4,
|
|
8
|
+
minScale: 0.8,
|
|
9
|
+
maxScale: 1.2,
|
|
10
|
+
minDistance: 0,
|
|
11
|
+
seed: "",
|
|
12
|
+
};
|
|
13
|
+
function metaNumber(meta, key, fallback) {
|
|
14
|
+
const value = meta?.[key];
|
|
15
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
16
|
+
}
|
|
17
|
+
function metaString(meta, key, fallback) {
|
|
18
|
+
const value = meta?.[key];
|
|
19
|
+
return typeof value === "string" && value.length > 0 ? value : fallback;
|
|
20
|
+
}
|
|
21
|
+
/** True when an editor volume is a vegetation fill area.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export function isVegetationVolume(volume) {
|
|
25
|
+
return volume.kind === VEGETATION_VOLUME_KIND;
|
|
26
|
+
}
|
|
27
|
+
/** The volume's vegetation settings with defaults filled in; null for non-vegetation volumes.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export function readVegetationSettings(volume) {
|
|
31
|
+
if (!isVegetationVolume(volume))
|
|
32
|
+
return null;
|
|
33
|
+
return {
|
|
34
|
+
item: metaString(volume.meta, "item", VEGETATION_DEFAULTS.item),
|
|
35
|
+
density: Math.max(0, metaNumber(volume.meta, "density", VEGETATION_DEFAULTS.density)),
|
|
36
|
+
minScale: metaNumber(volume.meta, "minScale", VEGETATION_DEFAULTS.minScale),
|
|
37
|
+
maxScale: metaNumber(volume.meta, "maxScale", VEGETATION_DEFAULTS.maxScale),
|
|
38
|
+
minDistance: Math.max(0, metaNumber(volume.meta, "minDistance", VEGETATION_DEFAULTS.minDistance)),
|
|
39
|
+
seed: metaString(volume.meta, "seed", VEGETATION_DEFAULTS.seed),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** The ground-plane footprint of a volume: box half-extents or sphere/cylinder radius.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export function vegetationFootprint(volume) {
|
|
46
|
+
const halfW = volume.shape === "box" ? (volume.halfExtents?.x ?? 5) : (volume.radius ?? 5);
|
|
47
|
+
const halfD = volume.shape === "box" ? (volume.halfExtents?.z ?? 5) : (volume.radius ?? 5);
|
|
48
|
+
return {
|
|
49
|
+
minX: volume.center.x - halfW,
|
|
50
|
+
minZ: volume.center.z - halfD,
|
|
51
|
+
maxX: volume.center.x + halfW,
|
|
52
|
+
maxZ: volume.center.z + halfD,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function placementHash(volumeId, seed, index, salt) {
|
|
56
|
+
const text = `${volumeId}:${seed}:${index}:${salt}`;
|
|
57
|
+
let h = 2166136261 >>> 0;
|
|
58
|
+
for (let i = 0; i < text.length; i++) {
|
|
59
|
+
h ^= text.charCodeAt(i);
|
|
60
|
+
h = Math.imul(h, 16777619);
|
|
61
|
+
}
|
|
62
|
+
return (h >>> 0) / 4294967296;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Deterministic placements for one vegetation volume: scatter its footprint at
|
|
66
|
+
* `density` items/m² (respecting `minDistance`), clip round shapes to their
|
|
67
|
+
* radius, and derive per-instance scale/rotation from the volume id + seed, so
|
|
68
|
+
* the same saved scene always grows the same field.
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
export function resolveVegetationVolume(volume) {
|
|
72
|
+
const settings = readVegetationSettings(volume);
|
|
73
|
+
if (settings === null || settings.density <= 0)
|
|
74
|
+
return [];
|
|
75
|
+
const area = vegetationFootprint(volume);
|
|
76
|
+
const points = scatter({
|
|
77
|
+
area,
|
|
78
|
+
density: settings.density,
|
|
79
|
+
minDistance: settings.minDistance,
|
|
80
|
+
seed: `${volume.id}:${settings.seed}`,
|
|
81
|
+
});
|
|
82
|
+
const round = volume.shape !== "box";
|
|
83
|
+
const radius = volume.radius ?? 5;
|
|
84
|
+
const radiusSq = radius * radius;
|
|
85
|
+
const placements = [];
|
|
86
|
+
for (const point of points) {
|
|
87
|
+
if (round) {
|
|
88
|
+
const dx = point.x - volume.center.x;
|
|
89
|
+
const dz = point.z - volume.center.z;
|
|
90
|
+
if (dx * dx + dz * dz > radiusSq)
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const t = placementHash(volume.id, settings.seed, point.index, 0x51);
|
|
94
|
+
placements.push({
|
|
95
|
+
id: `${volume.id}/${point.index}`,
|
|
96
|
+
volumeId: volume.id,
|
|
97
|
+
item: settings.item,
|
|
98
|
+
x: point.x,
|
|
99
|
+
z: point.z,
|
|
100
|
+
scale: settings.minScale + (settings.maxScale - settings.minScale) * t,
|
|
101
|
+
rotation: placementHash(volume.id, settings.seed, point.index, 0x9e) * Math.PI * 2,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return placements;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* All model-item placements in a document (every vegetation volume except
|
|
108
|
+
* `item: "grass"`, which the shell renders as blades — see
|
|
109
|
+
* `grassPatchesFromVegetation`). A game maps each placement's `item` to a
|
|
110
|
+
* mesh/entity via its render catalog and places it grounded.
|
|
111
|
+
* @internal
|
|
112
|
+
*/
|
|
113
|
+
export function resolveVegetation(doc) {
|
|
114
|
+
const out = [];
|
|
115
|
+
for (const volume of doc.volumes) {
|
|
116
|
+
if (!isVegetationVolume(volume))
|
|
117
|
+
continue;
|
|
118
|
+
const settings = readVegetationSettings(volume);
|
|
119
|
+
if (settings === null || settings.item === "grass")
|
|
120
|
+
continue;
|
|
121
|
+
out.push(...resolveVegetationVolume(volume));
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Grass-blade patches for every `item: "grass"` vegetation volume, ready to
|
|
127
|
+
* spread into `environment()`'s `grass` list — the volume's density number is
|
|
128
|
+
* the blades-per-m² the shell renders, so the editor slider drives it directly.
|
|
129
|
+
* @internal
|
|
130
|
+
*/
|
|
131
|
+
export function grassPatchesFromVegetation(doc) {
|
|
132
|
+
const patches = [];
|
|
133
|
+
for (const volume of doc.volumes) {
|
|
134
|
+
if (!isVegetationVolume(volume))
|
|
135
|
+
continue;
|
|
136
|
+
const settings = readVegetationSettings(volume);
|
|
137
|
+
if (settings === null || settings.item !== "grass" || settings.density <= 0)
|
|
138
|
+
continue;
|
|
139
|
+
const area = vegetationFootprint(volume);
|
|
140
|
+
patches.push({
|
|
141
|
+
area: {
|
|
142
|
+
w: area.maxX - area.minX,
|
|
143
|
+
d: area.maxZ - area.minZ,
|
|
144
|
+
position: [volume.center.x, volume.center.z],
|
|
145
|
+
},
|
|
146
|
+
density: settings.density,
|
|
147
|
+
seed: `${volume.id}:${settings.seed}`,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return patches;
|
|
151
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type { FogBounds } from "./fog.js";
|
|
2
|
+
/** Numeric code for a cell no group member has seen, or has fully forgotten. */
|
|
3
|
+
export declare const VISIBILITY_HIDDEN = 0;
|
|
4
|
+
/** Numeric code for a cell seen before but not currently in view (last-known). */
|
|
5
|
+
export declare const VISIBILITY_REMEMBERED = 1;
|
|
6
|
+
/** Numeric code for a cell a group currently observes. */
|
|
7
|
+
export declare const VISIBILITY_OBSERVED = 2;
|
|
8
|
+
/** One viewer group's knowledge of a cell: never/forgotten, last-known, or live. */
|
|
9
|
+
export type VisibilityState = "hidden" | "remembered" | "observed";
|
|
10
|
+
/**
|
|
11
|
+
* How a cell decays after a group stops observing it — the terrain-memory policy.
|
|
12
|
+
* `permanent` keeps last-known terrain forever (RTS explored map); `none` drops
|
|
13
|
+
* it straight back to hidden the moment it leaves view (pure line-of-sight
|
|
14
|
+
* stealth); `decay` remembers it for `updates` observe cycles, then hides it.
|
|
15
|
+
* Day/night, height, sensor, and stealth rules are NOT encoded here — the caller
|
|
16
|
+
* bakes those into which cells it reports as observed each update.
|
|
17
|
+
*/
|
|
18
|
+
export type VisibilityMemory = {
|
|
19
|
+
readonly kind: "permanent";
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: "none";
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: "decay";
|
|
24
|
+
readonly updates: number;
|
|
25
|
+
};
|
|
26
|
+
/** Construction options for {@link createVisibilityField}. */
|
|
27
|
+
export interface VisibilityFieldConfig {
|
|
28
|
+
/** World-space rectangle the grid covers (reused from `world/fog`). */
|
|
29
|
+
readonly bounds: FogBounds;
|
|
30
|
+
/** World units per grid cell. Must be positive. */
|
|
31
|
+
readonly cellSize: number;
|
|
32
|
+
/** Default memory policy applied to every group. Default `{ kind: "permanent" }`. */
|
|
33
|
+
readonly memory?: VisibilityMemory;
|
|
34
|
+
/** Rehydrate from a previously serialized field (see {@link VisibilityField.toState}). */
|
|
35
|
+
readonly restore?: VisibilityFieldState;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The cells that changed state for one group in a single {@link VisibilityField.observe}
|
|
39
|
+
* call — a pure incremental readout for rendering, minimaps, AI, UI, and
|
|
40
|
+
* authoritative replication. Never lists unchanged cells, so it stays bounded by
|
|
41
|
+
* how much the group's view actually moved.
|
|
42
|
+
*/
|
|
43
|
+
export interface VisibilityDelta {
|
|
44
|
+
readonly group: string;
|
|
45
|
+
/** Cells that entered observation this update. */
|
|
46
|
+
readonly observed: readonly number[];
|
|
47
|
+
/** Cells that left observation into remembered (last-known) state. */
|
|
48
|
+
readonly remembered: readonly number[];
|
|
49
|
+
/** Cells that fell out of memory entirely (decay expiry or `none` policy). */
|
|
50
|
+
readonly hidden: readonly number[];
|
|
51
|
+
}
|
|
52
|
+
/** Sparse serialized knowledge for one group — only non-hidden cells are stored. */
|
|
53
|
+
export interface VisibilityGroupState {
|
|
54
|
+
/** Currently observed cell indices. */
|
|
55
|
+
readonly observed: readonly number[];
|
|
56
|
+
/** Remembered cells as `[cellIndex, lastObservedTick]` pairs. */
|
|
57
|
+
readonly remembered: readonly (readonly [number, number])[];
|
|
58
|
+
/** Monotonic update counter, used to age remembered cells under a decay policy. */
|
|
59
|
+
readonly tick: number;
|
|
60
|
+
/** Per-group memory override, when it differs from the field default. */
|
|
61
|
+
readonly memory?: VisibilityMemory;
|
|
62
|
+
}
|
|
63
|
+
/** Serializable snapshot of a whole field — JSON round-trips losslessly. */
|
|
64
|
+
export interface VisibilityFieldState {
|
|
65
|
+
readonly cols: number;
|
|
66
|
+
readonly rows: number;
|
|
67
|
+
readonly minX: number;
|
|
68
|
+
readonly minZ: number;
|
|
69
|
+
readonly cellSize: number;
|
|
70
|
+
readonly memory: VisibilityMemory;
|
|
71
|
+
readonly groups: Readonly<Record<string, VisibilityGroupState>>;
|
|
72
|
+
}
|
|
73
|
+
/** Dense per-cell readout for one group, shaped for minimap/overlay drawing. */
|
|
74
|
+
export interface VisibilityCells {
|
|
75
|
+
readonly cols: number;
|
|
76
|
+
readonly rows: number;
|
|
77
|
+
readonly minX: number;
|
|
78
|
+
readonly minZ: number;
|
|
79
|
+
readonly cellSize: number;
|
|
80
|
+
/** Row-major `VISIBILITY_*` codes; index = row * cols + col. */
|
|
81
|
+
readonly codes: Uint8Array;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* A gameplay (fog-of-war) knowledge field: per viewer group, every grid cell is
|
|
85
|
+
* hidden, remembered, or observed. Distinct from render culling in
|
|
86
|
+
* `core/visibility` — this models what a team KNOWS, not what a camera can draw.
|
|
87
|
+
* It generalizes `world/fog`'s single-group reveal-once model to many groups
|
|
88
|
+
* with configurable terrain memory, and keeps each group's knowledge isolated so
|
|
89
|
+
* one group's hidden state can never be derived from another's.
|
|
90
|
+
*/
|
|
91
|
+
export interface VisibilityField {
|
|
92
|
+
readonly cols: number;
|
|
93
|
+
readonly rows: number;
|
|
94
|
+
cellCount(): number;
|
|
95
|
+
colOf(x: number): number;
|
|
96
|
+
rowOf(z: number): number;
|
|
97
|
+
/** Row-major cell index for a world point, clamped into the grid. */
|
|
98
|
+
cellIndex(x: number, z: number): number;
|
|
99
|
+
/** Register a viewer group, optionally with its own memory policy. Idempotent. */
|
|
100
|
+
ensureGroup(group: string, memory?: VisibilityMemory): void;
|
|
101
|
+
hasGroup(group: string): boolean;
|
|
102
|
+
groups(): string[];
|
|
103
|
+
/** Forget everything for a group and drop it. */
|
|
104
|
+
removeGroup(group: string): void;
|
|
105
|
+
/**
|
|
106
|
+
* Cell indices whose centers fall within `radius` of a world point (bounded
|
|
107
|
+
* disc), appended into `out` when supplied. Feed these into {@link observe};
|
|
108
|
+
* union several sources' discs before observing to model overlapping observers.
|
|
109
|
+
*/
|
|
110
|
+
cellsInRadius(x: number, z: number, radius: number, out?: number[]): number[];
|
|
111
|
+
/**
|
|
112
|
+
* Replace a group's observed set for this update. Cells newly covered become
|
|
113
|
+
* observed; cells that dropped out become remembered (or hidden under `none`);
|
|
114
|
+
* decayed memory expires. Work is bounded by the observed + remembered working
|
|
115
|
+
* sets — it never scans the whole grid. Returns the resulting {@link VisibilityDelta}.
|
|
116
|
+
*/
|
|
117
|
+
observe(group: string, cells: Iterable<number>): VisibilityDelta;
|
|
118
|
+
/** Convenience {@link observe} over a single disc around a source. */
|
|
119
|
+
observeCircle(group: string, x: number, z: number, radius: number): VisibilityDelta;
|
|
120
|
+
stateAtCell(group: string, cell: number): VisibilityState;
|
|
121
|
+
stateAt(group: string, x: number, z: number): VisibilityState;
|
|
122
|
+
isObserved(group: string, x: number, z: number): boolean;
|
|
123
|
+
isRemembered(group: string, x: number, z: number): boolean;
|
|
124
|
+
/** Terrain disclosure: observed OR remembered (anything the group has ever mapped). */
|
|
125
|
+
isKnown(group: string, x: number, z: number): boolean;
|
|
126
|
+
observedCount(group: string): number;
|
|
127
|
+
knownCount(group: string): number;
|
|
128
|
+
/**
|
|
129
|
+
* Authoritative entity-disclosure filter: keep only entities standing in a cell
|
|
130
|
+
* the group currently OBSERVES. Remembered and hidden cells never disclose live
|
|
131
|
+
* entities, so a unit that moved away or was destroyed re-hides. Reads only this
|
|
132
|
+
* group's state, so it is the seam that stops one group's hidden entities from
|
|
133
|
+
* leaking into another group's replicated view.
|
|
134
|
+
*/
|
|
135
|
+
visibleTo<T>(group: string, entities: readonly T[], positionOf: (entity: T) => {
|
|
136
|
+
readonly x: number;
|
|
137
|
+
readonly z: number;
|
|
138
|
+
}): T[];
|
|
139
|
+
/** Dense per-cell codes for a group, for minimap/overlay rendering. */
|
|
140
|
+
cells(group: string): VisibilityCells;
|
|
141
|
+
/** Sparse serializable snapshot; round-trips through {@link createVisibilityField}'s `restore`. */
|
|
142
|
+
toState(): VisibilityFieldState;
|
|
143
|
+
/** Forget one group's knowledge, or every group when `group` is omitted. */
|
|
144
|
+
reset(group?: string): void;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Build a per-group gameplay visibility field. First adopters: an RTS/stealth
|
|
148
|
+
* team whose scout observes terrain (which stays remembered after it leaves)
|
|
149
|
+
* while enemy units re-hide once no scout observes their cell, and any
|
|
150
|
+
* authoritative host that must filter hidden entities out of a client's replica.
|
|
151
|
+
*
|
|
152
|
+
* @capability visibility-field per-viewer-group observed/remembered/hidden fog-of-war knowledge with terrain memory and authoritative entity disclosure
|
|
153
|
+
*/
|
|
154
|
+
export declare function createVisibilityField(config: VisibilityFieldConfig): VisibilityField;
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/** Numeric code for a cell no group member has seen, or has fully forgotten. */
|
|
2
|
+
export const VISIBILITY_HIDDEN = 0;
|
|
3
|
+
/** Numeric code for a cell seen before but not currently in view (last-known). */
|
|
4
|
+
export const VISIBILITY_REMEMBERED = 1;
|
|
5
|
+
/** Numeric code for a cell a group currently observes. */
|
|
6
|
+
export const VISIBILITY_OBSERVED = 2;
|
|
7
|
+
function clampInt(value, min, max) {
|
|
8
|
+
const rounded = Math.floor(value);
|
|
9
|
+
return rounded < min ? min : rounded > max ? max : rounded;
|
|
10
|
+
}
|
|
11
|
+
function stateOf(code) {
|
|
12
|
+
return code === VISIBILITY_OBSERVED
|
|
13
|
+
? "observed"
|
|
14
|
+
: code === VISIBILITY_REMEMBERED
|
|
15
|
+
? "remembered"
|
|
16
|
+
: "hidden";
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build a per-group gameplay visibility field. First adopters: an RTS/stealth
|
|
20
|
+
* team whose scout observes terrain (which stays remembered after it leaves)
|
|
21
|
+
* while enemy units re-hide once no scout observes their cell, and any
|
|
22
|
+
* authoritative host that must filter hidden entities out of a client's replica.
|
|
23
|
+
*
|
|
24
|
+
* @capability visibility-field per-viewer-group observed/remembered/hidden fog-of-war knowledge with terrain memory and authoritative entity disclosure
|
|
25
|
+
*/
|
|
26
|
+
export function createVisibilityField(config) {
|
|
27
|
+
const cellSize = config.cellSize;
|
|
28
|
+
if (cellSize <= 0)
|
|
29
|
+
throw new Error("createVisibilityField: cellSize must be positive");
|
|
30
|
+
const restore = config.restore;
|
|
31
|
+
const minX = restore?.minX ?? config.bounds.minX;
|
|
32
|
+
const minZ = restore?.minZ ?? config.bounds.minZ;
|
|
33
|
+
const cols = restore?.cols ?? Math.max(1, Math.ceil((config.bounds.maxX - config.bounds.minX) / cellSize));
|
|
34
|
+
const rows = restore?.rows ?? Math.max(1, Math.ceil((config.bounds.maxZ - config.bounds.minZ) / cellSize));
|
|
35
|
+
const total = cols * rows;
|
|
36
|
+
const defaultMemory = restore?.memory ?? config.memory ?? { kind: "permanent" };
|
|
37
|
+
const groups = new Map();
|
|
38
|
+
function makeGroup(memory) {
|
|
39
|
+
return {
|
|
40
|
+
codes: new Uint8Array(total),
|
|
41
|
+
observed: new Set(),
|
|
42
|
+
remembered: new Map(),
|
|
43
|
+
tick: 0,
|
|
44
|
+
memory,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function getGroup(group) {
|
|
48
|
+
let data = groups.get(group);
|
|
49
|
+
if (data === undefined) {
|
|
50
|
+
data = makeGroup(defaultMemory);
|
|
51
|
+
groups.set(group, data);
|
|
52
|
+
}
|
|
53
|
+
return data;
|
|
54
|
+
}
|
|
55
|
+
if (restore !== undefined) {
|
|
56
|
+
for (const [name, state] of Object.entries(restore.groups)) {
|
|
57
|
+
const data = makeGroup(state.memory ?? defaultMemory);
|
|
58
|
+
data.tick = state.tick;
|
|
59
|
+
for (const cell of state.observed) {
|
|
60
|
+
if (cell >= 0 && cell < total) {
|
|
61
|
+
data.codes[cell] = VISIBILITY_OBSERVED;
|
|
62
|
+
data.observed.add(cell);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
for (const [cell, tick] of state.remembered) {
|
|
66
|
+
if (cell >= 0 && cell < total && data.codes[cell] === VISIBILITY_HIDDEN) {
|
|
67
|
+
data.codes[cell] = VISIBILITY_REMEMBERED;
|
|
68
|
+
data.remembered.set(cell, tick);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
groups.set(name, data);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function colOf(x) {
|
|
75
|
+
return clampInt((x - minX) / cellSize, 0, cols - 1);
|
|
76
|
+
}
|
|
77
|
+
function rowOf(z) {
|
|
78
|
+
return clampInt((z - minZ) / cellSize, 0, rows - 1);
|
|
79
|
+
}
|
|
80
|
+
function cellIndex(x, z) {
|
|
81
|
+
return rowOf(z) * cols + colOf(x);
|
|
82
|
+
}
|
|
83
|
+
function cellsInRadius(x, z, radius, out = []) {
|
|
84
|
+
const centerCol = colOf(x);
|
|
85
|
+
const centerRow = rowOf(z);
|
|
86
|
+
if (radius <= 0) {
|
|
87
|
+
out.push(centerRow * cols + centerCol);
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
const span = Math.ceil(radius / cellSize);
|
|
91
|
+
const radiusSq = radius * radius;
|
|
92
|
+
for (let dr = -span; dr <= span; dr += 1) {
|
|
93
|
+
const row = centerRow + dr;
|
|
94
|
+
if (row < 0 || row >= rows)
|
|
95
|
+
continue;
|
|
96
|
+
for (let dc = -span; dc <= span; dc += 1) {
|
|
97
|
+
const col = centerCol + dc;
|
|
98
|
+
if (col < 0 || col >= cols)
|
|
99
|
+
continue;
|
|
100
|
+
const cellX = minX + (col + 0.5) * cellSize;
|
|
101
|
+
const cellZ = minZ + (row + 0.5) * cellSize;
|
|
102
|
+
const dx = cellX - x;
|
|
103
|
+
const dz = cellZ - z;
|
|
104
|
+
if (dx * dx + dz * dz > radiusSq)
|
|
105
|
+
continue;
|
|
106
|
+
out.push(row * cols + col);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
function observe(group, cells) {
|
|
112
|
+
const data = getGroup(group);
|
|
113
|
+
data.tick += 1;
|
|
114
|
+
const now = data.tick;
|
|
115
|
+
const remembering = data.memory.kind !== "none";
|
|
116
|
+
const next = new Set();
|
|
117
|
+
const observedDelta = [];
|
|
118
|
+
for (const cell of cells) {
|
|
119
|
+
if (cell < 0 || cell >= total || next.has(cell))
|
|
120
|
+
continue;
|
|
121
|
+
next.add(cell);
|
|
122
|
+
if (data.codes[cell] !== VISIBILITY_OBSERVED) {
|
|
123
|
+
data.codes[cell] = VISIBILITY_OBSERVED;
|
|
124
|
+
data.remembered.delete(cell);
|
|
125
|
+
observedDelta.push(cell);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const rememberedDelta = [];
|
|
129
|
+
const hiddenDelta = [];
|
|
130
|
+
for (const cell of data.observed) {
|
|
131
|
+
if (next.has(cell))
|
|
132
|
+
continue;
|
|
133
|
+
if (remembering) {
|
|
134
|
+
data.codes[cell] = VISIBILITY_REMEMBERED;
|
|
135
|
+
data.remembered.set(cell, now);
|
|
136
|
+
rememberedDelta.push(cell);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
data.codes[cell] = VISIBILITY_HIDDEN;
|
|
140
|
+
hiddenDelta.push(cell);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
data.observed = next;
|
|
144
|
+
if (data.memory.kind === "decay") {
|
|
145
|
+
const maxAge = data.memory.updates;
|
|
146
|
+
for (const [cell, seen] of data.remembered) {
|
|
147
|
+
if (now - seen >= maxAge) {
|
|
148
|
+
data.codes[cell] = VISIBILITY_HIDDEN;
|
|
149
|
+
data.remembered.delete(cell);
|
|
150
|
+
hiddenDelta.push(cell);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return { group, observed: observedDelta, remembered: rememberedDelta, hidden: hiddenDelta };
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
cols,
|
|
158
|
+
rows,
|
|
159
|
+
cellCount() {
|
|
160
|
+
return total;
|
|
161
|
+
},
|
|
162
|
+
colOf,
|
|
163
|
+
rowOf,
|
|
164
|
+
cellIndex,
|
|
165
|
+
ensureGroup(group, memory) {
|
|
166
|
+
const existing = groups.get(group);
|
|
167
|
+
if (existing === undefined) {
|
|
168
|
+
groups.set(group, makeGroup(memory ?? defaultMemory));
|
|
169
|
+
}
|
|
170
|
+
else if (memory !== undefined) {
|
|
171
|
+
existing.memory = memory;
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
hasGroup(group) {
|
|
175
|
+
return groups.has(group);
|
|
176
|
+
},
|
|
177
|
+
groups() {
|
|
178
|
+
return Array.from(groups.keys());
|
|
179
|
+
},
|
|
180
|
+
removeGroup(group) {
|
|
181
|
+
groups.delete(group);
|
|
182
|
+
},
|
|
183
|
+
cellsInRadius,
|
|
184
|
+
observe,
|
|
185
|
+
observeCircle(group, x, z, radius) {
|
|
186
|
+
return observe(group, cellsInRadius(x, z, radius));
|
|
187
|
+
},
|
|
188
|
+
stateAtCell(group, cell) {
|
|
189
|
+
const data = groups.get(group);
|
|
190
|
+
if (data === undefined || cell < 0 || cell >= total)
|
|
191
|
+
return "hidden";
|
|
192
|
+
return stateOf(data.codes[cell]);
|
|
193
|
+
},
|
|
194
|
+
stateAt(group, x, z) {
|
|
195
|
+
const data = groups.get(group);
|
|
196
|
+
if (data === undefined)
|
|
197
|
+
return "hidden";
|
|
198
|
+
return stateOf(data.codes[cellIndex(x, z)]);
|
|
199
|
+
},
|
|
200
|
+
isObserved(group, x, z) {
|
|
201
|
+
const data = groups.get(group);
|
|
202
|
+
return data !== undefined && data.codes[cellIndex(x, z)] === VISIBILITY_OBSERVED;
|
|
203
|
+
},
|
|
204
|
+
isRemembered(group, x, z) {
|
|
205
|
+
const data = groups.get(group);
|
|
206
|
+
return data !== undefined && data.codes[cellIndex(x, z)] === VISIBILITY_REMEMBERED;
|
|
207
|
+
},
|
|
208
|
+
isKnown(group, x, z) {
|
|
209
|
+
const data = groups.get(group);
|
|
210
|
+
return data !== undefined && data.codes[cellIndex(x, z)] !== VISIBILITY_HIDDEN;
|
|
211
|
+
},
|
|
212
|
+
observedCount(group) {
|
|
213
|
+
return groups.get(group)?.observed.size ?? 0;
|
|
214
|
+
},
|
|
215
|
+
knownCount(group) {
|
|
216
|
+
const data = groups.get(group);
|
|
217
|
+
if (data === undefined)
|
|
218
|
+
return 0;
|
|
219
|
+
return data.observed.size + data.remembered.size;
|
|
220
|
+
},
|
|
221
|
+
visibleTo(group, entities, positionOf) {
|
|
222
|
+
const data = groups.get(group);
|
|
223
|
+
if (data === undefined)
|
|
224
|
+
return [];
|
|
225
|
+
const result = [];
|
|
226
|
+
for (const entity of entities) {
|
|
227
|
+
const position = positionOf(entity);
|
|
228
|
+
if (data.codes[cellIndex(position.x, position.z)] === VISIBILITY_OBSERVED) {
|
|
229
|
+
result.push(entity);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
233
|
+
},
|
|
234
|
+
cells(group) {
|
|
235
|
+
const data = groups.get(group);
|
|
236
|
+
const codes = data === undefined ? new Uint8Array(total) : data.codes.slice();
|
|
237
|
+
return { cols, rows, minX, minZ, cellSize, codes };
|
|
238
|
+
},
|
|
239
|
+
toState() {
|
|
240
|
+
const out = {};
|
|
241
|
+
for (const [name, data] of groups) {
|
|
242
|
+
const remembered = Array.from(data.remembered.entries()).sort((a, b) => a[0] - b[0]);
|
|
243
|
+
out[name] = {
|
|
244
|
+
observed: Array.from(data.observed).sort((a, b) => a - b),
|
|
245
|
+
remembered,
|
|
246
|
+
tick: data.tick,
|
|
247
|
+
memory: data.memory,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
return { cols, rows, minX, minZ, cellSize, memory: defaultMemory, groups: out };
|
|
251
|
+
},
|
|
252
|
+
reset(group) {
|
|
253
|
+
if (group === undefined) {
|
|
254
|
+
for (const data of groups.values()) {
|
|
255
|
+
data.codes.fill(VISIBILITY_HIDDEN);
|
|
256
|
+
data.observed.clear();
|
|
257
|
+
data.remembered.clear();
|
|
258
|
+
data.tick = 0;
|
|
259
|
+
}
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const data = groups.get(group);
|
|
263
|
+
if (data === undefined)
|
|
264
|
+
return;
|
|
265
|
+
data.codes.fill(VISIBILITY_HIDDEN);
|
|
266
|
+
data.observed.clear();
|
|
267
|
+
data.remembered.clear();
|
|
268
|
+
data.tick = 0;
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
}
|