@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
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export type MovementKey = "w" | "a" | "s" | "d" | "shift" | "control" | "c" | "space";
|
|
14
14
|
export type MovementKeysState = Record<MovementKey, boolean>;
|
|
15
|
+
/** @internal */
|
|
15
16
|
export declare function createEmptyMovementKeys(): MovementKeysState;
|
|
16
17
|
/**
|
|
17
18
|
* Frame-independent description of what the player is asking the avatar to do.
|
|
@@ -31,7 +32,8 @@ export interface MovementIntent {
|
|
|
31
32
|
* Translate the set of held keys into an intent. When `canMove` is false (a
|
|
32
33
|
* menu is open, the world is paused) the avatar is fully idle so it never
|
|
33
34
|
* drifts behind an overlay.
|
|
34
|
-
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
35
37
|
export declare function resolveMovementIntent(keys: MovementKeysState, canMove: boolean): MovementIntent;
|
|
36
38
|
/**
|
|
37
39
|
* Kinematics + feel tuning for the first-person controller. Centralised here so
|
|
@@ -43,6 +45,8 @@ export declare const MOVEMENT_TUNING: {
|
|
|
43
45
|
readonly walkSpeedMultiplier: 1.75;
|
|
44
46
|
readonly runSpeedMultiplier: 2.25;
|
|
45
47
|
readonly crouchSpeedMultiplier: 0.45;
|
|
48
|
+
/** Backward (S) travels this fraction of walk speed so retreating reads slower than advancing. */
|
|
49
|
+
readonly backpedalSpeedMultiplier: 0.65;
|
|
46
50
|
readonly groundAcceleration: 26;
|
|
47
51
|
readonly airAcceleration: 12;
|
|
48
52
|
readonly groundFriction: 18;
|
|
@@ -74,6 +78,7 @@ export interface PlayerMotionState {
|
|
|
74
78
|
grounded: boolean;
|
|
75
79
|
jumpHeld: boolean;
|
|
76
80
|
}
|
|
81
|
+
/** @internal */
|
|
77
82
|
export declare function createPlayerMotionState(): PlayerMotionState;
|
|
78
83
|
/** Horizontal step (world units) the avatar should commit this frame. */
|
|
79
84
|
export interface MovementFrameStep {
|
|
@@ -87,6 +92,19 @@ export interface MovementFrameStep {
|
|
|
87
92
|
export interface MovementTuningOverrides {
|
|
88
93
|
gravityAcceleration?: number;
|
|
89
94
|
jumpVelocity?: number;
|
|
95
|
+
/** Fraction of walk speed while backpedalling; overrides {@link MOVEMENT_TUNING.backpedalSpeedMultiplier}. */
|
|
96
|
+
backpedalSpeedMultiplier?: number;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Per-frame dynamic modifiers for {@link advancePlayerMotion} — state the caller
|
|
100
|
+
* recomputes each tick (unlike the static {@link MovementTuningOverrides}). Omitted
|
|
101
|
+
* fields leave the integrator at its default behavior.
|
|
102
|
+
*/
|
|
103
|
+
export interface MotionFrameOptions {
|
|
104
|
+
/** Extra multiplier applied on top of the resolved target speed (e.g. swimming). Default 1. */
|
|
105
|
+
speedScale?: number;
|
|
106
|
+
/** Suppress gravity/jump integration and hold the avatar afloat this frame (e.g. swimming). Default false. */
|
|
107
|
+
floating?: boolean;
|
|
90
108
|
}
|
|
91
109
|
/**
|
|
92
110
|
* Advance one frame of avatar kinematics. Mutates `motion` (velocity, jump,
|
|
@@ -97,14 +115,29 @@ export interface MovementTuningOverrides {
|
|
|
97
115
|
* (need not be normalized); the avatar's right axis is derived from it. Pulling
|
|
98
116
|
* this out of the render loop is what lets us assert "held forward for N frames
|
|
99
117
|
* crosses the room" in a unit test instead of only in the live game.
|
|
100
|
-
|
|
101
|
-
|
|
118
|
+
* @internal
|
|
119
|
+
*/
|
|
120
|
+
export declare function advancePlayerMotion(motion: PlayerMotionState, intent: MovementIntent, forwardX: number, forwardZ: number, baseSpeed: number, rawDeltaSeconds: number, tuning?: MovementTuningOverrides, options?: MotionFrameOptions): MovementFrameStep;
|
|
102
121
|
/** A placed scene object the walking player collides against as a circle-vs-AABB obstacle. */
|
|
103
122
|
export interface CollisionObstacle {
|
|
104
123
|
position: readonly [number, number, number];
|
|
105
|
-
/** Box half-size on each axis. Default `[0.5, 0.5, 0.5]` (unit-box scene objects). */
|
|
124
|
+
/** Box half-size on each axis. Default `[0.5, 0.5, 0.5]` (unit-box scene objects). Ignored when `boxes` is set. */
|
|
106
125
|
halfExtents?: readonly [number, number, number];
|
|
126
|
+
/** Local center shift added to `position` for the single-AABB path (the collider's yaw-rotated offset). Ignored when `boxes` is set. */
|
|
127
|
+
offset?: readonly [number, number, number];
|
|
128
|
+
/**
|
|
129
|
+
* Optional compound solid: axis-aligned sub-boxes as `min`/`max` **relative to `position`** (add
|
|
130
|
+
* `position` for world space), already yaw-rotated and conservatively expanded by the caller. When
|
|
131
|
+
* present the capsule slides against EACH sub-box instead of the single `halfExtents` AABB, so a
|
|
132
|
+
* concave opening (the gap between an archway's pillars/lintel) lets the capsule pass through.
|
|
133
|
+
*/
|
|
134
|
+
boxes?: readonly {
|
|
135
|
+
min: readonly [number, number, number];
|
|
136
|
+
max: readonly [number, number, number];
|
|
137
|
+
}[];
|
|
107
138
|
}
|
|
139
|
+
/** @internal Player radius the walking obstruction inflates obstacles by; callers gather within reach of it. */
|
|
140
|
+
export declare const DEFAULT_OBSTACLE_PLAYER_RADIUS = 0.3;
|
|
108
141
|
/**
|
|
109
142
|
* Resolve a horizontal step against nearby placed objects with classic
|
|
110
143
|
* axis-separated sliding (try X, then Z against the post-X position) so
|
|
@@ -113,21 +146,29 @@ export interface CollisionObstacle {
|
|
|
113
146
|
* by `playerRadius`; an obstacle whose vertical span misses the player's
|
|
114
147
|
* feet-to-head span is skipped entirely. Callers should pre-filter to nearby
|
|
115
148
|
* objects — this also early-exits per obstacle on horizontal distance.
|
|
116
|
-
|
|
149
|
+
* @internal
|
|
150
|
+
*/
|
|
117
151
|
export declare function resolveObstacleStep(current: readonly [number, number, number], stepX: number, stepZ: number, obstacles: readonly CollisionObstacle[], playerRadius?: number): MovementFrameStep;
|
|
118
|
-
/** Placed objects within `radius` (XZ) of `center`, as {@link CollisionObstacle}s to pre-filter for {@link resolveObstacleStep}.
|
|
152
|
+
/** Placed objects within `radius` (XZ) of `center`, as {@link CollisionObstacle}s to pre-filter for {@link resolveObstacleStep}.
|
|
153
|
+
* @internal
|
|
154
|
+
*/
|
|
119
155
|
export declare function nearbyObstacles(objects: readonly {
|
|
120
156
|
position: readonly [number, number, number];
|
|
121
157
|
}[], center: readonly [number, number, number], radius?: number): CollisionObstacle[];
|
|
122
|
-
/** Zeroes the off-axis component so travel is locked to a single world axis (`PlayerMovementConfig.mode: "axis"`).
|
|
158
|
+
/** Zeroes the off-axis component so travel is locked to a single world axis (`PlayerMovementConfig.mode: "axis"`).
|
|
159
|
+
* @internal
|
|
160
|
+
*/
|
|
123
161
|
export declare function constrainStepToAxis(stepX: number, stepZ: number, axis: "x" | "z"): MovementFrameStep;
|
|
124
162
|
/**
|
|
125
163
|
* Snap a world position to its containing cell's center, matching the
|
|
126
164
|
* bounds-free form of `navGrid`'s and `tacticalGrid`'s `floor` + half-cell
|
|
127
165
|
* convention (`PlayerMovementConfig.mode: "grid"`).
|
|
128
|
-
|
|
166
|
+
* @internal
|
|
167
|
+
*/
|
|
129
168
|
export declare function snapPositionToGrid(x: number, z: number, cellSize: number): [number, number];
|
|
130
169
|
/** Peak jump height from MOVEMENT_TUNING.jumpVelocity + gravity, with small buffer. */
|
|
131
170
|
export declare const MAX_JUMP_OFFSET = 1.15;
|
|
132
|
-
/** Camera yaw looks along -Z; character mesh faces +Z at body rotation.y = 0.
|
|
171
|
+
/** Camera yaw looks along -Z; character mesh faces +Z at body rotation.y = 0.
|
|
172
|
+
* @internal
|
|
173
|
+
*/
|
|
133
174
|
export declare function cameraYawToAvatarBodyYaw(cameraYaw: number): number;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* touch controls) and its camera rigs (pointer lock, the per-frame look
|
|
11
11
|
* channel).
|
|
12
12
|
*/
|
|
13
|
+
/** @internal */
|
|
13
14
|
export function createEmptyMovementKeys() {
|
|
14
15
|
return { w: false, a: false, s: false, d: false, shift: false, control: false, c: false, space: false };
|
|
15
16
|
}
|
|
@@ -25,7 +26,8 @@ const IDLE_INTENT = {
|
|
|
25
26
|
* Translate the set of held keys into an intent. When `canMove` is false (a
|
|
26
27
|
* menu is open, the world is paused) the avatar is fully idle so it never
|
|
27
28
|
* drifts behind an overlay.
|
|
28
|
-
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
29
31
|
export function resolveMovementIntent(keys, canMove) {
|
|
30
32
|
if (!canMove)
|
|
31
33
|
return IDLE_INTENT;
|
|
@@ -52,6 +54,8 @@ export const MOVEMENT_TUNING = {
|
|
|
52
54
|
walkSpeedMultiplier: 1.75,
|
|
53
55
|
runSpeedMultiplier: 2.25,
|
|
54
56
|
crouchSpeedMultiplier: 0.45,
|
|
57
|
+
/** Backward (S) travels this fraction of walk speed so retreating reads slower than advancing. */
|
|
58
|
+
backpedalSpeedMultiplier: 0.65,
|
|
55
59
|
groundAcceleration: 26,
|
|
56
60
|
airAcceleration: 12,
|
|
57
61
|
groundFriction: 18,
|
|
@@ -70,15 +74,24 @@ export const MOVEMENT_TUNING = {
|
|
|
70
74
|
/** Largest physics step we integrate so a stalled tab can't teleport the player. */
|
|
71
75
|
maxFrameSeconds: 0.05,
|
|
72
76
|
};
|
|
73
|
-
/**
|
|
74
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Speed (units/s) the avatar should target given the active intent. Crouch and run
|
|
79
|
+
* take precedence over backpedal; a plain backward intent (`forward < 0`) slows to
|
|
80
|
+
* {@link MOVEMENT_TUNING.backpedalSpeedMultiplier} (overridable via `tuning`), while a
|
|
81
|
+
* pure strafe keeps full speed.
|
|
82
|
+
*/
|
|
83
|
+
function resolveTargetSpeed(intent, baseSpeed, tuning) {
|
|
84
|
+
const backpedal = tuning?.backpedalSpeedMultiplier ?? MOVEMENT_TUNING.backpedalSpeedMultiplier;
|
|
75
85
|
const speedMultiplier = intent.crouching
|
|
76
86
|
? MOVEMENT_TUNING.crouchSpeedMultiplier
|
|
77
87
|
: intent.running
|
|
78
88
|
? MOVEMENT_TUNING.runSpeedMultiplier
|
|
79
|
-
:
|
|
89
|
+
: intent.forward < 0
|
|
90
|
+
? backpedal
|
|
91
|
+
: 1;
|
|
80
92
|
return baseSpeed * MOVEMENT_TUNING.walkSpeedMultiplier * speedMultiplier;
|
|
81
93
|
}
|
|
94
|
+
/** @internal */
|
|
82
95
|
export function createPlayerMotionState() {
|
|
83
96
|
return {
|
|
84
97
|
horizontalVelocityX: 0,
|
|
@@ -98,10 +111,11 @@ export function createPlayerMotionState() {
|
|
|
98
111
|
* (need not be normalized); the avatar's right axis is derived from it. Pulling
|
|
99
112
|
* this out of the render loop is what lets us assert "held forward for N frames
|
|
100
113
|
* crosses the room" in a unit test instead of only in the live game.
|
|
101
|
-
|
|
102
|
-
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
export function advancePlayerMotion(motion, intent, forwardX, forwardZ, baseSpeed, rawDeltaSeconds, tuning, options) {
|
|
103
117
|
const deltaSeconds = Math.min(rawDeltaSeconds, MOVEMENT_TUNING.maxFrameSeconds);
|
|
104
|
-
const targetSpeed = resolveTargetSpeed(intent, baseSpeed);
|
|
118
|
+
const targetSpeed = resolveTargetSpeed(intent, baseSpeed, tuning) * (options?.speedScale ?? 1);
|
|
105
119
|
const gravityAcceleration = tuning?.gravityAcceleration ?? MOVEMENT_TUNING.gravityAcceleration;
|
|
106
120
|
const jumpVelocity = tuning?.jumpVelocity ?? MOVEMENT_TUNING.jumpVelocity;
|
|
107
121
|
let targetVelocityX = 0;
|
|
@@ -146,13 +160,19 @@ export function advancePlayerMotion(motion, intent, forwardX, forwardZ, baseSpee
|
|
|
146
160
|
motion.horizontalVelocityX *= friction;
|
|
147
161
|
motion.horizontalVelocityZ *= friction;
|
|
148
162
|
}
|
|
163
|
+
const floating = options?.floating === true;
|
|
149
164
|
const jumpPressed = intent.jumping;
|
|
150
|
-
if (jumpPressed && !motion.jumpHeld && motion.grounded && !intent.crouching) {
|
|
165
|
+
if (jumpPressed && !motion.jumpHeld && motion.grounded && !intent.crouching && !floating) {
|
|
151
166
|
motion.verticalVelocity = jumpVelocity;
|
|
152
167
|
motion.grounded = false;
|
|
153
168
|
}
|
|
154
169
|
motion.jumpHeld = jumpPressed;
|
|
155
|
-
if (
|
|
170
|
+
if (floating) {
|
|
171
|
+
motion.verticalVelocity = 0;
|
|
172
|
+
motion.jumpOffset = 0;
|
|
173
|
+
motion.grounded = true;
|
|
174
|
+
}
|
|
175
|
+
else if (!motion.grounded || motion.verticalVelocity > 0) {
|
|
156
176
|
motion.verticalVelocity -= gravityAcceleration * deltaSeconds;
|
|
157
177
|
motion.jumpOffset += motion.verticalVelocity * deltaSeconds;
|
|
158
178
|
if (motion.jumpOffset <= 0) {
|
|
@@ -167,7 +187,8 @@ export function advancePlayerMotion(motion, intent, forwardX, forwardZ, baseSpee
|
|
|
167
187
|
};
|
|
168
188
|
}
|
|
169
189
|
const DEFAULT_OBSTACLE_HALF_EXTENTS = [0.5, 0.5, 0.5];
|
|
170
|
-
|
|
190
|
+
/** @internal Player radius the walking obstruction inflates obstacles by; callers gather within reach of it. */
|
|
191
|
+
export const DEFAULT_OBSTACLE_PLAYER_RADIUS = 0.3;
|
|
171
192
|
/** Feet-to-head span used for the obstacle's vertical overlap test; matches DEFAULT_VOXEL_DIMS.height. */
|
|
172
193
|
const OBSTACLE_PLAYER_HEIGHT = 1.8;
|
|
173
194
|
function clampAxisStep(originalCoord, step, min, max) {
|
|
@@ -188,29 +209,47 @@ function clampAxisStep(originalCoord, step, min, max) {
|
|
|
188
209
|
* by `playerRadius`; an obstacle whose vertical span misses the player's
|
|
189
210
|
* feet-to-head span is skipped entirely. Callers should pre-filter to nearby
|
|
190
211
|
* objects — this also early-exits per obstacle on horizontal distance.
|
|
191
|
-
|
|
212
|
+
* @internal
|
|
213
|
+
*/
|
|
192
214
|
export function resolveObstacleStep(current, stepX, stepZ, obstacles, playerRadius = DEFAULT_OBSTACLE_PLAYER_RADIUS) {
|
|
193
215
|
const feetY = current[1];
|
|
194
216
|
const headY = feetY + OBSTACLE_PLAYER_HEIGHT;
|
|
195
217
|
const reachX = Math.abs(stepX) + playerRadius;
|
|
196
218
|
const reachZ = Math.abs(stepZ) + playerRadius;
|
|
197
219
|
const nearby = [];
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
if (Math.abs(
|
|
207
|
-
|
|
220
|
+
const considerBox = (minX, maxX, minY, maxY, minZ, maxZ) => {
|
|
221
|
+
// Vertical-span cull: a sub-box entirely above the head (walk under the lintel) or below the feet is skipped.
|
|
222
|
+
if (maxY <= feetY || minY >= headY)
|
|
223
|
+
return;
|
|
224
|
+
const centerX = (minX + maxX) / 2;
|
|
225
|
+
const centerZ = (minZ + maxZ) / 2;
|
|
226
|
+
const halfX = (maxX - minX) / 2;
|
|
227
|
+
const halfZ = (maxZ - minZ) / 2;
|
|
228
|
+
if (Math.abs(centerX - current[0]) > halfX + reachX || Math.abs(centerZ - current[2]) > halfZ + reachZ)
|
|
229
|
+
return;
|
|
208
230
|
nearby.push({
|
|
209
|
-
minX:
|
|
210
|
-
maxX:
|
|
211
|
-
minZ:
|
|
212
|
-
maxZ:
|
|
231
|
+
minX: minX - playerRadius,
|
|
232
|
+
maxX: maxX + playerRadius,
|
|
233
|
+
minZ: minZ - playerRadius,
|
|
234
|
+
maxZ: maxZ + playerRadius,
|
|
213
235
|
});
|
|
236
|
+
};
|
|
237
|
+
for (const obstacle of obstacles) {
|
|
238
|
+
const px = obstacle.position[0];
|
|
239
|
+
const py = obstacle.position[1];
|
|
240
|
+
const pz = obstacle.position[2];
|
|
241
|
+
if (obstacle.boxes !== undefined && obstacle.boxes.length > 0) {
|
|
242
|
+
for (const box of obstacle.boxes) {
|
|
243
|
+
considerBox(px + box.min[0], px + box.max[0], py + box.min[1], py + box.max[1], pz + box.min[2], pz + box.max[2]);
|
|
244
|
+
}
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
const halfExtents = obstacle.halfExtents ?? DEFAULT_OBSTACLE_HALF_EXTENTS;
|
|
248
|
+
const offset = obstacle.offset;
|
|
249
|
+
const cx = px + (offset !== undefined ? offset[0] : 0);
|
|
250
|
+
const cy = py + (offset !== undefined ? offset[1] : 0);
|
|
251
|
+
const cz = pz + (offset !== undefined ? offset[2] : 0);
|
|
252
|
+
considerBox(cx - halfExtents[0], cx + halfExtents[0], cy - halfExtents[1], cy + halfExtents[1], cz - halfExtents[2], cz + halfExtents[2]);
|
|
214
253
|
}
|
|
215
254
|
let resultX = stepX;
|
|
216
255
|
for (const box of nearby) {
|
|
@@ -228,7 +267,9 @@ export function resolveObstacleStep(current, stepX, stepZ, obstacles, playerRadi
|
|
|
228
267
|
return { stepX: resultX, stepZ: resultZ };
|
|
229
268
|
}
|
|
230
269
|
const OBSTACLE_GATHER_RADIUS = 3;
|
|
231
|
-
/** Placed objects within `radius` (XZ) of `center`, as {@link CollisionObstacle}s to pre-filter for {@link resolveObstacleStep}.
|
|
270
|
+
/** Placed objects within `radius` (XZ) of `center`, as {@link CollisionObstacle}s to pre-filter for {@link resolveObstacleStep}.
|
|
271
|
+
* @internal
|
|
272
|
+
*/
|
|
232
273
|
export function nearbyObstacles(objects, center, radius = OBSTACLE_GATHER_RADIUS) {
|
|
233
274
|
const radiusSq = radius * radius;
|
|
234
275
|
const result = [];
|
|
@@ -240,7 +281,9 @@ export function nearbyObstacles(objects, center, radius = OBSTACLE_GATHER_RADIUS
|
|
|
240
281
|
}
|
|
241
282
|
return result;
|
|
242
283
|
}
|
|
243
|
-
/** Zeroes the off-axis component so travel is locked to a single world axis (`PlayerMovementConfig.mode: "axis"`).
|
|
284
|
+
/** Zeroes the off-axis component so travel is locked to a single world axis (`PlayerMovementConfig.mode: "axis"`).
|
|
285
|
+
* @internal
|
|
286
|
+
*/
|
|
244
287
|
export function constrainStepToAxis(stepX, stepZ, axis) {
|
|
245
288
|
return axis === "x" ? { stepX, stepZ: 0 } : { stepX: 0, stepZ };
|
|
246
289
|
}
|
|
@@ -248,13 +291,16 @@ export function constrainStepToAxis(stepX, stepZ, axis) {
|
|
|
248
291
|
* Snap a world position to its containing cell's center, matching the
|
|
249
292
|
* bounds-free form of `navGrid`'s and `tacticalGrid`'s `floor` + half-cell
|
|
250
293
|
* convention (`PlayerMovementConfig.mode: "grid"`).
|
|
251
|
-
|
|
294
|
+
* @internal
|
|
295
|
+
*/
|
|
252
296
|
export function snapPositionToGrid(x, z, cellSize) {
|
|
253
297
|
return [(Math.floor(x / cellSize) + 0.5) * cellSize, (Math.floor(z / cellSize) + 0.5) * cellSize];
|
|
254
298
|
}
|
|
255
299
|
/** Peak jump height from MOVEMENT_TUNING.jumpVelocity + gravity, with small buffer. */
|
|
256
300
|
export const MAX_JUMP_OFFSET = 1.15;
|
|
257
|
-
/** Camera yaw looks along -Z; character mesh faces +Z at body rotation.y = 0.
|
|
301
|
+
/** Camera yaw looks along -Z; character mesh faces +Z at body rotation.y = 0.
|
|
302
|
+
* @internal
|
|
303
|
+
*/
|
|
258
304
|
export function cameraYawToAvatarBodyYaw(cameraYaw) {
|
|
259
305
|
return cameraYaw + Math.PI;
|
|
260
306
|
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { applyHorizontalImpulses, applyMotionImpulses } from "../runtime/motionIntents.js";
|
|
2
|
-
import { groundFieldFor, hasEnvironmentTerrain } from "../world/terrain.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { groundFieldFor, hasEnvironmentTerrain, sampleSlope } from "../world/terrain.js";
|
|
3
|
+
import { resolveColliders } from "../scene/colliders.js";
|
|
4
|
+
import { advancePlayerMotion, constrainStepToAxis, createEmptyMovementKeys, createPlayerMotionState, DEFAULT_OBSTACLE_PLAYER_RADIUS, resolveMovementIntent, resolveObstacleStep, snapPositionToGrid, } from "./movementModel.js";
|
|
5
|
+
import { approachYaw, steerYaw } from "./steering.js";
|
|
5
6
|
import { advanceVoxelPlayer, createVoxelPlayerBody, } from "./voxelController.js";
|
|
6
7
|
const DEFAULT_TURN_SPEED = 2.4;
|
|
7
8
|
const DEFAULT_WALK_SPEED = 2;
|
|
9
|
+
const DEFAULT_SWIM_SPEED_MULTIPLIER = 0.65;
|
|
10
|
+
/** Minimum ground-normal `y` the player can stand on before slope-slide kicks in — cos(50°) ≈ 0.643. */
|
|
11
|
+
const DEFAULT_MAX_CLIMB_NORMAL_Y = Math.cos((50 * Math.PI) / 180);
|
|
12
|
+
/** Downhill slide speed (units/s) per unit of slope steepness while on too-steep ground. */
|
|
13
|
+
const SLOPE_SLIDE_SPEED = 4;
|
|
8
14
|
/**
|
|
9
15
|
* Maps a game's declared `physics` onto the movement controllers' tuning. `PhysicsConfig.gravity` is a signed
|
|
10
16
|
* world acceleration (negative points down), but the controllers integrate `velocityY -= gravityAcceleration * dt`
|
|
@@ -25,10 +31,12 @@ export function resolvePhysicsTuning(physics) {
|
|
|
25
31
|
/** Gather a game's collision/movement/physics/world config into a {@link PlayerMovementTuning} — call once per world; both the shell and a host pass the result to {@link stepPlayerMovement}. */
|
|
26
32
|
export function resolvePlayerMovementTuning(opts) {
|
|
27
33
|
const physics = resolvePhysicsTuning(opts.physics);
|
|
34
|
+
const backpedal = opts.movement?.backpedalMult;
|
|
35
|
+
const overrides = backpedal === undefined ? physics : { ...(physics ?? {}), backpedalSpeedMultiplier: backpedal };
|
|
28
36
|
return {
|
|
29
37
|
...(opts.collision === undefined ? {} : { collision: opts.collision }),
|
|
30
38
|
...(opts.movement === undefined ? {} : { movement: opts.movement }),
|
|
31
|
-
...(
|
|
39
|
+
...(overrides === undefined ? {} : { physics: overrides }),
|
|
32
40
|
ground: groundFieldFor(opts.world),
|
|
33
41
|
hasTerrain: hasEnvironmentTerrain(opts.world),
|
|
34
42
|
};
|
|
@@ -45,7 +53,7 @@ function storeFor(ctx) {
|
|
|
45
53
|
function stateFor(store, userId) {
|
|
46
54
|
let state = store.players.get(userId);
|
|
47
55
|
if (state === undefined) {
|
|
48
|
-
state = { heading: 0, voxelBody: null, motion: null };
|
|
56
|
+
state = { heading: 0, facing: null, voxelBody: null, motion: null };
|
|
49
57
|
store.players.set(userId, state);
|
|
50
58
|
}
|
|
51
59
|
return state;
|
|
@@ -58,6 +66,25 @@ export function playerMovementHeading(ctx, userId) {
|
|
|
58
66
|
export function forgetPlayerMovement(ctx, userId) {
|
|
59
67
|
stores.get(ctx)?.players.delete(userId);
|
|
60
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Rendered body yaw to commit this frame. With `turnSpeed` unset the body snaps
|
|
71
|
+
* to its movement heading exactly as before (no opt-in, no behavior change); with
|
|
72
|
+
* `turnSpeed` set it rotates toward that heading at `turnSpeed` rad/s along the
|
|
73
|
+
* shortest arc, so strafing and backpedalling read as a turning body rather than
|
|
74
|
+
* an instant flip. Retained per player so the smoothing is continuous across frames.
|
|
75
|
+
*/
|
|
76
|
+
function resolveBodyFacing(state, moving, velocityX, velocityZ, fallbackYaw, turnSpeed, dt) {
|
|
77
|
+
if (turnSpeed === undefined) {
|
|
78
|
+
const snapped = moving ? Math.atan2(velocityX, velocityZ) : fallbackYaw;
|
|
79
|
+
state.facing = snapped;
|
|
80
|
+
return snapped;
|
|
81
|
+
}
|
|
82
|
+
const from = state.facing ?? fallbackYaw;
|
|
83
|
+
const target = moving ? Math.atan2(velocityX, velocityZ) : from;
|
|
84
|
+
const next = approachYaw(from, target, turnSpeed, dt);
|
|
85
|
+
state.facing = next;
|
|
86
|
+
return next;
|
|
87
|
+
}
|
|
61
88
|
/**
|
|
62
89
|
* Integrate one player's movement for a tick from their held-input frame and commit the pose — the single
|
|
63
90
|
* genre-agnostic controller both the shell (its local player) and a host (each connected player in `onTick`) call,
|
|
@@ -80,8 +107,9 @@ export function stepPlayerMovement(ctx, userId, input, dt, tuning, heading) {
|
|
|
80
107
|
}
|
|
81
108
|
else {
|
|
82
109
|
const turnInput = (isDown("turnRight") ? 1 : 0) - (isDown("turnLeft") ? 1 : 0);
|
|
110
|
+
const turnSpeed = tuning.movement?.turnSpeed ?? DEFAULT_TURN_SPEED;
|
|
83
111
|
if (turnInput !== 0)
|
|
84
|
-
state.heading = steerYaw(state.heading, turnInput,
|
|
112
|
+
state.heading = steerYaw(state.heading, turnInput, turnSpeed, dt);
|
|
85
113
|
}
|
|
86
114
|
const forwardX = Math.sin(state.heading);
|
|
87
115
|
const forwardZ = Math.cos(state.heading);
|
|
@@ -120,7 +148,7 @@ export function stepPlayerMovement(ctx, userId, input, dt, tuning, heading) {
|
|
|
120
148
|
body.y = motionBatch.y;
|
|
121
149
|
ctx.scene.entity.setPose(playerId, {
|
|
122
150
|
position: [body.x, body.y, body.z],
|
|
123
|
-
rotationY: intent.moving
|
|
151
|
+
rotationY: resolveBodyFacing(state, intent.moving, body.velocityX, body.velocityZ, player.rotationY, tuning.movement?.turnSpeed, dt),
|
|
124
152
|
dt,
|
|
125
153
|
});
|
|
126
154
|
return;
|
|
@@ -132,7 +160,19 @@ export function stepPlayerMovement(ctx, userId, input, dt, tuning, heading) {
|
|
|
132
160
|
}
|
|
133
161
|
motion.verticalVelocity = applyMotionImpulses(motion.verticalVelocity, motionBatch);
|
|
134
162
|
[motion.horizontalVelocityX, motion.horizontalVelocityZ] = applyHorizontalImpulses(motion.horizontalVelocityX, motion.horizontalVelocityZ, motionBatch);
|
|
135
|
-
const
|
|
163
|
+
const swimCfg = tuning.movement?.swim;
|
|
164
|
+
const swimEnabled = swimCfg === true || (typeof swimCfg === "object" && swimCfg !== null);
|
|
165
|
+
const swimSpeedMultiplier = typeof swimCfg === "object" && swimCfg !== null
|
|
166
|
+
? swimCfg.speedMultiplier ?? DEFAULT_SWIM_SPEED_MULTIPLIER
|
|
167
|
+
: DEFAULT_SWIM_SPEED_MULTIPLIER;
|
|
168
|
+
const waterLevel = tuning.ground.waterLevel;
|
|
169
|
+
const submerged = swimEnabled &&
|
|
170
|
+
waterLevel !== undefined &&
|
|
171
|
+
tuning.ground.sampleHeight(player.position[0], player.position[2]) < waterLevel;
|
|
172
|
+
const motionOptions = submerged
|
|
173
|
+
? { speedScale: swimSpeedMultiplier, floating: true }
|
|
174
|
+
: undefined;
|
|
175
|
+
const step = advancePlayerMotion(motion, intent, forwardX, forwardZ, walkSpeed, dt, tuning.physics, motionOptions);
|
|
136
176
|
let stepX = step.stepX;
|
|
137
177
|
let stepZ = step.stepZ;
|
|
138
178
|
if (tuning.movement?.mode === "axis") {
|
|
@@ -141,7 +181,7 @@ export function stepPlayerMovement(ctx, userId, input, dt, tuning, heading) {
|
|
|
141
181
|
stepZ = constrained.stepZ;
|
|
142
182
|
}
|
|
143
183
|
if (tuning.movement?.collideObjects === true) {
|
|
144
|
-
const obstacles =
|
|
184
|
+
const obstacles = gatherMovementObstacles(ctx, player.position, stepX, stepZ);
|
|
145
185
|
const resolved = resolveObstacleStep(player.position, stepX, stepZ, obstacles);
|
|
146
186
|
stepX = resolved.stepX;
|
|
147
187
|
stepZ = resolved.stepZ;
|
|
@@ -153,10 +193,26 @@ export function stepPlayerMovement(ctx, userId, input, dt, tuning, heading) {
|
|
|
153
193
|
nextX = snapped[0];
|
|
154
194
|
nextZ = snapped[1];
|
|
155
195
|
}
|
|
156
|
-
|
|
196
|
+
const slideCfg = tuning.movement?.slopeSlide;
|
|
197
|
+
if (slideCfg === true || (typeof slideCfg === "object" && slideCfg !== null)) {
|
|
198
|
+
const maxClimbNormalY = typeof slideCfg === "object" && slideCfg.maxClimbSlope !== undefined
|
|
199
|
+
? slideCfg.maxClimbSlope
|
|
200
|
+
: DEFAULT_MAX_CLIMB_NORMAL_Y;
|
|
201
|
+
if (tuning.ground.sampleNormal(nextX, nextZ)[1] < maxClimbNormalY) {
|
|
202
|
+
const slope = sampleSlope(tuning.ground, nextX, nextZ);
|
|
203
|
+
const slide = SLOPE_SLIDE_SPEED * slope.steepness * dt;
|
|
204
|
+
nextX += slope.downhill[0] * slide;
|
|
205
|
+
nextZ += slope.downhill[1] * slide;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const groundAtNext = tuning.ground.sampleHeight(nextX, nextZ);
|
|
209
|
+
let nextY = groundAtNext + motion.jumpOffset;
|
|
157
210
|
if (motionBatch !== null && motionBatch.y !== null) {
|
|
158
211
|
nextY = motionBatch.y;
|
|
159
|
-
motion.jumpOffset = motionBatch.y -
|
|
212
|
+
motion.jumpOffset = motionBatch.y - groundAtNext;
|
|
213
|
+
}
|
|
214
|
+
else if (swimEnabled && waterLevel !== undefined && groundAtNext < waterLevel) {
|
|
215
|
+
nextY = waterLevel;
|
|
160
216
|
}
|
|
161
217
|
if (tuning.movement?.beforeCommit !== undefined) {
|
|
162
218
|
const frame = {
|
|
@@ -175,7 +231,106 @@ export function stepPlayerMovement(ctx, userId, input, dt, tuning, heading) {
|
|
|
175
231
|
}
|
|
176
232
|
ctx.scene.entity.setPose(playerId, {
|
|
177
233
|
position: [nextX, nextY, nextZ],
|
|
178
|
-
rotationY: intent.moving
|
|
234
|
+
rotationY: resolveBodyFacing(state, intent.moving, motion.horizontalVelocityX, motion.horizontalVelocityZ, player.rotationY, tuning.movement?.turnSpeed, dt),
|
|
179
235
|
dt,
|
|
180
236
|
});
|
|
181
237
|
}
|
|
238
|
+
/** Feet-to-head span the obstruction test uses; matches `movementModel`'s `OBSTACLE_PLAYER_HEIGHT`. */
|
|
239
|
+
const OBSTACLE_PLAYER_HEIGHT = 1.8;
|
|
240
|
+
/**
|
|
241
|
+
* Largest collider half-extent the bounded broadphase assumes, so an object whose blocking box reaches
|
|
242
|
+
* the player still has its center inside the `inBox` query — a ~4m wall (half-extent ~2m) is caught. An
|
|
243
|
+
* object wider than this on an axis could be missed at its far edge; raise it if a wider blocker exists.
|
|
244
|
+
*/
|
|
245
|
+
const OBSTACLE_MAX_HALF_EXTENT = 4;
|
|
246
|
+
/**
|
|
247
|
+
* Gather the player's nearby blocking obstacles from resolved colliders — the mesh-accurate replacement
|
|
248
|
+
* for the old `nearbyObstacles(list(), …)` which emitted a default 1×1×1 box per object. Bounded by an
|
|
249
|
+
* `inBox` broadphase (reach ≥ player radius + max half-extent so wide walls can't be missed), then, per
|
|
250
|
+
* candidate, keeps only blocking physical colliders and emits their real half-extents/offset (or, for a
|
|
251
|
+
* mesh collider carrying `boxes`, the compound sub-boxes), conservatively yaw-rotated by the object's
|
|
252
|
+
* `rotationY`. Objects with no resolved collider fall back to the default box; objects whose colliders
|
|
253
|
+
* don't block stop obstructing. Runs for both the shell's local player and a host, so parity is automatic.
|
|
254
|
+
*/
|
|
255
|
+
function gatherMovementObstacles(ctx, position, stepX, stepZ) {
|
|
256
|
+
const reachX = Math.abs(stepX) + DEFAULT_OBSTACLE_PLAYER_RADIUS + OBSTACLE_MAX_HALF_EXTENT;
|
|
257
|
+
const reachZ = Math.abs(stepZ) + DEFAULT_OBSTACLE_PLAYER_RADIUS + OBSTACLE_MAX_HALF_EXTENT;
|
|
258
|
+
const min = [
|
|
259
|
+
position[0] - reachX,
|
|
260
|
+
position[1] - OBSTACLE_MAX_HALF_EXTENT,
|
|
261
|
+
position[2] - reachZ,
|
|
262
|
+
];
|
|
263
|
+
const max = [
|
|
264
|
+
position[0] + reachX,
|
|
265
|
+
position[1] + OBSTACLE_PLAYER_HEIGHT + OBSTACLE_MAX_HALF_EXTENT,
|
|
266
|
+
position[2] + reachZ,
|
|
267
|
+
];
|
|
268
|
+
const obstacles = [];
|
|
269
|
+
for (const object of ctx.scene.object.inBox(min, max)) {
|
|
270
|
+
const set = ctx.scene.object.collidersOf(object.instanceId);
|
|
271
|
+
if (set === null) {
|
|
272
|
+
// No resolved collider: preserve today's default 1×1×1 box.
|
|
273
|
+
obstacles.push({ position: object.position });
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
for (const collider of resolveColliders(set)) {
|
|
277
|
+
if (!collider.blocks || collider.purpose !== "physical")
|
|
278
|
+
continue;
|
|
279
|
+
obstacles.push(obstacleFromCollider(collider, object.position, object.rotationY));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return obstacles;
|
|
283
|
+
}
|
|
284
|
+
/** One blocking collider as a {@link CollisionObstacle}: a compound `boxes` obstacle for a mesh collider
|
|
285
|
+
* carrying sub-boxes, else a single half-extents/offset AABB. Yaw is applied by conservatively expanding
|
|
286
|
+
* each AABB to its rotated extent (mirroring `worldOffset`), so the obstruction never under-covers. */
|
|
287
|
+
function obstacleFromCollider(collider, position, rotationY) {
|
|
288
|
+
const cos = Math.cos(rotationY);
|
|
289
|
+
const sin = Math.sin(rotationY);
|
|
290
|
+
const shape = collider.shape;
|
|
291
|
+
if (shape.kind === "mesh" && shape.boxes !== undefined && shape.boxes.length > 0) {
|
|
292
|
+
return {
|
|
293
|
+
position,
|
|
294
|
+
boxes: shape.boxes.map((b) => yawExpandLocalBox(b.min, b.max, cos, sin)),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
let hx;
|
|
298
|
+
let hy;
|
|
299
|
+
let hz;
|
|
300
|
+
if (shape.kind === "sphere") {
|
|
301
|
+
hx = hy = hz = shape.radius;
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
hx = shape.halfExtents[0];
|
|
305
|
+
hy = shape.halfExtents[1];
|
|
306
|
+
hz = shape.halfExtents[2];
|
|
307
|
+
}
|
|
308
|
+
const offset = shape.offset;
|
|
309
|
+
const ox = offset !== undefined ? offset[0] : 0;
|
|
310
|
+
const oy = offset !== undefined ? offset[1] : 0;
|
|
311
|
+
const oz = offset !== undefined ? offset[2] : 0;
|
|
312
|
+
return {
|
|
313
|
+
position,
|
|
314
|
+
// Rotate the offset by yaw (mirror of colliders.worldOffset), expand the extents to the rotated AABB.
|
|
315
|
+
offset: [ox * cos + oz * sin, oy, -ox * sin + oz * cos],
|
|
316
|
+
halfExtents: [Math.abs(hx * cos) + Math.abs(hz * sin), hy, Math.abs(hx * sin) + Math.abs(hz * cos)],
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
/** Yaw-rotate an entity-local AABB about the object origin and re-fit it to an axis-aligned box, expressed
|
|
320
|
+
* as `min`/`max` relative to `position`. Conservative: the rotated box is grown to its enclosing AABB. */
|
|
321
|
+
function yawExpandLocalBox(boxMin, boxMax, cos, sin) {
|
|
322
|
+
const centerX = (boxMin[0] + boxMax[0]) / 2;
|
|
323
|
+
const centerY = (boxMin[1] + boxMax[1]) / 2;
|
|
324
|
+
const centerZ = (boxMin[2] + boxMax[2]) / 2;
|
|
325
|
+
const halfX = (boxMax[0] - boxMin[0]) / 2;
|
|
326
|
+
const halfY = (boxMax[1] - boxMin[1]) / 2;
|
|
327
|
+
const halfZ = (boxMax[2] - boxMin[2]) / 2;
|
|
328
|
+
const rcX = centerX * cos + centerZ * sin;
|
|
329
|
+
const rcZ = -centerX * sin + centerZ * cos;
|
|
330
|
+
const rhX = Math.abs(halfX * cos) + Math.abs(halfZ * sin);
|
|
331
|
+
const rhZ = Math.abs(halfX * sin) + Math.abs(halfZ * cos);
|
|
332
|
+
return {
|
|
333
|
+
min: [rcX - rhX, centerY - halfY, rcZ - rhZ],
|
|
334
|
+
max: [rcX + rhX, centerY + halfY, rcZ + rhZ],
|
|
335
|
+
};
|
|
336
|
+
}
|
|
@@ -13,11 +13,24 @@ export interface PoseAllowedStates {
|
|
|
13
13
|
export interface PoseRejection {
|
|
14
14
|
reason: string;
|
|
15
15
|
}
|
|
16
|
+
export interface PoseSnapshot {
|
|
17
|
+
poses: Record<string, MovementPose>;
|
|
18
|
+
aims: Record<string, AimMode>;
|
|
19
|
+
}
|
|
16
20
|
export interface PoseState {
|
|
17
21
|
getPose(instanceId: string): MovementPose;
|
|
18
22
|
setPose(instanceId: string, pose: MovementPose): PoseRejection | null;
|
|
19
23
|
getAim(instanceId: string): AimMode;
|
|
20
24
|
setAim(instanceId: string, mode: AimMode): PoseRejection | null;
|
|
21
25
|
clear(instanceId: string): void;
|
|
26
|
+
/** Snapshot every entity's pose and aim for a whole-world save. */
|
|
27
|
+
snapshotAll(): PoseSnapshot;
|
|
28
|
+
/** Restore every entity's pose and aim from a {@link snapshotAll} payload. */
|
|
29
|
+
hydrateAll(state: PoseSnapshot): void;
|
|
22
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Stance/pose transitions — stand, crouch, prone — that change the hitbox and movement.
|
|
33
|
+
*
|
|
34
|
+
* @capability crouch-prone stance/pose transitions that change the hitbox
|
|
35
|
+
*/
|
|
23
36
|
export declare function createPoseState(resolveAllowed: (instanceId: string) => PoseAllowedStates | null | undefined): PoseState;
|
|
@@ -23,6 +23,11 @@ export const POSE_HITBOX = {
|
|
|
23
23
|
speedMultiplier: MOVEMENT_TUNING.runSpeedMultiplier,
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* Stance/pose transitions — stand, crouch, prone — that change the hitbox and movement.
|
|
28
|
+
*
|
|
29
|
+
* @capability crouch-prone stance/pose transitions that change the hitbox
|
|
30
|
+
*/
|
|
26
31
|
export function createPoseState(resolveAllowed) {
|
|
27
32
|
const poses = new Map();
|
|
28
33
|
const aims = new Map();
|
|
@@ -57,5 +62,16 @@ export function createPoseState(resolveAllowed) {
|
|
|
57
62
|
poses.delete(instanceId);
|
|
58
63
|
aims.delete(instanceId);
|
|
59
64
|
},
|
|
65
|
+
snapshotAll() {
|
|
66
|
+
return { poses: Object.fromEntries(poses), aims: Object.fromEntries(aims) };
|
|
67
|
+
},
|
|
68
|
+
hydrateAll(state) {
|
|
69
|
+
poses.clear();
|
|
70
|
+
for (const [id, pose] of Object.entries(state.poses))
|
|
71
|
+
poses.set(id, pose);
|
|
72
|
+
aims.clear();
|
|
73
|
+
for (const [id, aim] of Object.entries(state.aims))
|
|
74
|
+
aims.set(id, aim);
|
|
75
|
+
},
|
|
60
76
|
};
|
|
61
77
|
}
|
|
@@ -25,3 +25,11 @@ export declare function steerYaw(yaw: number, steerRight: number, turnRatePerSec
|
|
|
25
25
|
* it into [-1, 1] at the call site.
|
|
26
26
|
*/
|
|
27
27
|
export declare function steerToward(yaw: number, desiredYaw: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* @internal Rotate `yaw` toward `targetYaw` by at most `turnRatePerSecond * dt`
|
|
30
|
+
* radians, always along the shortest arc, snapping exactly onto the target once
|
|
31
|
+
* within a single step so it converges without overshoot or jitter — the
|
|
32
|
+
* smoothing behind a rendered body-turn (`PlayerMovementConfig.turnSpeed`). A
|
|
33
|
+
* large enough rate (or `dt`) reaches the target in one call, matching a snap.
|
|
34
|
+
*/
|
|
35
|
+
export declare function approachYaw(yaw: number, targetYaw: number, turnRatePerSecond: number, dt: number): number;
|