@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,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reusable order verbs every commandable game re-derives -- move, stop,
|
|
3
|
+
* hold, attack-move, targeted action, patrol -- built as ordinary
|
|
4
|
+
* `OrderKind`s over two narrow world adapters, not baked into the queue (#912).
|
|
5
|
+
* Each factory takes a configurable `kind` string, so a game re-skins a verb
|
|
6
|
+
* ("harvest", "board") without the engine ever knowing the name. Movement,
|
|
7
|
+
* target acquisition, pursuit/leash, and completion predicates compose here;
|
|
8
|
+
* effect execution stays game-side, driven off the intent each kind writes into
|
|
9
|
+
* `order.state`.
|
|
10
|
+
*/
|
|
11
|
+
const RUNNING = { status: "running" };
|
|
12
|
+
const COMPLETED = { status: "completed" };
|
|
13
|
+
const DEFAULT_ARRIVE = 0.6;
|
|
14
|
+
function gone() {
|
|
15
|
+
return { status: "failed", reason: "mover has no position (despawned)" };
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The plain "go here" verb: step toward a point each tick, complete on arrival,
|
|
19
|
+
* fail if the entity despawns. The completion predicate is arrival within
|
|
20
|
+
* `arriveRadius`.
|
|
21
|
+
*
|
|
22
|
+
* @capability move-order go-to-point order that completes on arrival, composed over a motion adapter
|
|
23
|
+
*/
|
|
24
|
+
export function defineMoveOrder(config = {}) {
|
|
25
|
+
const arriveDefault = config.arriveRadius ?? DEFAULT_ARRIVE;
|
|
26
|
+
return {
|
|
27
|
+
kind: config.kind ?? "move",
|
|
28
|
+
validate: (payload) => (Array.isArray(payload.point) ? null : { reason: "move order requires a point." }),
|
|
29
|
+
start: () => ({ ok: true }),
|
|
30
|
+
update(order, ctx) {
|
|
31
|
+
if (ctx.position() === null)
|
|
32
|
+
return gone();
|
|
33
|
+
const arriveRadius = order.payload.arriveRadius ?? arriveDefault;
|
|
34
|
+
const result = ctx.moveToward(order.payload.point, { arriveRadius, speedScale: order.payload.speedScale });
|
|
35
|
+
return result.arrived ? COMPLETED : RUNNING;
|
|
36
|
+
},
|
|
37
|
+
finish: (_order, ctx) => ctx.halt(),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Stop: halt immediately and complete the same tick — the interrupt that clears
|
|
42
|
+
* a unit's intent to standstill.
|
|
43
|
+
*
|
|
44
|
+
* @capability stop-order halt-and-complete order that brings a unit to an immediate standstill
|
|
45
|
+
*/
|
|
46
|
+
export function defineStopOrder(config = {}) {
|
|
47
|
+
return {
|
|
48
|
+
kind: config.kind ?? "stop",
|
|
49
|
+
start(_order, ctx) {
|
|
50
|
+
ctx.halt();
|
|
51
|
+
return { ok: true };
|
|
52
|
+
},
|
|
53
|
+
update: () => COMPLETED,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Hold position: stand ground indefinitely (never completes on its own) until
|
|
58
|
+
* preempted or canceled — the "guard here" verb.
|
|
59
|
+
*
|
|
60
|
+
* @capability hold-order stand-ground order that holds position until preempted or canceled
|
|
61
|
+
*/
|
|
62
|
+
export function defineHoldOrder(config = {}) {
|
|
63
|
+
return {
|
|
64
|
+
kind: config.kind ?? "hold",
|
|
65
|
+
start(_order, ctx) {
|
|
66
|
+
ctx.halt();
|
|
67
|
+
return { ok: true };
|
|
68
|
+
},
|
|
69
|
+
update(_order, ctx) {
|
|
70
|
+
return ctx.position() === null ? gone() : RUNNING;
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Attack-move: advance toward a destination but break off to engage any hostile
|
|
76
|
+
* acquired within `aggroRadius`, pursuing it to `attackRange` and writing the
|
|
77
|
+
* engagement intent into `order.state` for the game to act on. Completes on
|
|
78
|
+
* reaching the destination with nothing to engage.
|
|
79
|
+
*
|
|
80
|
+
* @capability attack-move-order advance-and-engage order that pursues hostiles en route and completes at its destination
|
|
81
|
+
*/
|
|
82
|
+
export function defineAttackMoveOrder(config = {}) {
|
|
83
|
+
const arriveDefault = config.arriveRadius ?? DEFAULT_ARRIVE;
|
|
84
|
+
const aggroDefault = config.aggroRadius ?? 6;
|
|
85
|
+
const attackDefault = config.attackRange ?? 1.5;
|
|
86
|
+
return {
|
|
87
|
+
kind: config.kind ?? "attack-move",
|
|
88
|
+
validate: (payload) => (Array.isArray(payload.point) ? null : { reason: "attack-move order requires a point." }),
|
|
89
|
+
start(order) {
|
|
90
|
+
order.state = { engaging: null, inRange: false };
|
|
91
|
+
return { ok: true };
|
|
92
|
+
},
|
|
93
|
+
update(order, ctx) {
|
|
94
|
+
const position = ctx.position();
|
|
95
|
+
if (position === null)
|
|
96
|
+
return gone();
|
|
97
|
+
const state = order.state;
|
|
98
|
+
const attackRange = order.payload.attackRange ?? attackDefault;
|
|
99
|
+
// Keep the current target if it is still alive, else re-acquire.
|
|
100
|
+
let targetPos = state.engaging !== null ? ctx.positionOf(state.engaging) : null;
|
|
101
|
+
if (targetPos === null) {
|
|
102
|
+
const acquired = ctx.acquire(order.payload.aggroRadius ?? aggroDefault);
|
|
103
|
+
state.engaging = acquired;
|
|
104
|
+
targetPos = acquired !== null ? ctx.positionOf(acquired) : null;
|
|
105
|
+
}
|
|
106
|
+
if (state.engaging !== null && targetPos !== null) {
|
|
107
|
+
const result = ctx.moveToward(targetPos, { arriveRadius: attackRange, speedScale: order.payload.speedScale });
|
|
108
|
+
state.inRange = result.arrived;
|
|
109
|
+
return RUNNING;
|
|
110
|
+
}
|
|
111
|
+
state.engaging = null;
|
|
112
|
+
state.inRange = false;
|
|
113
|
+
const result = ctx.moveToward(order.payload.point, {
|
|
114
|
+
arriveRadius: order.payload.arriveRadius ?? arriveDefault,
|
|
115
|
+
speedScale: order.payload.speedScale,
|
|
116
|
+
});
|
|
117
|
+
return result.arrived ? COMPLETED : RUNNING;
|
|
118
|
+
},
|
|
119
|
+
finish: (_order, ctx) => ctx.halt(),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Targeted action: pursue one specific target until within `range`, writing the
|
|
124
|
+
* engagement intent into `order.state`. Completes when the target is gone
|
|
125
|
+
* (despawned/dead), so the game's effect loop runs while `inRange` is true.
|
|
126
|
+
*
|
|
127
|
+
* @capability targeted-order pursue-a-target order with leash/standoff that ends when the target is gone
|
|
128
|
+
*/
|
|
129
|
+
export function defineTargetedOrder(config = {}) {
|
|
130
|
+
const rangeDefault = config.range ?? 1.5;
|
|
131
|
+
return {
|
|
132
|
+
kind: config.kind ?? "targeted",
|
|
133
|
+
validate: (payload) => (typeof payload.targetId === "string" && payload.targetId !== "" ? null : { reason: "targeted order requires a targetId." }),
|
|
134
|
+
start(order) {
|
|
135
|
+
order.state = { engaging: order.payload.targetId, inRange: false };
|
|
136
|
+
return { ok: true };
|
|
137
|
+
},
|
|
138
|
+
update(order, ctx) {
|
|
139
|
+
if (ctx.position() === null)
|
|
140
|
+
return gone();
|
|
141
|
+
const state = order.state;
|
|
142
|
+
const targetPos = ctx.positionOf(order.payload.targetId);
|
|
143
|
+
if (targetPos === null)
|
|
144
|
+
return COMPLETED; // target gone -> objective resolved
|
|
145
|
+
const range = order.payload.range ?? rangeDefault;
|
|
146
|
+
const result = ctx.moveToward(targetPos, { arriveRadius: range, speedScale: order.payload.speedScale });
|
|
147
|
+
state.inRange = result.arrived;
|
|
148
|
+
return RUNNING;
|
|
149
|
+
},
|
|
150
|
+
finish: (_order, ctx) => ctx.halt(),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Patrol: walk a waypoint route, advancing the serialized `index` as each point
|
|
155
|
+
* is reached. Loops forever by default, or completes at the last waypoint when
|
|
156
|
+
* `loop` is `false`.
|
|
157
|
+
*
|
|
158
|
+
* @capability patrol-order waypoint-route order that cycles a path, looping or completing at the end
|
|
159
|
+
*/
|
|
160
|
+
export function definePatrolOrder(config = {}) {
|
|
161
|
+
const arriveDefault = config.arriveRadius ?? DEFAULT_ARRIVE;
|
|
162
|
+
return {
|
|
163
|
+
kind: config.kind ?? "patrol",
|
|
164
|
+
validate: (payload) => Array.isArray(payload.waypoints) && payload.waypoints.length > 0 ? null : { reason: "patrol order requires at least one waypoint." },
|
|
165
|
+
start(order) {
|
|
166
|
+
order.state = { index: 0 };
|
|
167
|
+
return { ok: true };
|
|
168
|
+
},
|
|
169
|
+
update(order, ctx) {
|
|
170
|
+
if (ctx.position() === null)
|
|
171
|
+
return gone();
|
|
172
|
+
const state = order.state;
|
|
173
|
+
const waypoints = order.payload.waypoints;
|
|
174
|
+
const loop = order.payload.loop ?? true;
|
|
175
|
+
const target = waypoints[state.index];
|
|
176
|
+
if (target === undefined)
|
|
177
|
+
return COMPLETED;
|
|
178
|
+
const result = ctx.moveToward(target, {
|
|
179
|
+
arriveRadius: order.payload.arriveRadius ?? arriveDefault,
|
|
180
|
+
speedScale: order.payload.speedScale,
|
|
181
|
+
});
|
|
182
|
+
if (!result.arrived)
|
|
183
|
+
return RUNNING;
|
|
184
|
+
const next = state.index + 1;
|
|
185
|
+
if (next >= waypoints.length) {
|
|
186
|
+
if (!loop)
|
|
187
|
+
return COMPLETED;
|
|
188
|
+
state.index = 0;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
state.index = next;
|
|
192
|
+
}
|
|
193
|
+
return RUNNING;
|
|
194
|
+
},
|
|
195
|
+
finish: (_order, ctx) => ctx.halt(),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composable entity orders: a serializable command queue with lifecycle,
|
|
3
|
+
* preemption, and pluggable order kinds (#912). Player- or AI-issued intent
|
|
4
|
+
* ("move here", "attack that", "patrol this route") becomes reusable data
|
|
5
|
+
* instead of a hard-coded RTS verb kit. The queue owns issue -> activate ->
|
|
6
|
+
* tick -> complete/cancel lifecycle and deterministic preemption policy; each
|
|
7
|
+
* order KIND owns what "running" means, composed over narrow world adapters.
|
|
8
|
+
* Engine code never branches on `move`, `attack`, or any game verb -- kinds are
|
|
9
|
+
* looked up by string in a registry, so a game adds a verb by registering data.
|
|
10
|
+
*/
|
|
11
|
+
/** XZ+Y position triple, matching the engine heading convention used across `movement`/`scene`. */
|
|
12
|
+
export type OrderVec3 = readonly [number, number, number];
|
|
13
|
+
/** Lifecycle phase of a single order. `queued` waits behind the active order; `active` is ticking; `completed`/`canceled` are terminal. */
|
|
14
|
+
export type OrderPhase = "queued" | "active" | "completed" | "canceled";
|
|
15
|
+
/**
|
|
16
|
+
* Why an order left the queue without completing. `replaced`/`preempted` come
|
|
17
|
+
* from a newer order taking over; `requested` from explicit `cancelActive`;
|
|
18
|
+
* `invalid` when the kind's `start` rejects; `failed` when `update` reports
|
|
19
|
+
* failure; `cleared` from a full `clear`/`cancelAll`.
|
|
20
|
+
*/
|
|
21
|
+
export type OrderCancelReason = "replaced" | "preempted" | "requested" | "invalid" | "failed" | "cleared";
|
|
22
|
+
/**
|
|
23
|
+
* One issued order. Fully serializable: `kind` is a registry key (not a
|
|
24
|
+
* closure), `payload` is the caller's plain data, and `state` is the kind's own
|
|
25
|
+
* plain progress scratch (e.g. a patrol waypoint index) written during
|
|
26
|
+
* `start`/`update`. Never holds functions, so the whole queue round-trips
|
|
27
|
+
* through `JSON`/`structuredClone`.
|
|
28
|
+
*/
|
|
29
|
+
export interface Order<TPayload = unknown> {
|
|
30
|
+
/** Stable id, caller-supplied or generated deterministically by the queue. */
|
|
31
|
+
readonly id: string;
|
|
32
|
+
/** Registry key selecting the order kind. */
|
|
33
|
+
readonly kind: string;
|
|
34
|
+
/** Caller data the kind interprets (destination, target id, waypoints, ...). */
|
|
35
|
+
readonly payload: TPayload;
|
|
36
|
+
/** Current lifecycle phase; the queue owns transitions. */
|
|
37
|
+
phase: OrderPhase;
|
|
38
|
+
/** When `true`, preemption policies may not cancel this order mid-flight; a replacing order waits until it finishes. */
|
|
39
|
+
uninterruptible: boolean;
|
|
40
|
+
/** Optional authority tag (which player/AI issued it) carried for replication/audit; the queue does not interpret it. */
|
|
41
|
+
issuer?: string;
|
|
42
|
+
/** Kind-owned serializable progress; `undefined` until the kind activates. */
|
|
43
|
+
state?: unknown;
|
|
44
|
+
/** Set once `phase === "canceled"`. */
|
|
45
|
+
cancelReason?: OrderCancelReason;
|
|
46
|
+
}
|
|
47
|
+
/** A kind's refusal of a payload (from `validate`) — surfaced to the issuer as a rejection reason. */
|
|
48
|
+
export interface OrderRejection {
|
|
49
|
+
reason: string;
|
|
50
|
+
}
|
|
51
|
+
/** Result of a kind's `start`: `ok:false` skips the order and cancels it with reason `invalid`. The kind seeds `order.state` directly when `ok:true`. */
|
|
52
|
+
export type OrderStartResult = {
|
|
53
|
+
ok: true;
|
|
54
|
+
} | {
|
|
55
|
+
ok: false;
|
|
56
|
+
reason: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Result of a kind's `update` tick. `running` keeps the order active; the
|
|
60
|
+
* completion predicate lives in the kind (returns `completed`); `failed` cancels
|
|
61
|
+
* the order (reason `failed`) so the queue advances to the next one.
|
|
62
|
+
*/
|
|
63
|
+
export type OrderProgress = {
|
|
64
|
+
status: "running";
|
|
65
|
+
} | {
|
|
66
|
+
status: "completed";
|
|
67
|
+
} | {
|
|
68
|
+
status: "failed";
|
|
69
|
+
reason: string;
|
|
70
|
+
};
|
|
71
|
+
/** Terminal outcome handed to a kind's `finish` cleanup hook. */
|
|
72
|
+
export interface OrderOutcome {
|
|
73
|
+
phase: "completed" | "canceled";
|
|
74
|
+
reason?: OrderCancelReason;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The composition seam for one order verb. `TCtx` is the game's world adapter
|
|
78
|
+
* (movement, targeting, effects) shared by every kind in a registry; `TPayload`
|
|
79
|
+
* is this verb's caller data. `start` seeds `order.state`, `update` advances it
|
|
80
|
+
* and reports lifecycle, and `finish` releases anything the kind held. Kinds are
|
|
81
|
+
* pure over their injected `ctx` -- no globals, no direct scene reach.
|
|
82
|
+
*/
|
|
83
|
+
export interface OrderKind<TCtx, TPayload = unknown> {
|
|
84
|
+
/** The registry key; also the default `Order.kind` for issues of this verb. */
|
|
85
|
+
readonly kind: string;
|
|
86
|
+
/** Reject a malformed payload before it ever queues. */
|
|
87
|
+
validate?(payload: TPayload): OrderRejection | null;
|
|
88
|
+
/** Called once when the order becomes active. Seed `order.state` here; return `ok:false` to skip it. */
|
|
89
|
+
start(order: Order<TPayload>, ctx: TCtx): OrderStartResult;
|
|
90
|
+
/** Advance one tick. Read/write `order.state`; drive the world through `ctx`; report lifecycle. */
|
|
91
|
+
update(order: Order<TPayload>, ctx: TCtx, dt: number): OrderProgress;
|
|
92
|
+
/** Cleanup hook on completion or cancellation (stop movement, drop reservations). */
|
|
93
|
+
finish?(order: Order<TPayload>, ctx: TCtx, outcome: OrderOutcome): void;
|
|
94
|
+
}
|
|
95
|
+
/** Registry of order kinds keyed by verb string; the queue dispatches through it so engine code never switches on a verb. */
|
|
96
|
+
export interface OrderRegistry<TCtx> {
|
|
97
|
+
/** Register a kind under `kind.kind`; throws on a duplicate key. */
|
|
98
|
+
define<TPayload>(kind: OrderKind<TCtx, TPayload>): void;
|
|
99
|
+
has(kind: string): boolean;
|
|
100
|
+
/** Look up a kind, or `null` if unregistered. */
|
|
101
|
+
get(kind: string): OrderKind<TCtx, unknown> | null;
|
|
102
|
+
/** All registered verb keys, in insertion order. */
|
|
103
|
+
kinds(): string[];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* How a newly issued order interacts with what's already queued.
|
|
107
|
+
* `replace` preempts the active order and clears pending; `append` queues it
|
|
108
|
+
* behind everything (shift-queue); `front` makes it the next to run without
|
|
109
|
+
* touching the active order; `reject` refuses it while anything is queued.
|
|
110
|
+
*/
|
|
111
|
+
export type OrderQueuePolicy = "replace" | "append" | "front" | "reject";
|
|
112
|
+
/** A request to issue an order; `policy` defaults to `replace`, `id` is generated when omitted. */
|
|
113
|
+
export interface OrderRequest<TPayload = unknown> {
|
|
114
|
+
kind: string;
|
|
115
|
+
payload: TPayload;
|
|
116
|
+
id?: string;
|
|
117
|
+
policy?: OrderQueuePolicy;
|
|
118
|
+
uninterruptible?: boolean;
|
|
119
|
+
issuer?: string;
|
|
120
|
+
}
|
|
121
|
+
/** Outcome of `issue`: `accepted` entered the queue, `queued` entered behind an uninterruptible/active order, `rejected` was refused (validation or `reject` policy). */
|
|
122
|
+
export type OrderIssueResult<TPayload = unknown> = {
|
|
123
|
+
status: "accepted";
|
|
124
|
+
order: Order<TPayload>;
|
|
125
|
+
} | {
|
|
126
|
+
status: "queued";
|
|
127
|
+
order: Order<TPayload>;
|
|
128
|
+
} | {
|
|
129
|
+
status: "rejected";
|
|
130
|
+
reason: string;
|
|
131
|
+
};
|
|
132
|
+
/** Serializable snapshot of a queue: the active order plus the pending list, in order. */
|
|
133
|
+
export interface OrderQueueState<TPayload = unknown> {
|
|
134
|
+
active: Order<TPayload> | null;
|
|
135
|
+
pending: Order<TPayload>[];
|
|
136
|
+
}
|
|
137
|
+
/** A lifecycle event emitted synchronously as orders move through the queue. */
|
|
138
|
+
export interface OrderEvent {
|
|
139
|
+
type: "issued" | "activated" | "completed" | "canceled";
|
|
140
|
+
orderId: string;
|
|
141
|
+
kind: string;
|
|
142
|
+
reason?: OrderCancelReason;
|
|
143
|
+
}
|
|
144
|
+
/** What one `tick` did this frame, for tests and game reactions (play a bark on activation, flash on completion). Bounded per tick. */
|
|
145
|
+
export interface OrderTickReport<TPayload = unknown> {
|
|
146
|
+
active: Order<TPayload> | null;
|
|
147
|
+
activated: string[];
|
|
148
|
+
completed: string[];
|
|
149
|
+
canceled: {
|
|
150
|
+
id: string;
|
|
151
|
+
reason: OrderCancelReason;
|
|
152
|
+
}[];
|
|
153
|
+
}
|
|
154
|
+
/** Construction options for a queue. */
|
|
155
|
+
export interface OrderQueueOptions<TPayload = unknown> {
|
|
156
|
+
/** Deterministic id source for orders issued without an `id`; defaults to a monotonic `order-<n>` counter. */
|
|
157
|
+
genId?: () => string;
|
|
158
|
+
/** Synchronous lifecycle observer (analytics, HUD, replication). */
|
|
159
|
+
onEvent?: (event: OrderEvent) => void;
|
|
160
|
+
/** Initial state (e.g. a deserialized snapshot) to load on construction. */
|
|
161
|
+
initial?: OrderQueueState<TPayload>;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* A per-entity order queue: one commandable unit's lifecycle of intent. The
|
|
165
|
+
* game ticks it with its world adapter; it activates, advances, completes, and
|
|
166
|
+
* cancels orders and enforces preemption policy. State is serializable for save
|
|
167
|
+
* and host-authoritative replication.
|
|
168
|
+
*/
|
|
169
|
+
export interface OrderQueue<TCtx, TPayload = unknown> {
|
|
170
|
+
/** Queue or preempt an order per its policy; validates the payload through the kind. */
|
|
171
|
+
issue<T extends TPayload = TPayload>(request: OrderRequest<T>): OrderIssueResult<T>;
|
|
172
|
+
/** Advance the active order one step (activating the next pending order as needed) and report transitions. */
|
|
173
|
+
tick(ctx: TCtx, dt: number): OrderTickReport<TPayload>;
|
|
174
|
+
/** The active order, or `null` when idle. */
|
|
175
|
+
active(): Order<TPayload> | null;
|
|
176
|
+
/** The pending orders, in run order (a copy). */
|
|
177
|
+
pending(): Order<TPayload>[];
|
|
178
|
+
/** No active order and nothing pending. */
|
|
179
|
+
isIdle(): boolean;
|
|
180
|
+
/** Force-cancel the active order (explicit cleanup ignores `uninterruptible`); needs `ctx` to run the kind's `finish`. */
|
|
181
|
+
cancelActive(ctx: TCtx, reason?: OrderCancelReason): void;
|
|
182
|
+
/** Cancel the active order and drop every pending order. */
|
|
183
|
+
cancelAll(ctx: TCtx, reason?: OrderCancelReason): void;
|
|
184
|
+
/** Hard reset: cancel everything with reason `cleared`. */
|
|
185
|
+
clear(ctx: TCtx): void;
|
|
186
|
+
/** Plain-data snapshot for save/replication (deep-cloned; safe to serialize). */
|
|
187
|
+
serialize(): OrderQueueState<TPayload>;
|
|
188
|
+
/** Replace queue contents from a (possibly deserialized) snapshot; the active order keeps its `state`. */
|
|
189
|
+
load(state: OrderQueueState<TPayload>): void;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Build an empty order-kind registry. Register the built-in compositions from
|
|
193
|
+
* `orders/orderKinds` or your own verbs, then hand it to `createOrderQueue`.
|
|
194
|
+
* One registry is shared by many per-entity queues.
|
|
195
|
+
*
|
|
196
|
+
* @capability order-registry register order verbs (move/attack/custom) as data so engine code never branches on a verb
|
|
197
|
+
*/
|
|
198
|
+
export declare function createOrderRegistry<TCtx>(): OrderRegistry<TCtx>;
|
|
199
|
+
/**
|
|
200
|
+
* Create a per-entity order queue over a shared kind registry. The queue owns
|
|
201
|
+
* the deterministic lifecycle and preemption policy; the kinds own behavior.
|
|
202
|
+
* Nothing here is random or unbounded: id generation is injected, activation is
|
|
203
|
+
* bounded by the pending count, and a single `tick` advances at most the active
|
|
204
|
+
* order plus one activation.
|
|
205
|
+
*
|
|
206
|
+
* @capability order-queue serializable per-entity command queue with lifecycle, preemption, and pluggable order kinds
|
|
207
|
+
*/
|
|
208
|
+
export declare function createOrderQueue<TCtx, TPayload = unknown>(registry: OrderRegistry<TCtx>, options?: OrderQueueOptions<TPayload>): OrderQueue<TCtx, TPayload>;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composable entity orders: a serializable command queue with lifecycle,
|
|
3
|
+
* preemption, and pluggable order kinds (#912). Player- or AI-issued intent
|
|
4
|
+
* ("move here", "attack that", "patrol this route") becomes reusable data
|
|
5
|
+
* instead of a hard-coded RTS verb kit. The queue owns issue -> activate ->
|
|
6
|
+
* tick -> complete/cancel lifecycle and deterministic preemption policy; each
|
|
7
|
+
* order KIND owns what "running" means, composed over narrow world adapters.
|
|
8
|
+
* Engine code never branches on `move`, `attack`, or any game verb -- kinds are
|
|
9
|
+
* looked up by string in a registry, so a game adds a verb by registering data.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Build an empty order-kind registry. Register the built-in compositions from
|
|
13
|
+
* `orders/orderKinds` or your own verbs, then hand it to `createOrderQueue`.
|
|
14
|
+
* One registry is shared by many per-entity queues.
|
|
15
|
+
*
|
|
16
|
+
* @capability order-registry register order verbs (move/attack/custom) as data so engine code never branches on a verb
|
|
17
|
+
*/
|
|
18
|
+
export function createOrderRegistry() {
|
|
19
|
+
const kinds = new Map();
|
|
20
|
+
return {
|
|
21
|
+
define(kind) {
|
|
22
|
+
if (kinds.has(kind.kind))
|
|
23
|
+
throw new Error(`Order kind "${kind.kind}" is already defined.`);
|
|
24
|
+
kinds.set(kind.kind, kind);
|
|
25
|
+
},
|
|
26
|
+
has(kind) {
|
|
27
|
+
return kinds.has(kind);
|
|
28
|
+
},
|
|
29
|
+
get(kind) {
|
|
30
|
+
return kinds.get(kind) ?? null;
|
|
31
|
+
},
|
|
32
|
+
kinds() {
|
|
33
|
+
return [...kinds.keys()];
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function cloneOrder(order) {
|
|
38
|
+
return structuredClone(order);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a per-entity order queue over a shared kind registry. The queue owns
|
|
42
|
+
* the deterministic lifecycle and preemption policy; the kinds own behavior.
|
|
43
|
+
* Nothing here is random or unbounded: id generation is injected, activation is
|
|
44
|
+
* bounded by the pending count, and a single `tick` advances at most the active
|
|
45
|
+
* order plus one activation.
|
|
46
|
+
*
|
|
47
|
+
* @capability order-queue serializable per-entity command queue with lifecycle, preemption, and pluggable order kinds
|
|
48
|
+
*/
|
|
49
|
+
export function createOrderQueue(registry, options = {}) {
|
|
50
|
+
const onEvent = options.onEvent;
|
|
51
|
+
let counter = 0;
|
|
52
|
+
const genId = options.genId ?? (() => `order-${++counter}`);
|
|
53
|
+
let active = options.initial ? options.initial.active : null;
|
|
54
|
+
let pending = options.initial ? [...options.initial.pending] : [];
|
|
55
|
+
function emit(type, order, reason) {
|
|
56
|
+
onEvent?.({ type, orderId: order.id, kind: order.kind, reason });
|
|
57
|
+
}
|
|
58
|
+
function markCanceled(order, reason) {
|
|
59
|
+
order.phase = "canceled";
|
|
60
|
+
order.cancelReason = reason;
|
|
61
|
+
emit("canceled", order, reason);
|
|
62
|
+
}
|
|
63
|
+
function finishActive(ctx, outcome) {
|
|
64
|
+
if (active === null)
|
|
65
|
+
return;
|
|
66
|
+
const kind = registry.get(active.kind);
|
|
67
|
+
kind?.finish?.(active, ctx, outcome);
|
|
68
|
+
}
|
|
69
|
+
/** Pull pending orders forward until one activates or the queue drains. Bounded by the pending length at entry. */
|
|
70
|
+
function activateNext(ctx, report) {
|
|
71
|
+
let budget = pending.length;
|
|
72
|
+
while (active === null && budget > 0) {
|
|
73
|
+
budget -= 1;
|
|
74
|
+
const next = pending.shift();
|
|
75
|
+
if (next === undefined)
|
|
76
|
+
return;
|
|
77
|
+
const kind = registry.get(next.kind);
|
|
78
|
+
if (kind === null) {
|
|
79
|
+
markCanceled(next, "invalid");
|
|
80
|
+
report.canceled.push({ id: next.id, reason: "invalid" });
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const started = kind.start(next, ctx);
|
|
84
|
+
if (!started.ok) {
|
|
85
|
+
markCanceled(next, "invalid");
|
|
86
|
+
report.canceled.push({ id: next.id, reason: "invalid" });
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
next.phase = "active";
|
|
90
|
+
active = next;
|
|
91
|
+
emit("activated", next);
|
|
92
|
+
report.activated.push(next.id);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
issue(request) {
|
|
97
|
+
const kind = registry.get(request.kind);
|
|
98
|
+
if (kind === null)
|
|
99
|
+
return { status: "rejected", reason: `Unknown order kind "${request.kind}".` };
|
|
100
|
+
const rejection = kind.validate?.(request.payload) ?? null;
|
|
101
|
+
if (rejection)
|
|
102
|
+
return { status: "rejected", reason: rejection.reason };
|
|
103
|
+
const policy = request.policy ?? "replace";
|
|
104
|
+
if (policy === "reject" && (active !== null || pending.length > 0)) {
|
|
105
|
+
return { status: "rejected", reason: "Queue is busy and policy is reject." };
|
|
106
|
+
}
|
|
107
|
+
const order = {
|
|
108
|
+
id: request.id ?? genId(),
|
|
109
|
+
kind: request.kind,
|
|
110
|
+
payload: request.payload,
|
|
111
|
+
phase: "queued",
|
|
112
|
+
uninterruptible: request.uninterruptible ?? false,
|
|
113
|
+
...(request.issuer !== undefined ? { issuer: request.issuer } : {}),
|
|
114
|
+
};
|
|
115
|
+
emit("issued", order);
|
|
116
|
+
if (policy === "replace") {
|
|
117
|
+
// Preempt the active order unless it is protected; a protected order
|
|
118
|
+
// finishes first and the newcomer waits at the front of the queue.
|
|
119
|
+
for (const queued of pending)
|
|
120
|
+
markCanceled(queued, "replaced");
|
|
121
|
+
pending = [];
|
|
122
|
+
if (active !== null && !active.uninterruptible) {
|
|
123
|
+
markCanceled(active, "replaced");
|
|
124
|
+
active = null;
|
|
125
|
+
}
|
|
126
|
+
pending.push(order);
|
|
127
|
+
return { status: active !== null ? "queued" : "accepted", order: order };
|
|
128
|
+
}
|
|
129
|
+
if (policy === "front") {
|
|
130
|
+
pending.unshift(order);
|
|
131
|
+
return { status: active !== null ? "queued" : "accepted", order: order };
|
|
132
|
+
}
|
|
133
|
+
// append (and the empty-queue reject case)
|
|
134
|
+
pending.push(order);
|
|
135
|
+
return { status: active !== null || pending.length > 1 ? "queued" : "accepted", order: order };
|
|
136
|
+
},
|
|
137
|
+
tick(ctx, dt) {
|
|
138
|
+
const report = { active: null, activated: [], completed: [], canceled: [] };
|
|
139
|
+
if (active === null)
|
|
140
|
+
activateNext(ctx, report);
|
|
141
|
+
if (active !== null) {
|
|
142
|
+
const kind = registry.get(active.kind);
|
|
143
|
+
if (kind === null) {
|
|
144
|
+
markCanceled(active, "invalid");
|
|
145
|
+
report.canceled.push({ id: active.id, reason: "invalid" });
|
|
146
|
+
active = null;
|
|
147
|
+
activateNext(ctx, report);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
const progress = kind.update(active, ctx, dt);
|
|
151
|
+
if (progress.status === "completed") {
|
|
152
|
+
finishActive(ctx, { phase: "completed" });
|
|
153
|
+
active.phase = "completed";
|
|
154
|
+
emit("completed", active);
|
|
155
|
+
report.completed.push(active.id);
|
|
156
|
+
active = null;
|
|
157
|
+
activateNext(ctx, report);
|
|
158
|
+
}
|
|
159
|
+
else if (progress.status === "failed") {
|
|
160
|
+
finishActive(ctx, { phase: "canceled", reason: "failed" });
|
|
161
|
+
markCanceled(active, "failed");
|
|
162
|
+
report.canceled.push({ id: active.id, reason: "failed" });
|
|
163
|
+
active = null;
|
|
164
|
+
activateNext(ctx, report);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
report.active = active;
|
|
169
|
+
return report;
|
|
170
|
+
},
|
|
171
|
+
active() {
|
|
172
|
+
return active;
|
|
173
|
+
},
|
|
174
|
+
pending() {
|
|
175
|
+
return [...pending];
|
|
176
|
+
},
|
|
177
|
+
isIdle() {
|
|
178
|
+
return active === null && pending.length === 0;
|
|
179
|
+
},
|
|
180
|
+
cancelActive(ctx, reason = "requested") {
|
|
181
|
+
if (active === null)
|
|
182
|
+
return;
|
|
183
|
+
finishActive(ctx, { phase: "canceled", reason });
|
|
184
|
+
markCanceled(active, reason);
|
|
185
|
+
active = null;
|
|
186
|
+
},
|
|
187
|
+
cancelAll(ctx, reason = "requested") {
|
|
188
|
+
for (const queued of pending)
|
|
189
|
+
markCanceled(queued, reason);
|
|
190
|
+
pending = [];
|
|
191
|
+
if (active !== null) {
|
|
192
|
+
finishActive(ctx, { phase: "canceled", reason });
|
|
193
|
+
markCanceled(active, reason);
|
|
194
|
+
active = null;
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
clear(ctx) {
|
|
198
|
+
this.cancelAll(ctx, "cleared");
|
|
199
|
+
},
|
|
200
|
+
serialize() {
|
|
201
|
+
return {
|
|
202
|
+
active: active ? cloneOrder(active) : null,
|
|
203
|
+
pending: pending.map(cloneOrder),
|
|
204
|
+
};
|
|
205
|
+
},
|
|
206
|
+
load(state) {
|
|
207
|
+
active = state.active ? cloneOrder(state.active) : null;
|
|
208
|
+
pending = state.pending.map(cloneOrder);
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AxisInput } from "../input/axisInput.js";
|
|
2
|
+
import type { KinematicVehicle, KinematicVehicleModifiers, KinematicVehicleStep } from "./kinematicVehicle.js";
|
|
3
|
+
/** World-space `[x, y, z]` for a drivable vehicle's resolved pose. */
|
|
4
|
+
export type DrivableVehiclePosition = readonly [number, number, number];
|
|
5
|
+
/** Options for {@link tickDrivableVehicle} — ground snapping and per-tick tuning modifiers. */
|
|
6
|
+
export interface DrivableVehicleOptions {
|
|
7
|
+
/** Resamples world-space Y each tick (terrain height, a ramp, a bridge deck); omit to keep the sim's own flat `y`. */
|
|
8
|
+
groundHeight?: (x: number, z: number) => number;
|
|
9
|
+
modifiers?: KinematicVehicleModifiers;
|
|
10
|
+
}
|
|
11
|
+
/** A `setPose`-ready patch — spread straight into `entities.setPose(vehicleId, drive.pose)`. */
|
|
12
|
+
export interface DrivableVehiclePose {
|
|
13
|
+
position: DrivableVehiclePosition;
|
|
14
|
+
rotationY: number;
|
|
15
|
+
rotationX: number;
|
|
16
|
+
rotationZ: number;
|
|
17
|
+
dt: number;
|
|
18
|
+
}
|
|
19
|
+
/** {@link tickDrivableVehicle}'s result — the ready-to-apply pose patch plus the raw sim step for HUD/telemetry reads. */
|
|
20
|
+
export interface DrivableVehicleStep {
|
|
21
|
+
pose: DrivableVehiclePose;
|
|
22
|
+
step: KinematicVehicleStep;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Connects an `AxisInput` sample straight through a {@link KinematicVehicle} to a scene entity's pose
|
|
26
|
+
* for one tick (#533.1) — the throttle/steer/handbrake → sim → `setPose` loop every drivable-vehicle
|
|
27
|
+
* game hand-rolled. Ground-snaps the result when `groundHeight` is given (terrain-following cars, not
|
|
28
|
+
* just flat racetracks). Pair with `scene/vehicleSeat` for who is allowed to drive and where the camera
|
|
29
|
+
* points; this function only steps the sim and shapes the pose patch, nothing else.
|
|
30
|
+
*/
|
|
31
|
+
export declare function tickDrivableVehicle(vehicle: KinematicVehicle, dt: number, axis: AxisInput, options?: DrivableVehicleOptions): DrivableVehicleStep;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connects an `AxisInput` sample straight through a {@link KinematicVehicle} to a scene entity's pose
|
|
3
|
+
* for one tick (#533.1) — the throttle/steer/handbrake → sim → `setPose` loop every drivable-vehicle
|
|
4
|
+
* game hand-rolled. Ground-snaps the result when `groundHeight` is given (terrain-following cars, not
|
|
5
|
+
* just flat racetracks). Pair with `scene/vehicleSeat` for who is allowed to drive and where the camera
|
|
6
|
+
* points; this function only steps the sim and shapes the pose patch, nothing else.
|
|
7
|
+
*/
|
|
8
|
+
export function tickDrivableVehicle(vehicle, dt, axis, options = {}) {
|
|
9
|
+
const step = vehicle.tick(dt, axis, options.modifiers);
|
|
10
|
+
const [x, y, z] = step.position;
|
|
11
|
+
const resolvedY = options.groundHeight === undefined ? y : options.groundHeight(x, z);
|
|
12
|
+
return {
|
|
13
|
+
pose: { position: [x, resolvedY, z], rotationX: step.bodyPitch, rotationY: step.heading, rotationZ: step.bodyRoll, dt },
|
|
14
|
+
step,
|
|
15
|
+
};
|
|
16
|
+
}
|