@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,222 @@
|
|
|
1
|
+
import { type Curve } from "../game/progression.js";
|
|
2
|
+
/**
|
|
3
|
+
* How cycles that came due between two {@link advanceLedger} calls are settled:
|
|
4
|
+
* - `"each"` — replay every missed cycle as its own transaction (bounded by the limits below);
|
|
5
|
+
* - `"sum"` — collapse the missed cycles into one transaction of the combined amount;
|
|
6
|
+
* - `"skip"` — apply only the most recent cycle and discard the rest (idle income that does not bank).
|
|
7
|
+
*/
|
|
8
|
+
export type CatchUpPolicy = "each" | "sum" | "skip";
|
|
9
|
+
/**
|
|
10
|
+
* A serializable recurring resource flow. Every field is plain JSON so the whole
|
|
11
|
+
* {@link ResourceLedger} round-trips through `structuredClone`/`JSON`. Dynamic, context-aware
|
|
12
|
+
* behaviour (providers, tax curves, affordability caps) lives in the runtime
|
|
13
|
+
* {@link ResourcePolicy} pipeline, never in this data.
|
|
14
|
+
*/
|
|
15
|
+
export interface ScheduledRule {
|
|
16
|
+
/** Stable id, unique within a ledger. */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Resource/currency key that moves. */
|
|
19
|
+
currency: string;
|
|
20
|
+
/** Positive nominal amount moved per cycle before policies run. */
|
|
21
|
+
amount: number;
|
|
22
|
+
/** Cadence in game-seconds; must be `> 0`. */
|
|
23
|
+
everySeconds: number;
|
|
24
|
+
/** First due time in game-seconds; defaults to the ledger clock when the rule is added. */
|
|
25
|
+
startSeconds?: number;
|
|
26
|
+
/** Inclusive end time; omitted means the rule never expires. */
|
|
27
|
+
endSeconds?: number;
|
|
28
|
+
/** Account debited each cycle; omitted mints the amount from an external source (production). */
|
|
29
|
+
source?: string;
|
|
30
|
+
/** Account credited each cycle; omitted burns the amount into an external sink (upkeep/tax). */
|
|
31
|
+
recipient?: string;
|
|
32
|
+
/** Finite reserve consumed by the nominal amount each cycle; the rule depletes when it empties. */
|
|
33
|
+
reserve?: number;
|
|
34
|
+
/** Catch-up settlement policy; defaults to `"each"`. */
|
|
35
|
+
catchUp?: CatchUpPolicy;
|
|
36
|
+
/** Per-rule offline limit: due cycles beyond this in one advance are dropped, not banked. */
|
|
37
|
+
maxCatchUpCycles?: number;
|
|
38
|
+
}
|
|
39
|
+
/** Mutable per-rule progress, kept separate from the immutable {@link ScheduledRule} definition. */
|
|
40
|
+
export interface RuleCursor {
|
|
41
|
+
/** Absolute time of the next cycle that has not yet been settled. */
|
|
42
|
+
nextDueSeconds: number;
|
|
43
|
+
/** Remaining finite reserve, when the rule declared one. */
|
|
44
|
+
reserveRemaining?: number;
|
|
45
|
+
/** Total cycles fired so far — a stable, monotonic cycle index. */
|
|
46
|
+
fired: number;
|
|
47
|
+
/** Paused rules keep their cursor but fire nothing until resumed. */
|
|
48
|
+
paused: boolean;
|
|
49
|
+
/** Set once the rule expired or fully depleted; it never fires again. */
|
|
50
|
+
done: boolean;
|
|
51
|
+
}
|
|
52
|
+
/** Fully serializable scheduled-transaction state: clock, balances, rule definitions, and cursors. */
|
|
53
|
+
export interface ResourceLedger {
|
|
54
|
+
nowSeconds: number;
|
|
55
|
+
accounts: Record<string, Record<string, number>>;
|
|
56
|
+
rules: Record<string, ScheduledRule>;
|
|
57
|
+
cursors: Record<string, RuleCursor>;
|
|
58
|
+
}
|
|
59
|
+
/** One resource movement produced by a due cycle, before it is applied to balances. */
|
|
60
|
+
export interface ResourceTransaction {
|
|
61
|
+
ruleId: string;
|
|
62
|
+
currency: string;
|
|
63
|
+
amount: number;
|
|
64
|
+
source?: string;
|
|
65
|
+
recipient?: string;
|
|
66
|
+
/** Which cycle of the rule produced this (from {@link RuleCursor.fired}). */
|
|
67
|
+
cycleIndex: number;
|
|
68
|
+
atSeconds: number;
|
|
69
|
+
/** Ordered provenance tags appended by the policy pipeline. */
|
|
70
|
+
provenance: readonly string[];
|
|
71
|
+
}
|
|
72
|
+
/** Read-only context handed to every {@link ResourcePolicy} for a transaction. */
|
|
73
|
+
export interface PolicyContext {
|
|
74
|
+
/** The rule that scheduled this flow. */
|
|
75
|
+
rule: ScheduledRule;
|
|
76
|
+
/** Current balance snapshot (reflects transactions already applied this advance). */
|
|
77
|
+
balanceOf(account: string, currency: string): number;
|
|
78
|
+
/** Caller-supplied numeric context bag read by threshold/curve modifiers. */
|
|
79
|
+
vars: Readonly<Record<string, number>>;
|
|
80
|
+
nowSeconds: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A composable transform over one transaction. Return the transactions to keep:
|
|
84
|
+
* `[]` rejects it, `[txn]` passes/transforms it, and multiple entries split it.
|
|
85
|
+
*/
|
|
86
|
+
export type ResourcePolicy = (txn: ResourceTransaction, ctx: PolicyContext) => readonly ResourceTransaction[];
|
|
87
|
+
/** Deterministic rounding applied to every transaction amount before it touches balances. */
|
|
88
|
+
export interface Precision {
|
|
89
|
+
/** Quantisation step, e.g. `1` for whole units or `0.01` for cents. */
|
|
90
|
+
quantum: number;
|
|
91
|
+
/** Rounding mode; defaults to `"round"`. */
|
|
92
|
+
mode?: "floor" | "round" | "ceil";
|
|
93
|
+
}
|
|
94
|
+
/** A `{ min, factor }` band for {@link thresholdScale}; the highest band whose `min` is met wins. */
|
|
95
|
+
export interface ThresholdBand {
|
|
96
|
+
min: number;
|
|
97
|
+
factor: number;
|
|
98
|
+
}
|
|
99
|
+
/** Per-advance settings: the policy pipeline, caller context, rounding, and safety bounds. */
|
|
100
|
+
export interface AdvanceOptions {
|
|
101
|
+
/** Policy pipeline applied to every transaction, in order. */
|
|
102
|
+
policies?: readonly ResourcePolicy[];
|
|
103
|
+
/** Numeric context exposed to policies via {@link PolicyContext.vars}. */
|
|
104
|
+
vars?: Readonly<Record<string, number>>;
|
|
105
|
+
/** Rounding applied to each transaction amount before it hits balances. */
|
|
106
|
+
precision?: Precision;
|
|
107
|
+
/** Global safety bound on individual cycles settled per rule per advance; defaults to `10000`. */
|
|
108
|
+
maxCyclesPerRule?: number;
|
|
109
|
+
}
|
|
110
|
+
/** The kinds of lifecycle signal {@link advanceLedger} can emit for a rule. */
|
|
111
|
+
export type LedgerEventKind = "started" | "fired" | "skipped" | "depleted" | "ended";
|
|
112
|
+
/** Lifecycle signal emitted by {@link advanceLedger}. */
|
|
113
|
+
export interface LedgerEvent {
|
|
114
|
+
kind: LedgerEventKind;
|
|
115
|
+
ruleId: string;
|
|
116
|
+
atSeconds: number;
|
|
117
|
+
/** Cycle count for `fired`/`skipped`, or the consumed reserve for `depleted`. */
|
|
118
|
+
detail: number;
|
|
119
|
+
}
|
|
120
|
+
/** A {@link ResourceTransaction} after policies and rounding, as actually applied to balances. */
|
|
121
|
+
export type AppliedTransaction = ResourceTransaction;
|
|
122
|
+
/** The outcome of {@link advanceLedger}: the new ledger plus applied transactions and events. */
|
|
123
|
+
export interface AdvanceResult {
|
|
124
|
+
ledger: ResourceLedger;
|
|
125
|
+
applied: AppliedTransaction[];
|
|
126
|
+
events: LedgerEvent[];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Create an empty scheduled-transaction ledger, or hydrate one from a saved snapshot.
|
|
130
|
+
* State is plain data: production, depletion, tax, and upkeep are all expressed as
|
|
131
|
+
* {@link ScheduledRule}s settled deterministically by {@link advanceLedger}.
|
|
132
|
+
*
|
|
133
|
+
* @capability resource-ledger schedule recurring resource transactions with policy transforms
|
|
134
|
+
*/
|
|
135
|
+
export declare function createResourceLedger(init?: Partial<ResourceLedger>): ResourceLedger;
|
|
136
|
+
/** Read a single balance; unknown account/currency pairs read as `0`. */
|
|
137
|
+
export declare function balanceOf(ledger: ResourceLedger, account: string, currency: string): number;
|
|
138
|
+
/**
|
|
139
|
+
* Register a recurring rule and seed its cursor. Returns a new ledger; the rule's first cycle
|
|
140
|
+
* is due at `rule.startSeconds` (defaulting to the current clock).
|
|
141
|
+
*/
|
|
142
|
+
export declare function addScheduledRule(ledger: ResourceLedger, rule: ScheduledRule): ResourceLedger;
|
|
143
|
+
/**
|
|
144
|
+
* Remove a rule and its cursor entirely (hard cancellation).
|
|
145
|
+
*
|
|
146
|
+
* @capability cancel-scheduled-rule remove a scheduled rule and its cursor entirely
|
|
147
|
+
*/
|
|
148
|
+
export declare function cancelRule(ledger: ResourceLedger, ruleId: string): ResourceLedger;
|
|
149
|
+
/**
|
|
150
|
+
* Pause a rule: its cursor is retained but it fires nothing until {@link resumeRule}.
|
|
151
|
+
*
|
|
152
|
+
* @capability pause-scheduled-rule stop a scheduled rule from firing while retaining its cursor
|
|
153
|
+
*/
|
|
154
|
+
export declare function pauseRule(ledger: ResourceLedger, ruleId: string): ResourceLedger;
|
|
155
|
+
/**
|
|
156
|
+
* Resume a paused rule. Its `nextDueSeconds` is unchanged, so the paused span counts as missed
|
|
157
|
+
* cycles that the rule's {@link CatchUpPolicy} decides how to settle on the next advance.
|
|
158
|
+
*
|
|
159
|
+
* @capability resume-scheduled-rule resume a paused scheduled rule, deferring missed cycles to its catch-up policy
|
|
160
|
+
*/
|
|
161
|
+
export declare function resumeRule(ledger: ResourceLedger, ruleId: string): ResourceLedger;
|
|
162
|
+
/**
|
|
163
|
+
* Advance the ledger clock to `toSeconds`, settling every due cycle deterministically.
|
|
164
|
+
* Rules are processed in sorted-id order; cycle counts are integer math; large deltas are
|
|
165
|
+
* bounded by `catchUp`, `maxCatchUpCycles`, and `maxCyclesPerRule`. Every produced transaction
|
|
166
|
+
* flows through the policy pipeline (transform, cap, reject, split, redirect, annotate) before it
|
|
167
|
+
* is quantised and applied to balances.
|
|
168
|
+
*
|
|
169
|
+
* @capability advance-ledger settle due scheduled transactions through a policy pipeline
|
|
170
|
+
*/
|
|
171
|
+
export declare function advanceLedger(ledger: ResourceLedger, toSeconds: number, options?: AdvanceOptions): AdvanceResult;
|
|
172
|
+
/** Reader over policy context: a `vars` key or a function of the context. */
|
|
173
|
+
export type PolicyRead = string | ((ctx: PolicyContext) => number);
|
|
174
|
+
/**
|
|
175
|
+
* Clamp a transaction's amount to at most `max` (a fixed number or a function of context).
|
|
176
|
+
*
|
|
177
|
+
* @capability policy-cap cap a scheduled transaction amount by context
|
|
178
|
+
*/
|
|
179
|
+
export declare function capAmount(max: number | ((ctx: PolicyContext) => number)): ResourcePolicy;
|
|
180
|
+
/**
|
|
181
|
+
* Take a fraction of the amount. With `to`, the taxed portion is split off into a second
|
|
182
|
+
* transaction toward that recipient (a transfer/tax); without it, the fraction is simply removed.
|
|
183
|
+
*
|
|
184
|
+
* @capability policy-tax split off a fraction of a transaction as tax or transfer
|
|
185
|
+
*/
|
|
186
|
+
export declare function taxFraction(fraction: number, to?: string): ResourcePolicy;
|
|
187
|
+
/**
|
|
188
|
+
* Override the source and/or recipient accounts of a transaction.
|
|
189
|
+
*
|
|
190
|
+
* @capability policy-redirect redirect a scheduled transaction's source or recipient
|
|
191
|
+
*/
|
|
192
|
+
export declare function redirect(endpoints: {
|
|
193
|
+
source?: string;
|
|
194
|
+
recipient?: string;
|
|
195
|
+
}): ResourcePolicy;
|
|
196
|
+
/**
|
|
197
|
+
* Drop a transaction when `predicate` holds — the reject arm of the pipeline.
|
|
198
|
+
*
|
|
199
|
+
* @capability policy-reject reject scheduled transactions by predicate
|
|
200
|
+
*/
|
|
201
|
+
export declare function rejectWhen(predicate: (txn: ResourceTransaction, ctx: PolicyContext) => boolean): ResourcePolicy;
|
|
202
|
+
/**
|
|
203
|
+
* Append a provenance tag to a transaction without changing its value.
|
|
204
|
+
*
|
|
205
|
+
* @capability policy-annotate tag a scheduled transaction's provenance without changing its value
|
|
206
|
+
*/
|
|
207
|
+
export declare function annotate(tag: string): ResourcePolicy;
|
|
208
|
+
/**
|
|
209
|
+
* Scale the amount by the highest {@link ThresholdBand} whose `min` the read value meets — a
|
|
210
|
+
* generic bracket modifier (progressive tax, tiered upkeep) over caller data, with no built-in
|
|
211
|
+
* currencies or brackets.
|
|
212
|
+
*
|
|
213
|
+
* @capability policy-threshold scale a transaction by a context threshold band
|
|
214
|
+
*/
|
|
215
|
+
export declare function thresholdScale(read: PolicyRead, bands: readonly ThresholdBand[]): ResourcePolicy;
|
|
216
|
+
/**
|
|
217
|
+
* Scale the amount by a {@link Curve} evaluated at the read value — a generic curve modifier
|
|
218
|
+
* (population upkeep, depletion falloff, difficulty income) over caller-provided context.
|
|
219
|
+
*
|
|
220
|
+
* @capability policy-curve scale a transaction by a curve over context
|
|
221
|
+
*/
|
|
222
|
+
export declare function curveScale(read: PolicyRead, shape: Curve): ResourcePolicy;
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { evalCurve } from "../game/progression.js";
|
|
2
|
+
const EPSILON = 1e-9;
|
|
3
|
+
/**
|
|
4
|
+
* Create an empty scheduled-transaction ledger, or hydrate one from a saved snapshot.
|
|
5
|
+
* State is plain data: production, depletion, tax, and upkeep are all expressed as
|
|
6
|
+
* {@link ScheduledRule}s settled deterministically by {@link advanceLedger}.
|
|
7
|
+
*
|
|
8
|
+
* @capability resource-ledger schedule recurring resource transactions with policy transforms
|
|
9
|
+
*/
|
|
10
|
+
export function createResourceLedger(init) {
|
|
11
|
+
return {
|
|
12
|
+
nowSeconds: init?.nowSeconds ?? 0,
|
|
13
|
+
accounts: cloneAccounts(init?.accounts ?? {}),
|
|
14
|
+
rules: { ...(init?.rules ?? {}) },
|
|
15
|
+
cursors: { ...(init?.cursors ?? {}) },
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Read a single balance; unknown account/currency pairs read as `0`. */
|
|
19
|
+
export function balanceOf(ledger, account, currency) {
|
|
20
|
+
return ledger.accounts[account]?.[currency] ?? 0;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Register a recurring rule and seed its cursor. Returns a new ledger; the rule's first cycle
|
|
24
|
+
* is due at `rule.startSeconds` (defaulting to the current clock).
|
|
25
|
+
*/
|
|
26
|
+
export function addScheduledRule(ledger, rule) {
|
|
27
|
+
if (!(rule.everySeconds > 0)) {
|
|
28
|
+
throw new RangeError(`rule ${rule.id} everySeconds must be positive, got ${rule.everySeconds}`);
|
|
29
|
+
}
|
|
30
|
+
if (!Number.isFinite(rule.amount) || rule.amount < 0) {
|
|
31
|
+
throw new RangeError(`rule ${rule.id} amount must be a non-negative finite number, got ${rule.amount}`);
|
|
32
|
+
}
|
|
33
|
+
const cursor = {
|
|
34
|
+
nextDueSeconds: rule.startSeconds ?? ledger.nowSeconds,
|
|
35
|
+
reserveRemaining: rule.reserve,
|
|
36
|
+
fired: 0,
|
|
37
|
+
paused: false,
|
|
38
|
+
done: false,
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
...ledger,
|
|
42
|
+
rules: { ...ledger.rules, [rule.id]: { ...rule } },
|
|
43
|
+
cursors: { ...ledger.cursors, [rule.id]: cursor },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Remove a rule and its cursor entirely (hard cancellation).
|
|
48
|
+
*
|
|
49
|
+
* @capability cancel-scheduled-rule remove a scheduled rule and its cursor entirely
|
|
50
|
+
*/
|
|
51
|
+
export function cancelRule(ledger, ruleId) {
|
|
52
|
+
if (ledger.rules[ruleId] === undefined)
|
|
53
|
+
return ledger;
|
|
54
|
+
const rules = { ...ledger.rules };
|
|
55
|
+
const cursors = { ...ledger.cursors };
|
|
56
|
+
delete rules[ruleId];
|
|
57
|
+
delete cursors[ruleId];
|
|
58
|
+
return { ...ledger, rules, cursors };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Pause a rule: its cursor is retained but it fires nothing until {@link resumeRule}.
|
|
62
|
+
*
|
|
63
|
+
* @capability pause-scheduled-rule stop a scheduled rule from firing while retaining its cursor
|
|
64
|
+
*/
|
|
65
|
+
export function pauseRule(ledger, ruleId) {
|
|
66
|
+
return setPaused(ledger, ruleId, true);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resume a paused rule. Its `nextDueSeconds` is unchanged, so the paused span counts as missed
|
|
70
|
+
* cycles that the rule's {@link CatchUpPolicy} decides how to settle on the next advance.
|
|
71
|
+
*
|
|
72
|
+
* @capability resume-scheduled-rule resume a paused scheduled rule, deferring missed cycles to its catch-up policy
|
|
73
|
+
*/
|
|
74
|
+
export function resumeRule(ledger, ruleId) {
|
|
75
|
+
return setPaused(ledger, ruleId, false);
|
|
76
|
+
}
|
|
77
|
+
function setPaused(ledger, ruleId, paused) {
|
|
78
|
+
const cursor = ledger.cursors[ruleId];
|
|
79
|
+
if (cursor === undefined || cursor.paused === paused)
|
|
80
|
+
return ledger;
|
|
81
|
+
return { ...ledger, cursors: { ...ledger.cursors, [ruleId]: { ...cursor, paused } } };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Advance the ledger clock to `toSeconds`, settling every due cycle deterministically.
|
|
85
|
+
* Rules are processed in sorted-id order; cycle counts are integer math; large deltas are
|
|
86
|
+
* bounded by `catchUp`, `maxCatchUpCycles`, and `maxCyclesPerRule`. Every produced transaction
|
|
87
|
+
* flows through the policy pipeline (transform, cap, reject, split, redirect, annotate) before it
|
|
88
|
+
* is quantised and applied to balances.
|
|
89
|
+
*
|
|
90
|
+
* @capability advance-ledger settle due scheduled transactions through a policy pipeline
|
|
91
|
+
*/
|
|
92
|
+
export function advanceLedger(ledger, toSeconds, options = {}) {
|
|
93
|
+
if (toSeconds < ledger.nowSeconds) {
|
|
94
|
+
throw new RangeError(`advanceLedger cannot rewind: ${toSeconds} < ${ledger.nowSeconds}`);
|
|
95
|
+
}
|
|
96
|
+
const accounts = cloneAccounts(ledger.accounts);
|
|
97
|
+
const cursors = { ...ledger.cursors };
|
|
98
|
+
const applied = [];
|
|
99
|
+
const events = [];
|
|
100
|
+
const policies = options.policies ?? [];
|
|
101
|
+
const vars = options.vars ?? {};
|
|
102
|
+
const maxCycles = options.maxCyclesPerRule ?? 10_000;
|
|
103
|
+
const ctxBalance = (account, currency) => accounts[account]?.[currency] ?? 0;
|
|
104
|
+
for (const id of Object.keys(ledger.rules).sort()) {
|
|
105
|
+
const rule = ledger.rules[id];
|
|
106
|
+
const cursor = { ...cursors[id] };
|
|
107
|
+
if (cursor.done || cursor.paused)
|
|
108
|
+
continue;
|
|
109
|
+
const end = rule.endSeconds ?? Number.POSITIVE_INFINITY;
|
|
110
|
+
const windowEnd = Math.min(toSeconds, end);
|
|
111
|
+
if (cursor.nextDueSeconds <= windowEnd) {
|
|
112
|
+
const wasFirstFire = cursor.fired === 0;
|
|
113
|
+
const dueCount = Math.floor((windowEnd - cursor.nextDueSeconds) / rule.everySeconds + EPSILON) + 1;
|
|
114
|
+
const firstDue = cursor.nextDueSeconds;
|
|
115
|
+
const perRuleLimit = rule.maxCatchUpCycles ?? Number.POSITIVE_INFINITY;
|
|
116
|
+
const catchUp = rule.catchUp ?? "each";
|
|
117
|
+
// Reserve-capped nominal amount per candidate cycle, in chronological order.
|
|
118
|
+
const nominal = reserveCappedAmounts(dueCount, rule.amount, cursor.reserveRemaining);
|
|
119
|
+
const depleted = cursor.reserveRemaining !== undefined && nominal.remaining <= EPSILON;
|
|
120
|
+
const cycles = buildCycles(catchUp, nominal.amounts, firstDue, rule.everySeconds, perRuleLimit, maxCycles);
|
|
121
|
+
if (wasFirstFire && cycles.settled.length > 0) {
|
|
122
|
+
events.push({ kind: "started", ruleId: id, atSeconds: cycles.settled[0].atSeconds, detail: 0 });
|
|
123
|
+
}
|
|
124
|
+
for (const cycle of cycles.settled) {
|
|
125
|
+
const seed = {
|
|
126
|
+
ruleId: id,
|
|
127
|
+
currency: rule.currency,
|
|
128
|
+
amount: cycle.amount,
|
|
129
|
+
source: rule.source,
|
|
130
|
+
recipient: rule.recipient,
|
|
131
|
+
cycleIndex: cursor.fired,
|
|
132
|
+
atSeconds: cycle.atSeconds,
|
|
133
|
+
provenance: [],
|
|
134
|
+
};
|
|
135
|
+
cursor.fired += 1;
|
|
136
|
+
const context = { rule, balanceOf: ctxBalance, vars, nowSeconds: cycle.atSeconds };
|
|
137
|
+
for (const txn of runPolicies(seed, policies, context)) {
|
|
138
|
+
const amount = quantize(txn.amount, options.precision);
|
|
139
|
+
if (amount === 0)
|
|
140
|
+
continue;
|
|
141
|
+
const finalTxn = { ...txn, amount };
|
|
142
|
+
applyTransaction(accounts, finalTxn);
|
|
143
|
+
applied.push(finalTxn);
|
|
144
|
+
events.push({ kind: "fired", ruleId: id, atSeconds: finalTxn.atSeconds, detail: amount });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (cycles.skipped > 0) {
|
|
148
|
+
events.push({ kind: "skipped", ruleId: id, atSeconds: windowEnd, detail: cycles.skipped });
|
|
149
|
+
}
|
|
150
|
+
if (cursor.reserveRemaining !== undefined)
|
|
151
|
+
cursor.reserveRemaining = nominal.remaining;
|
|
152
|
+
// Time always moves past every due cycle in the window, whether settled or skipped.
|
|
153
|
+
cursor.nextDueSeconds = firstDue + dueCount * rule.everySeconds;
|
|
154
|
+
if (depleted) {
|
|
155
|
+
cursor.done = true;
|
|
156
|
+
events.push({ kind: "depleted", ruleId: id, atSeconds: windowEnd, detail: nominal.consumed });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (!cursor.done && Number.isFinite(end) && cursor.nextDueSeconds > end) {
|
|
160
|
+
cursor.done = true;
|
|
161
|
+
events.push({ kind: "ended", ruleId: id, atSeconds: end, detail: cursor.fired });
|
|
162
|
+
}
|
|
163
|
+
cursors[id] = cursor;
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
ledger: { nowSeconds: toSeconds, accounts, rules: { ...ledger.rules }, cursors },
|
|
167
|
+
applied,
|
|
168
|
+
events,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function buildCycles(catchUp, amounts, firstDue, everySeconds, perRuleLimit, maxCycles) {
|
|
172
|
+
const available = amounts.length;
|
|
173
|
+
if (available === 0)
|
|
174
|
+
return { settled: [], skipped: 0 };
|
|
175
|
+
const timeOf = (index) => firstDue + index * everySeconds;
|
|
176
|
+
if (catchUp === "skip") {
|
|
177
|
+
const last = available - 1;
|
|
178
|
+
return { settled: [{ atSeconds: timeOf(last), amount: amounts[last] }], skipped: last };
|
|
179
|
+
}
|
|
180
|
+
if (catchUp === "sum") {
|
|
181
|
+
const kept = Math.min(available, perRuleLimit);
|
|
182
|
+
let total = 0;
|
|
183
|
+
for (let i = 0; i < kept; i += 1)
|
|
184
|
+
total += amounts[i];
|
|
185
|
+
const skipped = available - kept;
|
|
186
|
+
if (kept === 0)
|
|
187
|
+
return { settled: [], skipped };
|
|
188
|
+
return { settled: [{ atSeconds: timeOf(kept - 1), amount: total }], skipped };
|
|
189
|
+
}
|
|
190
|
+
// "each"
|
|
191
|
+
const kept = Math.min(available, perRuleLimit, maxCycles);
|
|
192
|
+
const settled = [];
|
|
193
|
+
for (let i = 0; i < kept; i += 1)
|
|
194
|
+
settled.push({ atSeconds: timeOf(i), amount: amounts[i] });
|
|
195
|
+
return { settled, skipped: available - kept };
|
|
196
|
+
}
|
|
197
|
+
function reserveCappedAmounts(count, amount, reserveRemaining) {
|
|
198
|
+
if (reserveRemaining === undefined) {
|
|
199
|
+
return { amounts: new Array(count).fill(amount), remaining: Number.POSITIVE_INFINITY, consumed: count * amount };
|
|
200
|
+
}
|
|
201
|
+
const amounts = [];
|
|
202
|
+
let remaining = reserveRemaining;
|
|
203
|
+
for (let i = 0; i < count && remaining > EPSILON; i += 1) {
|
|
204
|
+
const take = Math.min(amount, remaining);
|
|
205
|
+
amounts.push(take);
|
|
206
|
+
remaining -= take;
|
|
207
|
+
}
|
|
208
|
+
if (remaining < EPSILON)
|
|
209
|
+
remaining = 0;
|
|
210
|
+
return { amounts, remaining, consumed: reserveRemaining - remaining };
|
|
211
|
+
}
|
|
212
|
+
function runPolicies(seed, policies, ctx) {
|
|
213
|
+
let current = [seed];
|
|
214
|
+
for (const policy of policies) {
|
|
215
|
+
const next = [];
|
|
216
|
+
for (const txn of current) {
|
|
217
|
+
for (const out of policy(txn, ctx))
|
|
218
|
+
next.push(out);
|
|
219
|
+
}
|
|
220
|
+
current = next;
|
|
221
|
+
if (current.length === 0)
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
return current;
|
|
225
|
+
}
|
|
226
|
+
function applyTransaction(accounts, txn) {
|
|
227
|
+
if (txn.source !== undefined)
|
|
228
|
+
addBalance(accounts, txn.source, txn.currency, -txn.amount);
|
|
229
|
+
if (txn.recipient !== undefined)
|
|
230
|
+
addBalance(accounts, txn.recipient, txn.currency, txn.amount);
|
|
231
|
+
}
|
|
232
|
+
function addBalance(accounts, account, currency, delta) {
|
|
233
|
+
const wallet = accounts[account] ?? (accounts[account] = {});
|
|
234
|
+
wallet[currency] = (wallet[currency] ?? 0) + delta;
|
|
235
|
+
}
|
|
236
|
+
function quantize(value, precision) {
|
|
237
|
+
if (precision === undefined || !(precision.quantum > 0))
|
|
238
|
+
return value;
|
|
239
|
+
const steps = value / precision.quantum;
|
|
240
|
+
const rounded = Math.round(steps * 1e9) / 1e9;
|
|
241
|
+
const mode = precision.mode ?? "round";
|
|
242
|
+
const n = mode === "floor" ? Math.floor(rounded) : mode === "ceil" ? Math.ceil(rounded) : Math.round(rounded);
|
|
243
|
+
return n * precision.quantum;
|
|
244
|
+
}
|
|
245
|
+
function cloneAccounts(accounts) {
|
|
246
|
+
const out = {};
|
|
247
|
+
for (const account of Object.keys(accounts))
|
|
248
|
+
out[account] = { ...accounts[account] };
|
|
249
|
+
return out;
|
|
250
|
+
}
|
|
251
|
+
function readValue(read, ctx) {
|
|
252
|
+
return typeof read === "function" ? read(ctx) : (ctx.vars[read] ?? 0);
|
|
253
|
+
}
|
|
254
|
+
function tagged(txn, tag) {
|
|
255
|
+
return [...txn.provenance, tag];
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Clamp a transaction's amount to at most `max` (a fixed number or a function of context).
|
|
259
|
+
*
|
|
260
|
+
* @capability policy-cap cap a scheduled transaction amount by context
|
|
261
|
+
*/
|
|
262
|
+
export function capAmount(max) {
|
|
263
|
+
return (txn, ctx) => {
|
|
264
|
+
const limit = typeof max === "function" ? max(ctx) : max;
|
|
265
|
+
if (txn.amount <= limit)
|
|
266
|
+
return [txn];
|
|
267
|
+
return [{ ...txn, amount: limit, provenance: tagged(txn, "capped") }];
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Take a fraction of the amount. With `to`, the taxed portion is split off into a second
|
|
272
|
+
* transaction toward that recipient (a transfer/tax); without it, the fraction is simply removed.
|
|
273
|
+
*
|
|
274
|
+
* @capability policy-tax split off a fraction of a transaction as tax or transfer
|
|
275
|
+
*/
|
|
276
|
+
export function taxFraction(fraction, to) {
|
|
277
|
+
const rate = Math.max(0, Math.min(1, fraction));
|
|
278
|
+
return (txn) => {
|
|
279
|
+
const taxed = txn.amount * rate;
|
|
280
|
+
const kept = txn.amount - taxed;
|
|
281
|
+
const out = [];
|
|
282
|
+
if (kept > 0)
|
|
283
|
+
out.push({ ...txn, amount: kept, provenance: tagged(txn, "taxed") });
|
|
284
|
+
if (taxed > 0 && to !== undefined) {
|
|
285
|
+
out.push({ ...txn, amount: taxed, recipient: to, provenance: tagged(txn, `tax->${to}`) });
|
|
286
|
+
}
|
|
287
|
+
return out;
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Override the source and/or recipient accounts of a transaction.
|
|
292
|
+
*
|
|
293
|
+
* @capability policy-redirect redirect a scheduled transaction's source or recipient
|
|
294
|
+
*/
|
|
295
|
+
export function redirect(endpoints) {
|
|
296
|
+
return (txn) => [
|
|
297
|
+
{
|
|
298
|
+
...txn,
|
|
299
|
+
source: endpoints.source ?? txn.source,
|
|
300
|
+
recipient: endpoints.recipient ?? txn.recipient,
|
|
301
|
+
provenance: tagged(txn, "redirected"),
|
|
302
|
+
},
|
|
303
|
+
];
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Drop a transaction when `predicate` holds — the reject arm of the pipeline.
|
|
307
|
+
*
|
|
308
|
+
* @capability policy-reject reject scheduled transactions by predicate
|
|
309
|
+
*/
|
|
310
|
+
export function rejectWhen(predicate) {
|
|
311
|
+
return (txn, ctx) => (predicate(txn, ctx) ? [] : [txn]);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Append a provenance tag to a transaction without changing its value.
|
|
315
|
+
*
|
|
316
|
+
* @capability policy-annotate tag a scheduled transaction's provenance without changing its value
|
|
317
|
+
*/
|
|
318
|
+
export function annotate(tag) {
|
|
319
|
+
return (txn) => [{ ...txn, provenance: tagged(txn, tag) }];
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Scale the amount by the highest {@link ThresholdBand} whose `min` the read value meets — a
|
|
323
|
+
* generic bracket modifier (progressive tax, tiered upkeep) over caller data, with no built-in
|
|
324
|
+
* currencies or brackets.
|
|
325
|
+
*
|
|
326
|
+
* @capability policy-threshold scale a transaction by a context threshold band
|
|
327
|
+
*/
|
|
328
|
+
export function thresholdScale(read, bands) {
|
|
329
|
+
const sorted = [...bands].sort((a, b) => a.min - b.min);
|
|
330
|
+
return (txn, ctx) => {
|
|
331
|
+
const value = readValue(read, ctx);
|
|
332
|
+
let factor = 1;
|
|
333
|
+
for (const band of sorted) {
|
|
334
|
+
if (value >= band.min)
|
|
335
|
+
factor = band.factor;
|
|
336
|
+
else
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
return [{ ...txn, amount: txn.amount * factor, provenance: tagged(txn, `threshold:${factor}`) }];
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Scale the amount by a {@link Curve} evaluated at the read value — a generic curve modifier
|
|
344
|
+
* (population upkeep, depletion falloff, difficulty income) over caller-provided context.
|
|
345
|
+
*
|
|
346
|
+
* @capability policy-curve scale a transaction by a curve over context
|
|
347
|
+
*/
|
|
348
|
+
export function curveScale(read, shape) {
|
|
349
|
+
return (txn, ctx) => {
|
|
350
|
+
const factor = evalCurve(shape, readValue(read, ctx));
|
|
351
|
+
return [{ ...txn, amount: txn.amount * factor, provenance: tagged(txn, "curve") }];
|
|
352
|
+
};
|
|
353
|
+
}
|
|
@@ -6,8 +6,11 @@ export type WalletScope = {
|
|
|
6
6
|
kind: "group";
|
|
7
7
|
groupId: string;
|
|
8
8
|
};
|
|
9
|
+
/** @internal */
|
|
9
10
|
export declare function scopeKey(scope: WalletScope): string;
|
|
11
|
+
/** @internal */
|
|
10
12
|
export declare function userScope(userId: string): WalletScope;
|
|
13
|
+
/** @internal */
|
|
11
14
|
export declare function groupScope(groupId: string): WalletScope;
|
|
12
15
|
export interface WalletBook {
|
|
13
16
|
scopes: Readonly<Record<string, WalletState>>;
|
|
@@ -20,9 +23,20 @@ export type BookChargeResult = {
|
|
|
20
23
|
status: "rejected";
|
|
21
24
|
reason: "insufficient-funds";
|
|
22
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* Shared or group currency pools that track each member's contribution to a common balance.
|
|
28
|
+
*
|
|
29
|
+
* @capability shared-wallet shared/group currency pools tracking per-member contributions
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
23
32
|
export declare function createWalletBook(): WalletBook;
|
|
33
|
+
/** @internal */
|
|
24
34
|
export declare function balanceIn(book: WalletBook, scope: WalletScope, currency: string): number;
|
|
35
|
+
/** @internal */
|
|
25
36
|
export declare function grantTo(book: WalletBook, scope: WalletScope, currency: string, amount: number, by?: string): WalletBook;
|
|
37
|
+
/** @internal */
|
|
26
38
|
export declare function chargeFrom(book: WalletBook, scope: WalletScope, currency: string, amount: number, by?: string): BookChargeResult;
|
|
39
|
+
/** @internal */
|
|
27
40
|
export declare function contributionOf(book: WalletBook, groupId: string, userId: string): Readonly<Record<string, number>>;
|
|
41
|
+
/** @internal */
|
|
28
42
|
export declare function contributorsOf(book: WalletBook, groupId: string): string[];
|
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
import { balance, charge, createEmptyWallet, grant } from "./wallet.js";
|
|
2
|
+
/** @internal */
|
|
2
3
|
export function scopeKey(scope) {
|
|
3
4
|
return scope.kind === "user" ? `user:${scope.userId}` : `group:${scope.groupId}`;
|
|
4
5
|
}
|
|
6
|
+
/** @internal */
|
|
5
7
|
export function userScope(userId) {
|
|
6
8
|
return { kind: "user", userId };
|
|
7
9
|
}
|
|
10
|
+
/** @internal */
|
|
8
11
|
export function groupScope(groupId) {
|
|
9
12
|
return { kind: "group", groupId };
|
|
10
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Shared or group currency pools that track each member's contribution to a common balance.
|
|
16
|
+
*
|
|
17
|
+
* @capability shared-wallet shared/group currency pools tracking per-member contributions
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
11
20
|
export function createWalletBook() {
|
|
12
21
|
return { scopes: {}, contributions: {} };
|
|
13
22
|
}
|
|
14
23
|
function scopeState(book, key) {
|
|
15
24
|
return book.scopes[key] ?? createEmptyWallet();
|
|
16
25
|
}
|
|
26
|
+
/** @internal */
|
|
17
27
|
export function balanceIn(book, scope, currency) {
|
|
18
28
|
return balance(scopeState(book, scopeKey(scope)), currency);
|
|
19
29
|
}
|
|
@@ -35,6 +45,7 @@ function recordContribution(book, groupKey, userId, currency, delta) {
|
|
|
35
45
|
},
|
|
36
46
|
};
|
|
37
47
|
}
|
|
48
|
+
/** @internal */
|
|
38
49
|
export function grantTo(book, scope, currency, amount, by) {
|
|
39
50
|
const key = scopeKey(scope);
|
|
40
51
|
let next = withScope(book, key, grant(scopeState(book, key), currency, amount));
|
|
@@ -43,6 +54,7 @@ export function grantTo(book, scope, currency, amount, by) {
|
|
|
43
54
|
}
|
|
44
55
|
return next;
|
|
45
56
|
}
|
|
57
|
+
/** @internal */
|
|
46
58
|
export function chargeFrom(book, scope, currency, amount, by) {
|
|
47
59
|
const key = scopeKey(scope);
|
|
48
60
|
const result = charge(scopeState(book, key), currency, amount);
|
|
@@ -54,9 +66,11 @@ export function chargeFrom(book, scope, currency, amount, by) {
|
|
|
54
66
|
}
|
|
55
67
|
return { status: "ok", book: next };
|
|
56
68
|
}
|
|
69
|
+
/** @internal */
|
|
57
70
|
export function contributionOf(book, groupId, userId) {
|
|
58
71
|
return book.contributions[scopeKey(groupScope(groupId))]?.[userId] ?? {};
|
|
59
72
|
}
|
|
73
|
+
/** @internal */
|
|
60
74
|
export function contributorsOf(book, groupId) {
|
|
61
75
|
return Object.keys(book.contributions[scopeKey(groupScope(groupId))] ?? {});
|
|
62
76
|
}
|