@jgengine/core 0.10.0 → 0.12.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 +39 -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/populationDirector.d.ts +103 -0
- package/dist/ai/populationDirector.js +190 -0
- package/dist/ai/pursuit.d.ts +56 -0
- package/dist/ai/pursuit.js +53 -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 +2 -1
- package/dist/authoring.js +2 -1
- 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 +35 -0
- package/dist/combat.js +35 -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/controls.d.ts +38 -0
- package/dist/devtools/controls.js +181 -0
- package/dist/devtools/devtools.d.ts +5 -197
- package/dist/devtools/devtools.js +38 -774
- package/dist/devtools/discover.d.ts +32 -0
- package/dist/devtools/discover.js +240 -0
- package/dist/devtools/fallbackSeams.d.ts +50 -0
- package/dist/devtools/fallbackSeams.js +111 -0
- package/dist/devtools/frame.d.ts +15 -0
- package/dist/devtools/frame.js +247 -0
- package/dist/devtools/logs.d.ts +15 -0
- package/dist/devtools/logs.js +86 -0
- package/dist/devtools/overrides.d.ts +16 -0
- package/dist/devtools/overrides.js +66 -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/devtools/types.d.ts +212 -0
- package/dist/devtools/types.js +1 -0
- package/dist/economy/auctionBook.d.ts +122 -0
- package/dist/economy/auctionBook.js +213 -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/priceHistory.d.ts +44 -0
- package/dist/economy/priceHistory.js +89 -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/unlockPoints.d.ts +92 -0
- package/dist/economy/unlockPoints.js +103 -0
- package/dist/economy/wallet.d.ts +26 -2
- package/dist/economy/wallet.js +35 -6
- package/dist/editor/commandApply.d.ts +5 -0
- package/dist/editor/commandApply.js +755 -0
- package/dist/editor/commands.d.ts +235 -7
- package/dist/editor/commands.js +82 -124
- package/dist/editor/directives.d.ts +94 -0
- package/dist/editor/directives.js +206 -0
- package/dist/editor/document.d.ts +194 -13
- package/dist/editor/document.js +1166 -19
- package/dist/editor/entityCatalog.d.ts +42 -0
- package/dist/editor/entityCatalog.js +101 -0
- package/dist/editor/environment.d.ts +74 -0
- package/dist/editor/environment.js +169 -0
- package/dist/editor/grid.d.ts +229 -0
- package/dist/editor/grid.js +366 -0
- package/dist/editor/gridAdapters.d.ts +80 -0
- package/dist/editor/gridAdapters.js +134 -0
- package/dist/editor/index.d.ts +98 -6
- package/dist/editor/index.js +13 -2
- package/dist/editor/liveSync.d.ts +127 -0
- package/dist/editor/liveSync.js +249 -0
- package/dist/editor/minimap.d.ts +31 -0
- package/dist/editor/minimap.js +73 -0
- package/dist/editor/runtimeInspector.d.ts +88 -0
- package/dist/editor/runtimeInspector.js +239 -0
- package/dist/editor/streamer.d.ts +66 -0
- package/dist/editor/streamer.js +68 -0
- package/dist/editor/types.d.ts +250 -1
- package/dist/editor/world.d.ts +136 -0
- package/dist/editor/world.js +303 -0
- package/dist/faction/reputation.d.ts +5 -0
- package/dist/faction/reputation.js +5 -0
- package/dist/format/distance.d.ts +17 -0
- package/dist/format/distance.js +18 -0
- package/dist/format/duration.d.ts +27 -0
- package/dist/format/duration.js +45 -0
- package/dist/format/speed.d.ts +17 -0
- package/dist/format/speed.js +25 -0
- package/dist/game/breeding.d.ts +161 -0
- package/dist/game/breeding.js +181 -0
- package/dist/game/cameraConfig.d.ts +451 -0
- package/dist/game/cameraConfig.js +1 -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 +110 -5
- package/dist/game/defineGame.js +49 -4
- package/dist/game/defineSystem.d.ts +90 -0
- package/dist/game/defineSystem.js +47 -0
- package/dist/game/dialogue.d.ts +33 -0
- package/dist/game/dialogue.js +21 -0
- package/dist/game/events.d.ts +63 -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 +116 -432
- package/dist/game/playableGame.js +1 -1
- package/dist/game/progression.d.ts +35 -0
- package/dist/game/progression.js +19 -0
- package/dist/game/quest.d.ts +8 -0
- package/dist/game/quest.js +30 -3
- 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/tribe.d.ts +184 -0
- package/dist/game/tribe.js +432 -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 +93 -0
- package/dist/gameplay.js +93 -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/encumbrance.d.ts +69 -0
- package/dist/inventory/encumbrance.js +68 -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 +6 -3
- 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 +39 -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 +50 -9
- package/dist/movement/movementModel.js +75 -29
- package/dist/movement/playerMovement.js +167 -12
- 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 +16 -8
- package/dist/multiplayer/lagCompensation.d.ts +5 -0
- package/dist/multiplayer/lagCompensation.js +5 -0
- package/dist/multiplayer/presenceModel.d.ts +11 -1
- package/dist/multiplayer/presenceModel.js +17 -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 +31 -0
- package/dist/physics/drivableVehicle.js +16 -0
- package/dist/physics/flightDynamics.d.ts +82 -0
- package/dist/physics/flightDynamics.js +165 -0
- package/dist/physics/gravityField.d.ts +25 -0
- package/dist/physics/gravityField.js +41 -0
- package/dist/physics/kinematicVehicle.d.ts +108 -1
- package/dist/physics/kinematicVehicle.js +212 -15
- package/dist/physics/physicsWorld.d.ts +50 -12
- package/dist/physics/physicsWorld.js +120 -122
- package/dist/physics/radialImpulse.d.ts +25 -0
- package/dist/physics/radialImpulse.js +27 -0
- package/dist/physics/vehicleObstacles.d.ts +44 -0
- package/dist/physics/vehicleObstacles.js +115 -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 +26 -1
- package/dist/random/rng.js +32 -9
- 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 +55 -3
- package/dist/runtime/adapter.js +57 -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/combat.d.ts +51 -0
- package/dist/runtime/context/combat.js +130 -0
- package/dist/runtime/context/combatFx.d.ts +23 -0
- package/dist/runtime/context/combatFx.js +161 -0
- package/dist/runtime/context/deathLoot.d.ts +30 -0
- package/dist/runtime/context/deathLoot.js +39 -0
- package/dist/runtime/context/player.d.ts +48 -0
- package/dist/runtime/context/player.js +125 -0
- package/dist/runtime/context/registries.d.ts +13 -0
- package/dist/runtime/context/registries.js +84 -0
- package/dist/runtime/context/scene.d.ts +59 -0
- package/dist/runtime/context/scene.js +291 -0
- package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
- package/dist/runtime/context/snapshotCodecs.js +26 -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 +157 -0
- package/dist/runtime/descriptors/features.d.ts +79 -0
- package/dist/runtime/descriptors/features.js +299 -0
- package/dist/runtime/gameContext.d.ts +2 -327
- package/dist/runtime/gameContext.js +273 -778
- package/dist/runtime/gameContextTypes.d.ts +467 -0
- package/dist/runtime/gameContextTypes.js +1 -0
- package/dist/runtime/gameRuntime.d.ts +1 -0
- package/dist/runtime/gameRuntime.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +62 -0
- package/dist/runtime/headlessRunner.js +45 -0
- package/dist/runtime/hostPersistence.d.ts +12 -0
- package/dist/runtime/hostPersistence.js +12 -0
- package/dist/runtime/hostPolicy.d.ts +51 -0
- package/dist/runtime/hostPolicy.js +68 -0
- package/dist/runtime/hostedGameRunner.d.ts +11 -4
- package/dist/runtime/hostedGameRunner.js +27 -3
- package/dist/runtime/hostedWorldSession.d.ts +15 -5
- package/dist/runtime/hostedWorldSession.js +12 -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 +42 -3
- package/dist/runtime/worldSnapshot.js +34 -7
- package/dist/scene/assetCatalog.d.ts +26 -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 +257 -0
- package/dist/scene/authoredTriggers.d.ts +219 -0
- package/dist/scene/authoredTriggers.js +454 -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 +67 -0
- package/dist/scene/colliders.d.ts +71 -1
- package/dist/scene/colliders.js +145 -1
- package/dist/scene/collisionMesh.d.ts +94 -0
- package/dist/scene/collisionMesh.js +699 -0
- package/dist/scene/companion.d.ts +147 -0
- package/dist/scene/companion.js +193 -0
- package/dist/scene/entityStats.d.ts +18 -11
- package/dist/scene/entityStats.js +21 -16
- 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 +256 -0
- package/dist/scene/sceneKinds.js +218 -0
- package/dist/scene/sceneOwnership.d.ts +169 -0
- package/dist/scene/sceneOwnership.js +179 -0
- package/dist/scene/sceneRaycast.js +15 -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/spawnLevelStats.d.ts +110 -0
- package/dist/stats/spawnLevelStats.js +140 -0
- package/dist/stats/statModifiers.d.ts +5 -0
- package/dist/stats/statModifiers.js +5 -0
- package/dist/stats/statPool.d.ts +70 -0
- package/dist/stats/statPool.js +59 -0
- package/dist/store/changeSignal.d.ts +3 -0
- package/dist/store/changeSignal.js +2 -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 +7 -0
- package/dist/store/observableKeyedStore.js +35 -2
- package/dist/survival/decayMeter.d.ts +55 -0
- package/dist/survival/decayMeter.js +130 -57
- package/dist/survival/moodle.d.ts +2 -0
- package/dist/survival/regionHealth.d.ts +6 -0
- package/dist/survival/regionHealth.js +6 -3
- 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 +38 -1
- package/dist/ui/hudLayout.js +220 -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/authoredEntities.d.ts +29 -0
- package/dist/world/authoredEntities.js +29 -0
- package/dist/world/authoredObjects.d.ts +72 -0
- package/dist/world/authoredObjects.js +81 -0
- package/dist/world/authoredSpawn.d.ts +39 -0
- package/dist/world/authoredSpawn.js +37 -0
- package/dist/world/buildSockets.d.ts +152 -0
- package/dist/world/buildSockets.js +188 -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/cityBlocks.d.ts +152 -0
- package/dist/world/cityBlocks.js +670 -0
- package/dist/world/cityContent.d.ts +77 -0
- package/dist/world/cityContent.js +261 -0
- package/dist/world/cityGeometry.d.ts +114 -0
- package/dist/world/cityGeometry.js +573 -0
- package/dist/world/cityKind.d.ts +314 -0
- package/dist/world/cityKind.js +1578 -0
- package/dist/world/features.d.ts +133 -10
- package/dist/world/features.js +66 -6
- 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/markers.d.ts +50 -4
- package/dist/world/markers.js +49 -0
- package/dist/world/massing.js +1 -1
- package/dist/world/minimapBake.d.ts +78 -0
- package/dist/world/minimapBake.js +208 -0
- package/dist/world/minimapTrack.d.ts +17 -0
- package/dist/world/minimapTrack.js +22 -0
- package/dist/world/pathInstances.d.ts +27 -0
- package/dist/world/pathInstances.js +27 -0
- package/dist/world/pathNetwork.d.ts +159 -0
- package/dist/world/pathNetwork.js +684 -0
- package/dist/world/pathTerrain.d.ts +80 -0
- package/dist/world/pathTerrain.js +142 -0
- package/dist/world/place.d.ts +166 -0
- package/dist/world/place.js +96 -0
- package/dist/world/placeAsset.d.ts +81 -0
- package/dist/world/placeAsset.js +79 -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/poleLineKind.d.ts +40 -0
- package/dist/world/poleLineKind.js +97 -0
- package/dist/world/polyline.d.ts +34 -0
- package/dist/world/polyline.js +88 -0
- package/dist/world/resourceNode.d.ts +109 -0
- package/dist/world/resourceNode.js +140 -0
- package/dist/world/roads.d.ts +8 -0
- package/dist/world/roads.js +38 -0
- package/dist/world/scatter.js +2 -20
- package/dist/world/scatterRegion.d.ts +164 -0
- package/dist/world/scatterRegion.js +409 -0
- package/dist/world/sceneShapes.d.ts +43 -0
- package/dist/world/sceneShapes.js +1 -0
- package/dist/world/segment.d.ts +27 -0
- package/dist/world/segment.js +43 -0
- package/dist/world/soilKind.d.ts +48 -0
- package/dist/world/soilKind.js +92 -0
- package/dist/world/spatialSample.d.ts +241 -0
- package/dist/world/spatialSample.js +465 -0
- package/dist/world/streets.d.ts +29 -0
- package/dist/world/streets.js +55 -0
- package/dist/world/terraform.d.ts +213 -1
- package/dist/world/terraform.js +627 -22
- package/dist/world/terrain.d.ts +164 -20
- package/dist/world/terrain.js +325 -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 +141 -0
- package/dist/world.js +141 -0
- package/package.json +32 -8
- package/skills/game-design/SKILL.md +28 -0
- package/skills/game-design/agents/openai.yaml +4 -0
- package/skills/game-design/references/application-playbook.md +170 -0
- package/skills/game-design/references/field-guide.md +288 -0
- package/skills/jgengine/SKILL.md +54 -0
- package/skills/jgengine/api.md +527 -0
- package/skills/jgengine/capabilities.md +131 -0
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-combat/SKILL.md +38 -0
- package/skills/jgengine-combat/api.md +585 -0
- package/skills/jgengine-combat/capabilities.md +213 -0
- package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
- package/skills/jgengine-combat/reference.md +108 -0
- package/skills/jgengine-gameplay/SKILL.md +39 -0
- package/skills/jgengine-gameplay/api.md +1920 -0
- package/skills/jgengine-gameplay/capabilities.md +454 -0
- package/skills/jgengine-gameplay/reference-systems.md +56 -0
- package/skills/jgengine-world/SKILL.md +51 -0
- package/skills/jgengine-world/api.md +3056 -0
- package/skills/jgengine-world/capabilities.md +476 -0
- package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
- package/skills/jgengine-world/reference.md +261 -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,432 @@
|
|
|
1
|
+
const DEFAULT_LOG_CAP = 128;
|
|
2
|
+
function assetKey(kind, id) {
|
|
3
|
+
// Length-prefix the kind so the key is collision-free even when `kind` or `id`
|
|
4
|
+
// contains the delimiter (e.g. kind "ab"+id "c" must not collide with "a"+"bc").
|
|
5
|
+
return `${kind.length}:${kind}:${id}`;
|
|
6
|
+
}
|
|
7
|
+
function toRankRuntime(def) {
|
|
8
|
+
return {
|
|
9
|
+
id: def.id,
|
|
10
|
+
name: def.name,
|
|
11
|
+
level: def.level,
|
|
12
|
+
permissions: new Set(def.permissions ?? []),
|
|
13
|
+
bypass: def.bypass === true,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function rankToDef(rank) {
|
|
17
|
+
return {
|
|
18
|
+
id: rank.id,
|
|
19
|
+
name: rank.name,
|
|
20
|
+
level: rank.level,
|
|
21
|
+
...(rank.permissions.size > 0 ? { permissions: [...rank.permissions] } : {}),
|
|
22
|
+
...(rank.bypass ? { bypass: true } : {}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create a shared-ownership group aggregate (tribe / guild / clan / company). Members hold a
|
|
27
|
+
* {@link TribeRankDef rank} whose configurable permission slugs gate management actions and access
|
|
28
|
+
* to group-owned assets, while personally-owned assets stay with their member — and follow them out
|
|
29
|
+
* when they leave. Group↔group {@link Tribe.addAlly alliances} resolve allied tribes as friendly, and
|
|
30
|
+
* every membership / ownership / alliance change lands in a bounded ring-buffer {@link Tribe.events log}.
|
|
31
|
+
* All state is plain JSON via {@link Tribe.snapshot}/{@link Tribe.hydrate}; timestamps come from an
|
|
32
|
+
* injected clock for determinism. Compose many tribes with {@link createTribeRegistry} for mutual
|
|
33
|
+
* alliances and cross-member relation lookups.
|
|
34
|
+
*
|
|
35
|
+
* @capability tribe-group shared-ownership group (tribe/guild/clan) with ranked permissions, group vs personal assets, alliances, and a bounded event log
|
|
36
|
+
*/
|
|
37
|
+
export function createTribe(config) {
|
|
38
|
+
const now = config.now ?? Date.now;
|
|
39
|
+
if (config.ranks.length === 0)
|
|
40
|
+
throw new Error("tribe requires at least one rank");
|
|
41
|
+
const ranks = new Map();
|
|
42
|
+
let lowest;
|
|
43
|
+
let highest;
|
|
44
|
+
for (const def of config.ranks) {
|
|
45
|
+
if (ranks.has(def.id))
|
|
46
|
+
throw new Error(`duplicate rank id "${def.id}"`);
|
|
47
|
+
const rank = toRankRuntime(def);
|
|
48
|
+
ranks.set(rank.id, rank);
|
|
49
|
+
if (lowest === undefined || rank.level < lowest.level)
|
|
50
|
+
lowest = rank;
|
|
51
|
+
if (highest === undefined || rank.level > highest.level)
|
|
52
|
+
highest = rank;
|
|
53
|
+
}
|
|
54
|
+
const resolveRankId = (id, fallback) => {
|
|
55
|
+
if (id === undefined)
|
|
56
|
+
return fallback.id;
|
|
57
|
+
if (!ranks.has(id))
|
|
58
|
+
throw new Error(`unknown rank id "${id}"`);
|
|
59
|
+
return id;
|
|
60
|
+
};
|
|
61
|
+
let defaultRankId = resolveRankId(config.defaultRankId, lowest);
|
|
62
|
+
let founderRankId = resolveRankId(config.founderRankId, highest);
|
|
63
|
+
let logCap = Math.max(1, Math.floor(config.logCap ?? DEFAULT_LOG_CAP));
|
|
64
|
+
let founderId = config.founderId;
|
|
65
|
+
const members = new Map();
|
|
66
|
+
const assets = new Map();
|
|
67
|
+
const allies = new Set();
|
|
68
|
+
const eventLog = [];
|
|
69
|
+
let eventSeq = 0;
|
|
70
|
+
members.set(founderId, { id: founderId, rankId: founderRankId, joinedAt: now() });
|
|
71
|
+
function rankRuntimeOf(memberId) {
|
|
72
|
+
const member = members.get(memberId);
|
|
73
|
+
if (member === undefined)
|
|
74
|
+
return null;
|
|
75
|
+
return ranks.get(member.rankId) ?? null;
|
|
76
|
+
}
|
|
77
|
+
function isAdmin(memberId) {
|
|
78
|
+
if (memberId === founderId && members.has(memberId))
|
|
79
|
+
return true;
|
|
80
|
+
return rankRuntimeOf(memberId)?.bypass ?? false;
|
|
81
|
+
}
|
|
82
|
+
function can(memberId, permission) {
|
|
83
|
+
if (!members.has(memberId))
|
|
84
|
+
return false;
|
|
85
|
+
if (isAdmin(memberId))
|
|
86
|
+
return true;
|
|
87
|
+
return rankRuntimeOf(memberId)?.permissions.has(permission) ?? false;
|
|
88
|
+
}
|
|
89
|
+
function levelOf(memberId) {
|
|
90
|
+
if (isAdmin(memberId))
|
|
91
|
+
return Number.POSITIVE_INFINITY;
|
|
92
|
+
return rankRuntimeOf(memberId)?.level ?? Number.NEGATIVE_INFINITY;
|
|
93
|
+
}
|
|
94
|
+
function log(type, fields) {
|
|
95
|
+
eventSeq += 1;
|
|
96
|
+
const event = {
|
|
97
|
+
seq: eventSeq,
|
|
98
|
+
type,
|
|
99
|
+
at: now(),
|
|
100
|
+
...(fields.actor === undefined ? {} : { actor: fields.actor }),
|
|
101
|
+
...(fields.subject === undefined ? {} : { subject: fields.subject }),
|
|
102
|
+
...(fields.tribeId === undefined ? {} : { tribeId: fields.tribeId }),
|
|
103
|
+
...(fields.rankId === undefined ? {} : { rankId: fields.rankId }),
|
|
104
|
+
...(fields.assetKind === undefined ? {} : { assetKind: fields.assetKind }),
|
|
105
|
+
...(fields.assetId === undefined ? {} : { assetId: fields.assetId }),
|
|
106
|
+
};
|
|
107
|
+
eventLog.push(event);
|
|
108
|
+
if (eventLog.length > logCap)
|
|
109
|
+
eventLog.shift();
|
|
110
|
+
}
|
|
111
|
+
function dropPersonalAssets(memberId) {
|
|
112
|
+
for (const [key, asset] of assets) {
|
|
113
|
+
if (asset.ownerId === memberId)
|
|
114
|
+
assets.delete(key);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
id: config.id,
|
|
119
|
+
founderId: () => founderId,
|
|
120
|
+
hasMember: (memberId) => members.has(memberId),
|
|
121
|
+
memberIds: () => [...members.keys()],
|
|
122
|
+
rankOf(memberId) {
|
|
123
|
+
const rank = rankRuntimeOf(memberId);
|
|
124
|
+
return rank === null ? null : rankToDef(rank);
|
|
125
|
+
},
|
|
126
|
+
can,
|
|
127
|
+
isAdmin,
|
|
128
|
+
addMember(actorId, memberId, rankId) {
|
|
129
|
+
if (!members.has(actorId))
|
|
130
|
+
return { reason: "actor is not a member" };
|
|
131
|
+
if (!can(actorId, "invite"))
|
|
132
|
+
return { reason: "missing invite permission" };
|
|
133
|
+
if (members.has(memberId))
|
|
134
|
+
return { reason: "already a member" };
|
|
135
|
+
const targetRankId = rankId ?? defaultRankId;
|
|
136
|
+
const targetRank = ranks.get(targetRankId);
|
|
137
|
+
if (targetRank === undefined)
|
|
138
|
+
return { reason: `unknown rank id "${targetRankId}"` };
|
|
139
|
+
if (!isAdmin(actorId) && targetRank.level >= levelOf(actorId)) {
|
|
140
|
+
return { reason: "cannot invite at or above your own rank" };
|
|
141
|
+
}
|
|
142
|
+
members.set(memberId, { id: memberId, rankId: targetRankId, joinedAt: now() });
|
|
143
|
+
log("member-added", { actor: actorId, subject: memberId, rankId: targetRankId });
|
|
144
|
+
return null;
|
|
145
|
+
},
|
|
146
|
+
removeMember(actorId, memberId) {
|
|
147
|
+
if (!members.has(actorId))
|
|
148
|
+
return { reason: "actor is not a member" };
|
|
149
|
+
if (actorId === memberId)
|
|
150
|
+
return { reason: "use leave to remove yourself" };
|
|
151
|
+
if (!members.has(memberId))
|
|
152
|
+
return { reason: "not a member" };
|
|
153
|
+
if (memberId === founderId)
|
|
154
|
+
return { reason: "cannot remove the founder" };
|
|
155
|
+
if (!can(actorId, "kick"))
|
|
156
|
+
return { reason: "missing kick permission" };
|
|
157
|
+
if (levelOf(actorId) <= levelOf(memberId))
|
|
158
|
+
return { reason: "cannot manage an equal or higher rank" };
|
|
159
|
+
members.delete(memberId);
|
|
160
|
+
dropPersonalAssets(memberId);
|
|
161
|
+
log("member-removed", { actor: actorId, subject: memberId });
|
|
162
|
+
return null;
|
|
163
|
+
},
|
|
164
|
+
leave(memberId) {
|
|
165
|
+
if (!members.has(memberId))
|
|
166
|
+
return { reason: "not a member" };
|
|
167
|
+
if (memberId === founderId)
|
|
168
|
+
return { reason: "founder must transfer leadership first" };
|
|
169
|
+
members.delete(memberId);
|
|
170
|
+
dropPersonalAssets(memberId);
|
|
171
|
+
log("member-left", { subject: memberId });
|
|
172
|
+
return null;
|
|
173
|
+
},
|
|
174
|
+
setMemberRank(actorId, memberId, rankId) {
|
|
175
|
+
if (!members.has(actorId))
|
|
176
|
+
return { reason: "actor is not a member" };
|
|
177
|
+
if (!members.has(memberId))
|
|
178
|
+
return { reason: "not a member" };
|
|
179
|
+
if (memberId === founderId)
|
|
180
|
+
return { reason: "cannot re-rank the founder" };
|
|
181
|
+
if (!can(actorId, "manage-ranks"))
|
|
182
|
+
return { reason: "missing manage-ranks permission" };
|
|
183
|
+
const nextRank = ranks.get(rankId);
|
|
184
|
+
if (nextRank === undefined)
|
|
185
|
+
return { reason: `unknown rank id "${rankId}"` };
|
|
186
|
+
if (!isAdmin(actorId)) {
|
|
187
|
+
if (levelOf(actorId) <= levelOf(memberId))
|
|
188
|
+
return { reason: "cannot manage an equal or higher rank" };
|
|
189
|
+
if (nextRank.level >= levelOf(actorId))
|
|
190
|
+
return { reason: "cannot assign a rank at or above your own" };
|
|
191
|
+
}
|
|
192
|
+
members.get(memberId).rankId = rankId;
|
|
193
|
+
log("rank-changed", { actor: actorId, subject: memberId, rankId });
|
|
194
|
+
return null;
|
|
195
|
+
},
|
|
196
|
+
transferFounder(actorId, memberId) {
|
|
197
|
+
if (actorId !== founderId)
|
|
198
|
+
return { reason: "only the founder can transfer leadership" };
|
|
199
|
+
if (!members.has(memberId))
|
|
200
|
+
return { reason: "not a member" };
|
|
201
|
+
if (memberId === founderId)
|
|
202
|
+
return { reason: "already the founder" };
|
|
203
|
+
members.get(memberId).rankId = founderRankId;
|
|
204
|
+
founderId = memberId;
|
|
205
|
+
log("founder-transferred", { actor: actorId, subject: memberId });
|
|
206
|
+
return null;
|
|
207
|
+
},
|
|
208
|
+
registerAsset(actorId, ref, ownership) {
|
|
209
|
+
if (!members.has(actorId))
|
|
210
|
+
return { reason: "actor is not a member" };
|
|
211
|
+
const key = assetKey(ref.kind, ref.id);
|
|
212
|
+
if (assets.has(key))
|
|
213
|
+
return { reason: "asset already registered" };
|
|
214
|
+
let ownerId;
|
|
215
|
+
if (ownership.scope === "group") {
|
|
216
|
+
if (!can(actorId, "build"))
|
|
217
|
+
return { reason: "missing build permission" };
|
|
218
|
+
ownerId = null;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
if (!members.has(ownership.memberId))
|
|
222
|
+
return { reason: "owner is not a member" };
|
|
223
|
+
if (ownership.memberId !== actorId && !isAdmin(actorId)) {
|
|
224
|
+
return { reason: "cannot register assets for another member" };
|
|
225
|
+
}
|
|
226
|
+
ownerId = ownership.memberId;
|
|
227
|
+
}
|
|
228
|
+
assets.set(key, { kind: ref.kind, id: ref.id, ownerId });
|
|
229
|
+
log("asset-registered", { actor: actorId, assetKind: ref.kind, assetId: ref.id });
|
|
230
|
+
return null;
|
|
231
|
+
},
|
|
232
|
+
unregisterAsset(actorId, ref) {
|
|
233
|
+
if (!members.has(actorId))
|
|
234
|
+
return { reason: "actor is not a member" };
|
|
235
|
+
const key = assetKey(ref.kind, ref.id);
|
|
236
|
+
const asset = assets.get(key);
|
|
237
|
+
if (asset === undefined)
|
|
238
|
+
return { reason: "unknown asset" };
|
|
239
|
+
if (asset.ownerId === null) {
|
|
240
|
+
if (!can(actorId, "demolish"))
|
|
241
|
+
return { reason: "missing demolish permission" };
|
|
242
|
+
}
|
|
243
|
+
else if (asset.ownerId !== actorId && !isAdmin(actorId)) {
|
|
244
|
+
return { reason: "not the asset owner" };
|
|
245
|
+
}
|
|
246
|
+
assets.delete(key);
|
|
247
|
+
log("asset-unregistered", { actor: actorId, assetKind: ref.kind, assetId: ref.id });
|
|
248
|
+
return null;
|
|
249
|
+
},
|
|
250
|
+
ownerOfAsset(ref) {
|
|
251
|
+
const asset = assets.get(assetKey(ref.kind, ref.id));
|
|
252
|
+
if (asset === undefined)
|
|
253
|
+
return null;
|
|
254
|
+
return asset.ownerId === null ? { scope: "group" } : { scope: "personal", memberId: asset.ownerId };
|
|
255
|
+
},
|
|
256
|
+
assetsOf(memberId) {
|
|
257
|
+
const out = [];
|
|
258
|
+
for (const asset of assets.values()) {
|
|
259
|
+
if (asset.ownerId === memberId)
|
|
260
|
+
out.push({ kind: asset.kind, id: asset.id });
|
|
261
|
+
}
|
|
262
|
+
return out;
|
|
263
|
+
},
|
|
264
|
+
canAccess(memberId, ref, action) {
|
|
265
|
+
if (!members.has(memberId))
|
|
266
|
+
return false;
|
|
267
|
+
if (isAdmin(memberId))
|
|
268
|
+
return true;
|
|
269
|
+
const asset = assets.get(assetKey(ref.kind, ref.id));
|
|
270
|
+
if (asset === undefined)
|
|
271
|
+
return false;
|
|
272
|
+
if (asset.ownerId !== null)
|
|
273
|
+
return asset.ownerId === memberId;
|
|
274
|
+
return can(memberId, action);
|
|
275
|
+
},
|
|
276
|
+
addAlly(tribeId) {
|
|
277
|
+
if (tribeId === config.id || allies.has(tribeId))
|
|
278
|
+
return;
|
|
279
|
+
allies.add(tribeId);
|
|
280
|
+
log("alliance-formed", { tribeId });
|
|
281
|
+
},
|
|
282
|
+
removeAlly(tribeId) {
|
|
283
|
+
if (!allies.delete(tribeId))
|
|
284
|
+
return;
|
|
285
|
+
log("alliance-broken", { tribeId });
|
|
286
|
+
},
|
|
287
|
+
isAllied: (tribeId) => allies.has(tribeId),
|
|
288
|
+
allyIds: () => [...allies],
|
|
289
|
+
relationTo(tribeId) {
|
|
290
|
+
if (tribeId === config.id || allies.has(tribeId))
|
|
291
|
+
return "friendly";
|
|
292
|
+
return "neutral";
|
|
293
|
+
},
|
|
294
|
+
events: () => eventLog.slice(),
|
|
295
|
+
snapshot() {
|
|
296
|
+
return {
|
|
297
|
+
id: config.id,
|
|
298
|
+
founderId,
|
|
299
|
+
ranks: [...ranks.values()].map(rankToDef),
|
|
300
|
+
defaultRankId,
|
|
301
|
+
founderRankId,
|
|
302
|
+
logCap,
|
|
303
|
+
members: [...members.values()].map((m) => ({ ...m })),
|
|
304
|
+
assets: [...assets.values()].map((a) => ({ kind: a.kind, id: a.id, ownerId: a.ownerId })),
|
|
305
|
+
allies: [...allies],
|
|
306
|
+
events: eventLog.map((e) => ({ ...e })),
|
|
307
|
+
eventSeq,
|
|
308
|
+
};
|
|
309
|
+
},
|
|
310
|
+
hydrate(snapshot) {
|
|
311
|
+
ranks.clear();
|
|
312
|
+
for (const def of snapshot.ranks)
|
|
313
|
+
ranks.set(def.id, toRankRuntime(def));
|
|
314
|
+
defaultRankId = snapshot.defaultRankId;
|
|
315
|
+
founderRankId = snapshot.founderRankId;
|
|
316
|
+
logCap = Math.max(1, Math.floor(snapshot.logCap));
|
|
317
|
+
founderId = snapshot.founderId;
|
|
318
|
+
members.clear();
|
|
319
|
+
for (const m of snapshot.members)
|
|
320
|
+
members.set(m.id, { ...m });
|
|
321
|
+
assets.clear();
|
|
322
|
+
for (const a of snapshot.assets)
|
|
323
|
+
assets.set(assetKey(a.kind, a.id), { kind: a.kind, id: a.id, ownerId: a.ownerId });
|
|
324
|
+
allies.clear();
|
|
325
|
+
for (const t of snapshot.allies)
|
|
326
|
+
allies.add(t);
|
|
327
|
+
eventLog.length = 0;
|
|
328
|
+
for (const e of snapshot.events)
|
|
329
|
+
eventLog.push({ ...e });
|
|
330
|
+
eventSeq = snapshot.eventSeq;
|
|
331
|
+
},
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Create a registry that owns many tribes, keeps alliances mutual, and resolves member relations.
|
|
336
|
+
*
|
|
337
|
+
* @capability tribe-registry registry of tribes with mutual alliances and cross-tribe relation lookup
|
|
338
|
+
*/
|
|
339
|
+
export function createTribeRegistry(deps = {}) {
|
|
340
|
+
const tribes = new Map();
|
|
341
|
+
const build = (config) => {
|
|
342
|
+
const merged = {
|
|
343
|
+
...config,
|
|
344
|
+
...(config.now === undefined && deps.now !== undefined ? { now: deps.now } : {}),
|
|
345
|
+
...(config.logCap === undefined && deps.defaultLogCap !== undefined ? { logCap: deps.defaultLogCap } : {}),
|
|
346
|
+
};
|
|
347
|
+
return createTribe(merged);
|
|
348
|
+
};
|
|
349
|
+
function relationBetweenTribes(tribeA, tribeB) {
|
|
350
|
+
if (tribeA === tribeB)
|
|
351
|
+
return "friendly";
|
|
352
|
+
const a = tribes.get(tribeA);
|
|
353
|
+
if (a === undefined || !tribes.has(tribeB))
|
|
354
|
+
return "neutral";
|
|
355
|
+
return a.isAllied(tribeB) ? "friendly" : "neutral";
|
|
356
|
+
}
|
|
357
|
+
function tribeOfMember(memberId) {
|
|
358
|
+
for (const tribe of tribes.values()) {
|
|
359
|
+
if (tribe.hasMember(memberId))
|
|
360
|
+
return tribe;
|
|
361
|
+
}
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
function relationBetweenMembers(memberA, memberB) {
|
|
365
|
+
const a = tribeOfMember(memberA);
|
|
366
|
+
const b = tribeOfMember(memberB);
|
|
367
|
+
if (a === null || b === null)
|
|
368
|
+
return "neutral";
|
|
369
|
+
if (a.id === b.id)
|
|
370
|
+
return "friendly";
|
|
371
|
+
return relationBetweenTribes(a.id, b.id);
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
create(config) {
|
|
375
|
+
if (tribes.has(config.id))
|
|
376
|
+
throw new Error(`duplicate tribe id "${config.id}"`);
|
|
377
|
+
const tribe = build(config);
|
|
378
|
+
tribes.set(config.id, tribe);
|
|
379
|
+
return tribe;
|
|
380
|
+
},
|
|
381
|
+
get: (id) => tribes.get(id) ?? null,
|
|
382
|
+
all: () => [...tribes.values()],
|
|
383
|
+
remove(id) {
|
|
384
|
+
if (!tribes.delete(id))
|
|
385
|
+
return;
|
|
386
|
+
for (const tribe of tribes.values())
|
|
387
|
+
tribe.removeAlly(id);
|
|
388
|
+
},
|
|
389
|
+
formAlliance(tribeA, tribeB) {
|
|
390
|
+
if (tribeA === tribeB)
|
|
391
|
+
return { reason: "a tribe cannot ally with itself" };
|
|
392
|
+
const a = tribes.get(tribeA);
|
|
393
|
+
const b = tribes.get(tribeB);
|
|
394
|
+
if (a === undefined || b === undefined)
|
|
395
|
+
return { reason: "unknown tribe" };
|
|
396
|
+
a.addAlly(tribeB);
|
|
397
|
+
b.addAlly(tribeA);
|
|
398
|
+
return null;
|
|
399
|
+
},
|
|
400
|
+
breakAlliance(tribeA, tribeB) {
|
|
401
|
+
tribes.get(tribeA)?.removeAlly(tribeB);
|
|
402
|
+
tribes.get(tribeB)?.removeAlly(tribeA);
|
|
403
|
+
},
|
|
404
|
+
areAllied(tribeA, tribeB) {
|
|
405
|
+
const a = tribes.get(tribeA);
|
|
406
|
+
const b = tribes.get(tribeB);
|
|
407
|
+
return a !== undefined && b !== undefined && a.isAllied(tribeB) && b.isAllied(tribeA);
|
|
408
|
+
},
|
|
409
|
+
relationBetweenTribes,
|
|
410
|
+
tribeOfMember,
|
|
411
|
+
relationBetweenMembers,
|
|
412
|
+
isFriendly: (memberA, memberB) => relationBetweenMembers(memberA, memberB) === "friendly",
|
|
413
|
+
snapshot: () => ({ tribes: [...tribes.values()].map((tribe) => tribe.snapshot()) }),
|
|
414
|
+
hydrate(snapshot) {
|
|
415
|
+
tribes.clear();
|
|
416
|
+
for (const tribeSnap of snapshot.tribes) {
|
|
417
|
+
const config = {
|
|
418
|
+
id: tribeSnap.id,
|
|
419
|
+
founderId: tribeSnap.founderId,
|
|
420
|
+
ranks: tribeSnap.ranks,
|
|
421
|
+
defaultRankId: tribeSnap.defaultRankId,
|
|
422
|
+
founderRankId: tribeSnap.founderRankId,
|
|
423
|
+
logCap: tribeSnap.logCap,
|
|
424
|
+
...(deps.now === undefined ? {} : { now: deps.now }),
|
|
425
|
+
};
|
|
426
|
+
const tribe = createTribe(config);
|
|
427
|
+
tribe.hydrate(tribeSnap);
|
|
428
|
+
tribes.set(tribe.id, tribe);
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
};
|
|
432
|
+
}
|
package/dist/game/unlocks.d.ts
CHANGED
|
@@ -10,6 +10,11 @@ export interface UnlockCatalog {
|
|
|
10
10
|
has(unlockId: string): boolean;
|
|
11
11
|
tree(categoryId: string): UnlockDef[];
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* A catalog of unlockable content gated behind conditions the player earns, tracking what is unlocked.
|
|
15
|
+
*
|
|
16
|
+
* @capability unlockables gate content behind unlock conditions the player earns
|
|
17
|
+
*/
|
|
13
18
|
export declare function createUnlockCatalog(defs?: readonly UnlockDef[]): UnlockCatalog;
|
|
14
19
|
export interface Unlocks {
|
|
15
20
|
has(userId: string, unlockId: string): boolean;
|
|
@@ -18,5 +23,8 @@ export interface Unlocks {
|
|
|
18
23
|
tree(categoryId: string): UnlockDef[];
|
|
19
24
|
snapshot(userId: string): string[];
|
|
20
25
|
hydrate(userId: string, ids: string[]): void;
|
|
26
|
+
/** Whole-store capture across every user — the world-save/replication seam (per-user `snapshot` can't enumerate users). */
|
|
27
|
+
snapshotAll(): Record<string, string[]>;
|
|
28
|
+
hydrateAll(data: Record<string, string[]>): void;
|
|
21
29
|
}
|
|
22
30
|
export declare function createUnlocks(defs?: UnlockDef[]): Unlocks;
|
package/dist/game/unlocks.js
CHANGED
|
@@ -7,6 +7,11 @@ export function grantUnlock(granted, unlockId) {
|
|
|
7
7
|
export function unlockTree(defs, categoryId) {
|
|
8
8
|
return defs.filter((def) => def.category === categoryId);
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* A catalog of unlockable content gated behind conditions the player earns, tracking what is unlocked.
|
|
12
|
+
*
|
|
13
|
+
* @capability unlockables gate content behind unlock conditions the player earns
|
|
14
|
+
*/
|
|
10
15
|
export function createUnlockCatalog(defs = []) {
|
|
11
16
|
const byId = new Map();
|
|
12
17
|
for (const def of defs)
|
|
@@ -48,5 +53,16 @@ export function createUnlocks(defs = []) {
|
|
|
48
53
|
hydrate(userId, ids) {
|
|
49
54
|
granted.set(userId, new Set(ids));
|
|
50
55
|
},
|
|
56
|
+
snapshotAll() {
|
|
57
|
+
const out = {};
|
|
58
|
+
for (const [userId, ids] of granted)
|
|
59
|
+
out[userId] = Array.from(ids);
|
|
60
|
+
return out;
|
|
61
|
+
},
|
|
62
|
+
hydrateAll(data) {
|
|
63
|
+
granted.clear();
|
|
64
|
+
for (const [userId, ids] of Object.entries(data))
|
|
65
|
+
granted.set(userId, new Set(ids));
|
|
66
|
+
},
|
|
51
67
|
};
|
|
52
68
|
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { RetainedVfxKind, VfxRef } from "./events.js";
|
|
2
|
+
/**
|
|
3
|
+
* The serializable specification for creating (or replacing) a retained VFX instance. Unlike a one-shot
|
|
4
|
+
* `combat.vfx` burst this describes a long-lived effect whose endpoints and parameters are updated over
|
|
5
|
+
* time. `id` is caller-stable so repeated `upsert` calls address the same effect; omit it to mint one.
|
|
6
|
+
* `from`/`to` are {@link VfxRef}s (an entity instance id or a world point) that a renderer resolves each
|
|
7
|
+
* frame, so an endpoint bound to a moving entity follows it without any per-frame command traffic.
|
|
8
|
+
*/
|
|
9
|
+
export interface VfxInstanceSpec {
|
|
10
|
+
/** Caller-stable handle. Repeated `upsert` with the same id replaces the instance; omitted mints a fresh id. */
|
|
11
|
+
id?: string;
|
|
12
|
+
/** Open effect archetype (e.g. `"beam"`). Renderers register kinds, so new visuals need no central branch. */
|
|
13
|
+
kind: RetainedVfxKind;
|
|
14
|
+
/** `0xRRGGBB` tint. */
|
|
15
|
+
color: number;
|
|
16
|
+
/** Origin endpoint: an entity instance id (followed live) or a fixed world point. */
|
|
17
|
+
from?: VfxRef;
|
|
18
|
+
/** Target endpoint: an entity instance id (followed live) or a fixed world point. */
|
|
19
|
+
to?: VfxRef;
|
|
20
|
+
/** Effect radius/thickness in world units, interpreted per kind. */
|
|
21
|
+
radius?: number;
|
|
22
|
+
/** Extra numeric knobs a renderer reads by name (intensity, spin, width, ...), kept a flat serializable bag. */
|
|
23
|
+
params?: Readonly<Record<string, number>>;
|
|
24
|
+
/** Optional time-to-live in ms: the instance auto-stops if `tick` runs past `ttlMs` since its last touch (heartbeat). */
|
|
25
|
+
ttlMs?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The stored, fully-resolved form of a retained VFX instance. It is a plain serializable record so hosts can
|
|
29
|
+
* replicate it and debug tooling can inspect it; renderers receive it verbatim and never merge partial state
|
|
30
|
+
* themselves. `updatedAtMs` is the last create/update time and drives TTL heartbeat eviction.
|
|
31
|
+
*/
|
|
32
|
+
export interface VfxInstanceState {
|
|
33
|
+
/** Stable instance id. */
|
|
34
|
+
readonly id: string;
|
|
35
|
+
/** Effect archetype. */
|
|
36
|
+
readonly kind: RetainedVfxKind;
|
|
37
|
+
/** `0xRRGGBB` tint. */
|
|
38
|
+
readonly color: number;
|
|
39
|
+
/** Origin endpoint, if any. */
|
|
40
|
+
readonly from?: VfxRef;
|
|
41
|
+
/** Target endpoint, if any. */
|
|
42
|
+
readonly to?: VfxRef;
|
|
43
|
+
/** Effect radius/thickness. */
|
|
44
|
+
readonly radius?: number;
|
|
45
|
+
/** Renderer knobs. */
|
|
46
|
+
readonly params?: Readonly<Record<string, number>>;
|
|
47
|
+
/** TTL in ms, if the instance heartbeats. */
|
|
48
|
+
readonly ttlMs?: number;
|
|
49
|
+
/** Clock time (ms) of the last create/update; the TTL heartbeat measures staleness from here. */
|
|
50
|
+
readonly updatedAtMs: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A partial update to a live retained VFX instance. Only the provided fields change; `params` is shallow-merged
|
|
54
|
+
* so a caller can nudge one knob without resending the whole bag. Setting a field to `undefined` clears it.
|
|
55
|
+
* Applying a patch refreshes the instance heartbeat.
|
|
56
|
+
*/
|
|
57
|
+
export interface VfxInstancePatch {
|
|
58
|
+
/** New tint. */
|
|
59
|
+
color?: number;
|
|
60
|
+
/** New origin endpoint. */
|
|
61
|
+
from?: VfxRef;
|
|
62
|
+
/** New target endpoint. */
|
|
63
|
+
to?: VfxRef;
|
|
64
|
+
/** New radius/thickness. */
|
|
65
|
+
radius?: number;
|
|
66
|
+
/** Knobs shallow-merged into the current `params`. */
|
|
67
|
+
params?: Readonly<Record<string, number>>;
|
|
68
|
+
}
|
|
69
|
+
/** Options for {@link VfxInstanceStore.stop}. */
|
|
70
|
+
export interface VfxInstanceStopOptions {
|
|
71
|
+
/** Fade-out duration in ms handed to the renderer; `0` (default) disposes immediately. */
|
|
72
|
+
fadeMs?: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The lifecycle op a {@link VfxInstanceStore} emits to its renderer sink. `upsert`/`update` carry the full merged
|
|
76
|
+
* {@link VfxInstanceState} (the renderer applies it directly, no merge); `stop` carries the id plus a fade duration.
|
|
77
|
+
* This is the payload of the `combat.vfxInstance` game event when the store is wired to the event bus.
|
|
78
|
+
*/
|
|
79
|
+
export interface CombatVfxInstanceEvent {
|
|
80
|
+
/** `upsert` creates/replaces, `update` mutates dynamic params, `stop` disposes (with optional fade). */
|
|
81
|
+
readonly op: "upsert" | "update" | "stop";
|
|
82
|
+
/** The affected instance id. */
|
|
83
|
+
readonly id: string;
|
|
84
|
+
/** The full merged state, present for `upsert` and `update`. */
|
|
85
|
+
readonly instance?: VfxInstanceState;
|
|
86
|
+
/** Fade-out duration in ms, present for `stop`. */
|
|
87
|
+
readonly fadeMs?: number;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A headless registry of retained VFX instances: create/replace, partially update, and stop long-lived effects
|
|
91
|
+
* addressed by stable id, independent of any renderer. It owns the authoritative serializable state and exposes
|
|
92
|
+
* inspection counts; wire {@link VfxInstanceStoreOptions.onOp} to a renderer (via the `combat.vfxInstance` event)
|
|
93
|
+
* to drive visuals.
|
|
94
|
+
*/
|
|
95
|
+
export interface VfxInstanceStore {
|
|
96
|
+
/**
|
|
97
|
+
* Create the instance, or replace it in place when its id already exists (idempotent by id). Returns the id
|
|
98
|
+
* (minted when the spec omits one). Refreshes the heartbeat.
|
|
99
|
+
*/
|
|
100
|
+
upsert(spec: VfxInstanceSpec): string;
|
|
101
|
+
/**
|
|
102
|
+
* Merge `patch` into the live instance and refresh its heartbeat. Returns `false` for an unknown id (a missing
|
|
103
|
+
* update is a no-op, never a throw), `true` otherwise.
|
|
104
|
+
*/
|
|
105
|
+
update(id: string, patch: VfxInstancePatch): boolean;
|
|
106
|
+
/** Dispose the instance, emitting a `stop` op with the resolved fade. Returns `false` for an unknown id. */
|
|
107
|
+
stop(id: string, options?: VfxInstanceStopOptions): boolean;
|
|
108
|
+
/** The current state of `id`, or `null` if absent. */
|
|
109
|
+
get(id: string): VfxInstanceState | null;
|
|
110
|
+
/** Every live instance, insertion-ordered. */
|
|
111
|
+
list(): readonly VfxInstanceState[];
|
|
112
|
+
/** Live instance count, for debug/inspection HUDs. */
|
|
113
|
+
count(): number;
|
|
114
|
+
/** Auto-stop instances whose TTL has elapsed as of `nowMs` (defaults to the store clock). Returns the number stopped. */
|
|
115
|
+
tick(nowMs?: number): number;
|
|
116
|
+
/** Dispose every instance (scene change / reset), emitting a `stop` op for each. */
|
|
117
|
+
clear(): void;
|
|
118
|
+
}
|
|
119
|
+
/** Options for {@link createVfxInstanceStore}. */
|
|
120
|
+
export interface VfxInstanceStoreOptions {
|
|
121
|
+
/** Sink for lifecycle ops; wire to `events.emit("combat.vfxInstance", op)` so the shell renders them. */
|
|
122
|
+
onOp?: (op: CombatVfxInstanceEvent) => void;
|
|
123
|
+
/** Injected clock (ms) for heartbeat timestamps and TTL; defaults to `Date.now`. Pass a sim clock for determinism. */
|
|
124
|
+
now?: () => number;
|
|
125
|
+
/** Prefix for minted instance ids. Defaults to `"vfx"`. */
|
|
126
|
+
idPrefix?: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Build a headless retained-VFX registry. The store is the serializable source of truth for long-lived effects
|
|
130
|
+
* (beams, tethers, zones, target lines, looping emitters) that must move and mutate without one-shot re-emit
|
|
131
|
+
* flicker: `upsert` creates or replaces by stable id, `update` nudges dynamic params, `stop` disposes with an
|
|
132
|
+
* optional fade, and `tick` enforces TTL heartbeats. It stays independent of renderer availability, so simulation
|
|
133
|
+
* and tests run without a shell; a wired `onOp` sink turns each op into a `combat.vfxInstance` event the shell
|
|
134
|
+
* binds to render resources.
|
|
135
|
+
*
|
|
136
|
+
* @capability retained-vfx create/update/stop long-lived dynamic visual effects (beam, tether, zone, target line) by stable id
|
|
137
|
+
*/
|
|
138
|
+
export declare function createVfxInstanceStore(options?: VfxInstanceStoreOptions): VfxInstanceStore;
|