@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
|
@@ -11,6 +11,7 @@ function isLeaderboardIncrement(value) {
|
|
|
11
11
|
typeof candidate.by === "number" &&
|
|
12
12
|
(candidate.serverId === undefined || typeof candidate.serverId === "string"));
|
|
13
13
|
}
|
|
14
|
+
/** @internal */
|
|
14
15
|
export function drainPendingLeaderboardIncrements(session) {
|
|
15
16
|
const raw = session[LEADERBOARD_PENDING_KEY];
|
|
16
17
|
if (!Array.isArray(raw) || raw.length === 0) {
|
|
@@ -21,15 +22,18 @@ export function drainPendingLeaderboardIncrements(session) {
|
|
|
21
22
|
return { increments: raw.filter(isLeaderboardIncrement), session: rest };
|
|
22
23
|
}
|
|
23
24
|
export const LEADERBOARD_TOP_LIMIT = 100;
|
|
25
|
+
/** @internal */
|
|
24
26
|
export function clampLimit(value, fallback, max) {
|
|
25
27
|
const candidate = value ?? fallback;
|
|
26
28
|
if (!Number.isFinite(candidate))
|
|
27
29
|
return fallback;
|
|
28
30
|
return Math.min(Math.max(Math.floor(candidate), 1), max);
|
|
29
31
|
}
|
|
32
|
+
/** @internal */
|
|
30
33
|
export function leaderboardRowKey(row) {
|
|
31
34
|
return [row.gameId, row.scope, row.stat, row.serverId ?? "", row.userId].join("|");
|
|
32
35
|
}
|
|
36
|
+
/** @internal */
|
|
33
37
|
export function applyLeaderboardRows(rows, gameId, entries, now) {
|
|
34
38
|
for (const entry of entries) {
|
|
35
39
|
const key = leaderboardRowKey({ ...entry, gameId });
|
|
@@ -50,6 +54,7 @@ export function applyLeaderboardRows(rows, gameId, entries, now) {
|
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
}
|
|
57
|
+
/** @internal */
|
|
53
58
|
export function topLeaderboardRows(rows, args) {
|
|
54
59
|
const limit = clampLimit(args.limit, LEADERBOARD_TOP_LIMIT, LEADERBOARD_TOP_LIMIT);
|
|
55
60
|
return [...rows]
|
|
@@ -61,6 +66,7 @@ export function topLeaderboardRows(rows, args) {
|
|
|
61
66
|
.slice(0, limit)
|
|
62
67
|
.map((row) => ({ userId: row.userId, value: row.value }));
|
|
63
68
|
}
|
|
69
|
+
/** @internal */
|
|
64
70
|
export function profileLeaderboardStats(rows, gameId, userId) {
|
|
65
71
|
const profile = {};
|
|
66
72
|
for (const row of rows) {
|
|
@@ -71,11 +77,13 @@ export function profileLeaderboardStats(rows, gameId, userId) {
|
|
|
71
77
|
return profile;
|
|
72
78
|
}
|
|
73
79
|
export const FEED_RING_LIMIT = 20;
|
|
80
|
+
/** @internal */
|
|
74
81
|
export function trimFeedEntries(entries, limit = FEED_RING_LIMIT) {
|
|
75
82
|
if (entries.length <= limit)
|
|
76
83
|
return entries;
|
|
77
84
|
return entries.slice(entries.length - limit);
|
|
78
85
|
}
|
|
86
|
+
/** @internal */
|
|
79
87
|
export function shouldAutoSave(save, dirtyAt, lastSavedAt, now) {
|
|
80
88
|
if (!isSaveEnabled(save))
|
|
81
89
|
return false;
|
|
@@ -85,6 +93,7 @@ export function shouldAutoSave(save, dirtyAt, lastSavedAt, now) {
|
|
|
85
93
|
const anchor = lastSavedAt ?? 0;
|
|
86
94
|
return now - anchor >= intervalMs;
|
|
87
95
|
}
|
|
96
|
+
/** @internal */
|
|
88
97
|
export function toServerListing(record, options = {}) {
|
|
89
98
|
return {
|
|
90
99
|
serverId: record.serverId,
|
|
@@ -103,12 +112,14 @@ export function toServerListing(record, options = {}) {
|
|
|
103
112
|
}
|
|
104
113
|
export const OPEN_SERVER_LISTING_LIMIT = 20;
|
|
105
114
|
export const OPEN_SERVER_LISTING_MAX = 100;
|
|
115
|
+
/** @internal */
|
|
106
116
|
export function toOpenServerListings(listings, limit = OPEN_SERVER_LISTING_LIMIT) {
|
|
107
117
|
return [...listings]
|
|
108
118
|
.filter((listing) => listing.status === "running")
|
|
109
119
|
.sort((a, b) => b.updatedAt - a.updatedAt)
|
|
110
120
|
.slice(0, clampLimit(limit, OPEN_SERVER_LISTING_LIMIT, OPEN_SERVER_LISTING_MAX));
|
|
111
121
|
}
|
|
122
|
+
/** @internal */
|
|
112
123
|
export function buildHydratePlayers(server, profiles) {
|
|
113
124
|
const players = {};
|
|
114
125
|
for (const userId of server.memberUserIds) {
|
|
@@ -129,6 +140,7 @@ export function buildHydratePlayers(server, profiles) {
|
|
|
129
140
|
}
|
|
130
141
|
return players;
|
|
131
142
|
}
|
|
143
|
+
/** @internal */
|
|
132
144
|
export function planServerPersist(server, snapshot, save, now) {
|
|
133
145
|
const drained = drainPendingLeaderboardIncrements(snapshot.server.session);
|
|
134
146
|
const serverState = drained.increments.length > 0 ? { ...snapshot.server, session: drained.session } : snapshot.server;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { GameServerStatus, SessionVisibility } from "./hostPersistence.js";
|
|
2
|
+
/**
|
|
3
|
+
* True when a server's `visibility` should surface in public listings / browse results.
|
|
4
|
+
* @capability host-listing-filter exclude private sessions from public browse results
|
|
5
|
+
*/
|
|
6
|
+
export declare function isListablePublicly(visibility: SessionVisibility | undefined): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Private-server join-code gate. Existing members always pass; non-members must present a
|
|
9
|
+
* matching `joinCode` (loose-normalized via {@link normalizeJoinCode}). Callers still decide
|
|
10
|
+
* whether the server is private — this only answers the code/membership half.
|
|
11
|
+
* @capability host-join-code-gate membership-or-code gate for private hosted servers
|
|
12
|
+
*/
|
|
13
|
+
export declare function canJoinPrivateServer(args: {
|
|
14
|
+
isMember: boolean;
|
|
15
|
+
joinCode: string | undefined;
|
|
16
|
+
suppliedCode: string | undefined;
|
|
17
|
+
}): boolean;
|
|
18
|
+
/** Whether `userId` is already on the server's member roster. */
|
|
19
|
+
export declare function isServerMember(memberUserIds: readonly string[], userId: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* True when the server has no free slots for a non-member. Existing members never count as
|
|
22
|
+
* "full" so rejoin/leave cycles keep working.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isServerFull(memberUserIds: readonly string[], slotsPerServer: number, userId: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Whether a private-visibility server blocks this join (non-member without a matching code).
|
|
27
|
+
* Public / undefined visibility never blocks.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isPrivateJoinBlocked(args: {
|
|
30
|
+
visibility: SessionVisibility | undefined;
|
|
31
|
+
memberUserIds: readonly string[];
|
|
32
|
+
userId: string;
|
|
33
|
+
joinCode: string | undefined;
|
|
34
|
+
suppliedCode: string | undefined;
|
|
35
|
+
}): boolean;
|
|
36
|
+
/** Roster after a successful join: unchanged when already a member, else appended. */
|
|
37
|
+
export declare function withJoinedMember(memberUserIds: readonly string[], userId: string): string[];
|
|
38
|
+
/** Roster after a leave: `userId` removed; order of remaining members preserved. */
|
|
39
|
+
export declare function withoutMember(memberUserIds: readonly string[], userId: string): string[];
|
|
40
|
+
/** Status after a leave: empty rooms reopen; non-empty rooms keep their current status. */
|
|
41
|
+
export declare function statusAfterLeave(remainingMemberCount: number, currentStatus: GameServerStatus): GameServerStatus;
|
|
42
|
+
/**
|
|
43
|
+
* Auto-match candidate when no `serverId` is supplied: already a member, or a public room with
|
|
44
|
+
* free capacity. Private rooms are never auto-picked (join-by-code / direct id only).
|
|
45
|
+
*/
|
|
46
|
+
export declare function isAutoJoinCandidate(args: {
|
|
47
|
+
memberUserIds: readonly string[];
|
|
48
|
+
slotsPerServer: number;
|
|
49
|
+
visibility: SessionVisibility | undefined;
|
|
50
|
+
userId: string;
|
|
51
|
+
}): boolean;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { normalizeJoinCode } from "../multiplayer/matchmaking.js";
|
|
2
|
+
/**
|
|
3
|
+
* True when a server's `visibility` should surface in public listings / browse results.
|
|
4
|
+
* @capability host-listing-filter exclude private sessions from public browse results
|
|
5
|
+
*/
|
|
6
|
+
export function isListablePublicly(visibility) {
|
|
7
|
+
return (visibility ?? "public") !== "private";
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Private-server join-code gate. Existing members always pass; non-members must present a
|
|
11
|
+
* matching `joinCode` (loose-normalized via {@link normalizeJoinCode}). Callers still decide
|
|
12
|
+
* whether the server is private — this only answers the code/membership half.
|
|
13
|
+
* @capability host-join-code-gate membership-or-code gate for private hosted servers
|
|
14
|
+
*/
|
|
15
|
+
export function canJoinPrivateServer(args) {
|
|
16
|
+
if (args.isMember)
|
|
17
|
+
return true;
|
|
18
|
+
if (args.joinCode === undefined || args.suppliedCode === undefined)
|
|
19
|
+
return false;
|
|
20
|
+
return normalizeJoinCode(args.suppliedCode) === normalizeJoinCode(args.joinCode);
|
|
21
|
+
}
|
|
22
|
+
/** Whether `userId` is already on the server's member roster. */
|
|
23
|
+
export function isServerMember(memberUserIds, userId) {
|
|
24
|
+
return memberUserIds.includes(userId);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* True when the server has no free slots for a non-member. Existing members never count as
|
|
28
|
+
* "full" so rejoin/leave cycles keep working.
|
|
29
|
+
*/
|
|
30
|
+
export function isServerFull(memberUserIds, slotsPerServer, userId) {
|
|
31
|
+
return memberUserIds.length >= slotsPerServer && !memberUserIds.includes(userId);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether a private-visibility server blocks this join (non-member without a matching code).
|
|
35
|
+
* Public / undefined visibility never blocks.
|
|
36
|
+
*/
|
|
37
|
+
export function isPrivateJoinBlocked(args) {
|
|
38
|
+
if ((args.visibility ?? "public") !== "private")
|
|
39
|
+
return false;
|
|
40
|
+
return !canJoinPrivateServer({
|
|
41
|
+
isMember: isServerMember(args.memberUserIds, args.userId),
|
|
42
|
+
joinCode: args.joinCode,
|
|
43
|
+
suppliedCode: args.suppliedCode,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** Roster after a successful join: unchanged when already a member, else appended. */
|
|
47
|
+
export function withJoinedMember(memberUserIds, userId) {
|
|
48
|
+
return memberUserIds.includes(userId) ? [...memberUserIds] : [...memberUserIds, userId];
|
|
49
|
+
}
|
|
50
|
+
/** Roster after a leave: `userId` removed; order of remaining members preserved. */
|
|
51
|
+
export function withoutMember(memberUserIds, userId) {
|
|
52
|
+
return memberUserIds.filter((id) => id !== userId);
|
|
53
|
+
}
|
|
54
|
+
/** Status after a leave: empty rooms reopen; non-empty rooms keep their current status. */
|
|
55
|
+
export function statusAfterLeave(remainingMemberCount, currentStatus) {
|
|
56
|
+
return remainingMemberCount === 0 ? "open" : currentStatus;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Auto-match candidate when no `serverId` is supplied: already a member, or a public room with
|
|
60
|
+
* free capacity. Private rooms are never auto-picked (join-by-code / direct id only).
|
|
61
|
+
*/
|
|
62
|
+
export function isAutoJoinCandidate(args) {
|
|
63
|
+
if (isServerMember(args.memberUserIds, args.userId))
|
|
64
|
+
return true;
|
|
65
|
+
if (args.memberUserIds.length >= args.slotsPerServer)
|
|
66
|
+
return false;
|
|
67
|
+
return isListablePublicly(args.visibility);
|
|
68
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { CommandResult } from "../commands/commandRegistry.js";
|
|
2
2
|
import type { GameDefinition, LoopPlayer } from "../game/defineGame.js";
|
|
3
3
|
import type { ModelAssetRef } from "../scene/assetCatalog.js";
|
|
4
|
-
import { type GameContext, type GameContextContent } from "./gameContext.js";
|
|
4
|
+
import { type GameContext, type GameContextContent, type GameContextModels } from "./gameContext.js";
|
|
5
5
|
import { type InputFrame } from "./inputSnapshot.js";
|
|
6
6
|
import { type WorldDiff } from "./worldReplication.js";
|
|
7
|
-
import type { WorldSnapshot } from "./worldSnapshot.js";
|
|
7
|
+
import type { SnapshotViewer, WorldSnapshot } from "./worldSnapshot.js";
|
|
8
8
|
export type { InputFrame };
|
|
9
9
|
/** Reserved command name the authoritative host intercepts on the existing `runCommand` transport to route a client's {@link InputFrame} to `session.input`, so per-tick input needs no separate wire. */
|
|
10
10
|
export declare const INPUT_COMMAND = "engine.input";
|
|
@@ -21,6 +21,8 @@ export interface HostedGameRunnerOptions<TAssetRef extends ModelAssetRef, TMulti
|
|
|
21
21
|
* snapshot overlays the world state it seeded. Omit for a long-lived stateful host (ws) that keeps one runner.
|
|
22
22
|
*/
|
|
23
23
|
restore?: WorldSnapshot;
|
|
24
|
+
/** Render-model lookup for collider auto-fit — pass the same lookup the shell derives from `entityModels`/`objectModels` so host and clients resolve identical hitboxes. */
|
|
25
|
+
models?: GameContextModels;
|
|
24
26
|
}
|
|
25
27
|
/**
|
|
26
28
|
* The GameContext-loop equivalent of the pure-reducer `createGameHost`: one authoritative `createGameContext`
|
|
@@ -41,9 +43,14 @@ export interface HostedGameRunner {
|
|
|
41
43
|
tick(dt: number): number;
|
|
42
44
|
diff(sinceRevision: number): WorldDiff;
|
|
43
45
|
revision(): number;
|
|
44
|
-
|
|
46
|
+
/** The full world baseline — projected to only what `viewer` may see when the context carries a replication policy, else the whole world. */
|
|
47
|
+
snapshot(viewer?: SnapshotViewer): WorldSnapshot;
|
|
48
|
+
/** True when {@link snapshot} is viewer-dependent (a replication policy projects private/AOI state); a host must then serve each viewer its own frame. */
|
|
49
|
+
projectsViewers(): boolean;
|
|
45
50
|
members(): readonly string[];
|
|
46
51
|
context(): GameContext;
|
|
47
52
|
}
|
|
48
|
-
/** Build a {@link HostedGameRunner} — one authoritative GameContext world driven server-side from the game's own loop.
|
|
53
|
+
/** Build a {@link HostedGameRunner} — one authoritative GameContext world driven server-side from the game's own loop.
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
49
56
|
export declare function createHostedGameRunner<TAssetRef extends ModelAssetRef, TMultiplayer>(options: HostedGameRunnerOptions<TAssetRef, TMultiplayer>): HostedGameRunner;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { syncLifecyclePhase } from "../game/gamePhase.js";
|
|
2
|
+
import { advanceBehaviors } from "../scene/behaviorRuntime.js";
|
|
1
3
|
import { createGameContext } from "./gameContext.js";
|
|
2
4
|
import {} from "./inputSnapshot.js";
|
|
3
5
|
import { createWorldReplicator } from "./worldReplication.js";
|
|
4
6
|
/** Reserved command name the authoritative host intercepts on the existing `runCommand` transport to route a client's {@link InputFrame} to `session.input`, so per-tick input needs no separate wire. */
|
|
5
7
|
export const INPUT_COMMAND = "engine.input";
|
|
6
|
-
/** Build a {@link HostedGameRunner} — one authoritative GameContext world driven server-side from the game's own loop.
|
|
8
|
+
/** Build a {@link HostedGameRunner} — one authoritative GameContext world driven server-side from the game's own loop.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
7
11
|
export function createHostedGameRunner(options) {
|
|
8
12
|
const { definition, content, host, now, restore } = options;
|
|
9
13
|
const ctx = createGameContext({
|
|
@@ -11,20 +15,29 @@ export function createHostedGameRunner(options) {
|
|
|
11
15
|
content,
|
|
12
16
|
player: host ?? { userId: "host", isNew: true },
|
|
13
17
|
...(now === undefined ? {} : { now }),
|
|
18
|
+
...(definition.replication === undefined ? {} : { replication: definition.replication }),
|
|
19
|
+
...(options.models === undefined ? {} : { models: options.models }),
|
|
14
20
|
});
|
|
15
21
|
const loop = definition.loop ?? {};
|
|
16
|
-
const replicator = createWorldReplicator(() => ctx.snapshot()
|
|
22
|
+
const replicator = createWorldReplicator(() => ctx.snapshot(), {
|
|
23
|
+
worldVersion: () => ctx.replicationVersion(),
|
|
24
|
+
});
|
|
17
25
|
const members = new Map();
|
|
18
26
|
const inputs = new Map();
|
|
27
|
+
const inputSeq = new Map();
|
|
19
28
|
loop.onInit?.(ctx);
|
|
29
|
+
syncLifecyclePhase(ctx, definition.lifecycle);
|
|
20
30
|
if (restore !== undefined)
|
|
21
31
|
ctx.hydrate(restore);
|
|
22
32
|
return {
|
|
23
33
|
join(userId, isNew) {
|
|
34
|
+
if (members.has(userId))
|
|
35
|
+
return;
|
|
24
36
|
const player = { userId, isNew };
|
|
25
37
|
members.set(userId, player);
|
|
26
38
|
ctx.game.players?.join(userId, isNew);
|
|
27
39
|
loop.onNewPlayer?.(ctx, player);
|
|
40
|
+
syncLifecyclePhase(ctx, definition.lifecycle);
|
|
28
41
|
},
|
|
29
42
|
resume(userId) {
|
|
30
43
|
members.set(userId, { userId, isNew: false });
|
|
@@ -36,10 +49,18 @@ export function createHostedGameRunner(options) {
|
|
|
36
49
|
return;
|
|
37
50
|
members.delete(userId);
|
|
38
51
|
inputs.delete(userId);
|
|
52
|
+
inputSeq.delete(userId);
|
|
39
53
|
loop.onPlayerLeave?.(ctx, player);
|
|
40
54
|
ctx.game.players?.leave(userId);
|
|
41
55
|
},
|
|
42
56
|
input(userId, frame) {
|
|
57
|
+
const seq = frame.seq;
|
|
58
|
+
if (seq !== undefined) {
|
|
59
|
+
const lastSeq = inputSeq.get(userId);
|
|
60
|
+
if (lastSeq !== undefined && seq <= lastSeq)
|
|
61
|
+
return;
|
|
62
|
+
inputSeq.set(userId, seq);
|
|
63
|
+
}
|
|
43
64
|
inputs.set(userId, frame);
|
|
44
65
|
ctx.game.players?.setInput(userId, frame);
|
|
45
66
|
},
|
|
@@ -51,11 +72,14 @@ export function createHostedGameRunner(options) {
|
|
|
51
72
|
},
|
|
52
73
|
tick(dt) {
|
|
53
74
|
loop.onTick?.(ctx, dt);
|
|
75
|
+
advanceBehaviors(ctx, dt);
|
|
76
|
+
syncLifecyclePhase(ctx, definition.lifecycle);
|
|
54
77
|
return replicator.commit();
|
|
55
78
|
},
|
|
56
79
|
diff: (sinceRevision) => replicator.diff(sinceRevision),
|
|
57
80
|
revision: () => replicator.revision(),
|
|
58
|
-
snapshot: () => ctx.snapshot(),
|
|
81
|
+
snapshot: (viewer) => ctx.snapshot(viewer),
|
|
82
|
+
projectsViewers: () => ctx.replicatesPerViewer(),
|
|
59
83
|
members: () => Array.from(members.keys()),
|
|
60
84
|
context: () => ctx,
|
|
61
85
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { CommandResult } from "../commands/commandRegistry.js";
|
|
2
2
|
import type { ModelAssetRef } from "../scene/assetCatalog.js";
|
|
3
|
-
import type { GameContext, GameContextContent } from "./gameContext.js";
|
|
3
|
+
import type { GameContext, GameContextContent, GameContextModels } from "./gameContext.js";
|
|
4
4
|
import type { GameDefinition, LoopPlayer } from "../game/defineGame.js";
|
|
5
5
|
import { type HostedGameRunner, type InputFrame } from "./hostedGameRunner.js";
|
|
6
6
|
import type { WorldDiff } from "./worldReplication.js";
|
|
7
|
-
import type { WorldSnapshot } from "./worldSnapshot.js";
|
|
7
|
+
import type { SnapshotViewer, WorldSnapshot } from "./worldSnapshot.js";
|
|
8
8
|
/** One hosted world's persisted authoritative state — the unit a {@link HostedWorldStore} loads and saves. */
|
|
9
9
|
export interface HostedWorldRecord {
|
|
10
10
|
snapshot: WorldSnapshot;
|
|
@@ -19,7 +19,9 @@ export interface HostedWorldStore {
|
|
|
19
19
|
load(): HostedWorldRecord | null;
|
|
20
20
|
save(record: HostedWorldRecord): void;
|
|
21
21
|
}
|
|
22
|
-
/** In-process {@link HostedWorldStore} for tests, local play, and the browser-tab P2P host.
|
|
22
|
+
/** In-process {@link HostedWorldStore} for tests, local play, and the browser-tab P2P host.
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
23
25
|
export declare function memoryWorldStore(seed?: HostedWorldRecord): HostedWorldStore;
|
|
24
26
|
/** A client replication pull: a full baseline (first sync / fell behind) or a diff since the client's cursor. */
|
|
25
27
|
export type HostedWorldSync = {
|
|
@@ -38,8 +40,10 @@ export interface HostedWorldSessionOptions<TAssetRef extends ModelAssetRef, TMul
|
|
|
38
40
|
now?: () => number;
|
|
39
41
|
/** Where the authoritative snapshot persists; defaults to {@link memoryWorldStore}. */
|
|
40
42
|
store?: HostedWorldStore;
|
|
41
|
-
/** Minimum elapsed
|
|
43
|
+
/** Minimum elapsed ms between auto-saves on tick, measured against `now` (defaults to `Date.now` when omitted). Default `0` — persist on every revision-changing tick. */
|
|
42
44
|
saveIntervalMs?: number;
|
|
45
|
+
/** Render-model lookup for collider auto-fit, forwarded to the runner — see {@link HostedGameRunnerOptions.models}. */
|
|
46
|
+
models?: GameContextModels;
|
|
43
47
|
}
|
|
44
48
|
/**
|
|
45
49
|
* The stateful host substrate a long-lived backend binds (ws server, browser P2P host): a live
|
|
@@ -55,11 +59,17 @@ export interface HostedWorldSession {
|
|
|
55
59
|
tick(dt: number): number;
|
|
56
60
|
/** Replication pull: `null`/`0` cursor → full baseline; a prior revision → a diff since it. */
|
|
57
61
|
sync(sinceRevision: number | null): HostedWorldSync;
|
|
62
|
+
/** The full world baseline projected for one viewer (private/AOI). Identity when no replication policy is set. */
|
|
63
|
+
snapshotFor(viewer: SnapshotViewer): WorldSnapshot;
|
|
64
|
+
/** True when {@link snapshotFor} is viewer-dependent — a host must serve each connection its own projected frame instead of a shared diff. */
|
|
65
|
+
projectsViewers(): boolean;
|
|
58
66
|
revision(): number;
|
|
59
67
|
members(): readonly string[];
|
|
60
68
|
/** Force-persist the current world to the store. */
|
|
61
69
|
save(): void;
|
|
62
70
|
runner(): HostedGameRunner;
|
|
63
71
|
}
|
|
64
|
-
/** Build a {@link HostedWorldSession} — a live runner loaded from a {@link HostedWorldStore} and auto-persisted on tick.
|
|
72
|
+
/** Build a {@link HostedWorldSession} — a live runner loaded from a {@link HostedWorldStore} and auto-persisted on tick.
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
65
75
|
export declare function createHostedWorldSession<TAssetRef extends ModelAssetRef, TMultiplayer>(options: HostedWorldSessionOptions<TAssetRef, TMultiplayer>): HostedWorldSession;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHostedGameRunner } from "./hostedGameRunner.js";
|
|
2
|
-
/** In-process {@link HostedWorldStore} for tests, local play, and the browser-tab P2P host.
|
|
2
|
+
/** In-process {@link HostedWorldStore} for tests, local play, and the browser-tab P2P host.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
3
5
|
export function memoryWorldStore(seed) {
|
|
4
6
|
let record = seed ?? null;
|
|
5
7
|
return {
|
|
@@ -9,9 +11,12 @@ export function memoryWorldStore(seed) {
|
|
|
9
11
|
},
|
|
10
12
|
};
|
|
11
13
|
}
|
|
12
|
-
/** Build a {@link HostedWorldSession} — a live runner loaded from a {@link HostedWorldStore} and auto-persisted on tick.
|
|
14
|
+
/** Build a {@link HostedWorldSession} — a live runner loaded from a {@link HostedWorldStore} and auto-persisted on tick.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
13
17
|
export function createHostedWorldSession(options) {
|
|
14
18
|
const { definition, content, host, now, saveIntervalMs = 0 } = options;
|
|
19
|
+
const clock = now ?? Date.now;
|
|
15
20
|
const store = options.store ?? memoryWorldStore();
|
|
16
21
|
const loaded = store.load();
|
|
17
22
|
const runner = createHostedGameRunner({
|
|
@@ -20,9 +25,10 @@ export function createHostedWorldSession(options) {
|
|
|
20
25
|
...(host === undefined ? {} : { host }),
|
|
21
26
|
...(now === undefined ? {} : { now }),
|
|
22
27
|
...(loaded === null ? {} : { restore: loaded.snapshot }),
|
|
28
|
+
...(options.models === undefined ? {} : { models: options.models }),
|
|
23
29
|
});
|
|
24
30
|
let savedRevision = loaded?.revision ?? 0;
|
|
25
|
-
let lastSaveAt =
|
|
31
|
+
let lastSaveAt = clock();
|
|
26
32
|
function persist() {
|
|
27
33
|
savedRevision = runner.revision();
|
|
28
34
|
store.save({ snapshot: runner.snapshot(), revision: savedRevision });
|
|
@@ -35,7 +41,7 @@ export function createHostedWorldSession(options) {
|
|
|
35
41
|
tick(dt) {
|
|
36
42
|
const revision = runner.tick(dt);
|
|
37
43
|
if (revision !== savedRevision) {
|
|
38
|
-
const at =
|
|
44
|
+
const at = clock();
|
|
39
45
|
if (saveIntervalMs <= 0 || at - lastSaveAt >= saveIntervalMs) {
|
|
40
46
|
lastSaveAt = at;
|
|
41
47
|
persist();
|
|
@@ -49,6 +55,8 @@ export function createHostedWorldSession(options) {
|
|
|
49
55
|
}
|
|
50
56
|
return { kind: "diff", diff: runner.diff(sinceRevision) };
|
|
51
57
|
},
|
|
58
|
+
snapshotFor: (viewer) => runner.snapshot(viewer),
|
|
59
|
+
projectsViewers: () => runner.projectsViewers(),
|
|
52
60
|
revision: () => runner.revision(),
|
|
53
61
|
members: () => runner.members(),
|
|
54
62
|
save: persist,
|
|
@@ -6,14 +6,19 @@ export interface InputFrame {
|
|
|
6
6
|
pointer: PointerAxisState | null;
|
|
7
7
|
}
|
|
8
8
|
export interface InputSnapshot {
|
|
9
|
-
/** Replaces the held-action set for this frame. Called by the shell before `onTick` each frame; does not bump `ctx.version()` or notify `ctx.subscribe` listeners — per-frame publishes would storm subscribers. */
|
|
9
|
+
/** Replaces the held-action set for this frame, rolling the previous held set forward for edge detection (#671). Called by the shell before `onTick` each frame; does not bump `ctx.version()` or notify `ctx.subscribe` listeners — per-frame publishes would storm subscribers. */
|
|
10
10
|
publish(held: readonly string[]): void;
|
|
11
11
|
/** Replaces the normalized pointer-position state for this frame (#293). Same no-notify contract as `publish`. */
|
|
12
12
|
publishPointer(state: PointerAxisState | null): void;
|
|
13
13
|
isDown(action: string): boolean;
|
|
14
|
+
/** The held-action set for this frame — an owned, frozen array; the array {@link publish} was called with is never aliased or returned. */
|
|
14
15
|
held(): readonly string[];
|
|
15
|
-
/**
|
|
16
|
-
|
|
16
|
+
/** True only on the frame `action` transitions from up to down (#671) — derived from the last two published held sets, so it stays replay-safe. */
|
|
17
|
+
justPressed(action: string): boolean;
|
|
18
|
+
/** True only on the frame `action` transitions from down to up (#671); mirrors {@link justPressed}. */
|
|
19
|
+
justReleased(action: string): boolean;
|
|
20
|
+
/** Pointer position over the play surface, `[-1, 1]` per axis with `+y` down, published by the shell each frame; `null` until the first pointer move. Frozen — an owned copy of what {@link publishPointer} was called with. */
|
|
21
|
+
pointer(): Readonly<PointerAxisState> | null;
|
|
17
22
|
/**
|
|
18
23
|
* Instantaneous analog axis sample against the held-action set and current pointer (#533.7) — bind
|
|
19
24
|
* throttle/steer/handbrake (or any axes) to *action names*, not raw key codes, since the held set is
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { sampleAxisBindings } from "../input/axisInput.js";
|
|
2
2
|
export function createInputSnapshot() {
|
|
3
3
|
let heldSet = new Set();
|
|
4
|
+
let previousHeldSet = new Set();
|
|
4
5
|
let heldList = [];
|
|
5
6
|
let pointerState = null;
|
|
6
7
|
return {
|
|
7
8
|
publish(held) {
|
|
8
|
-
|
|
9
|
+
previousHeldSet = heldSet;
|
|
10
|
+
heldList = Object.freeze([...held]);
|
|
9
11
|
heldSet = new Set(held);
|
|
10
12
|
},
|
|
11
13
|
publishPointer(state) {
|
|
12
|
-
pointerState = state;
|
|
14
|
+
pointerState = state === null ? null : Object.freeze({ ...state });
|
|
13
15
|
},
|
|
14
16
|
isDown: (action) => heldSet.has(action),
|
|
15
17
|
held: () => heldList,
|
|
16
18
|
pointer: () => pointerState,
|
|
17
19
|
axis: (bindings, ranges) => sampleAxisBindings(bindings, (action) => heldSet.has(action), pointerState, ranges),
|
|
20
|
+
justPressed: (action) => heldSet.has(action) && !previousHeldSet.has(action),
|
|
21
|
+
justReleased: (action) => !heldSet.has(action) && previousHeldSet.has(action),
|
|
18
22
|
};
|
|
19
23
|
}
|
|
@@ -21,6 +21,10 @@ export interface MotionIntents {
|
|
|
21
21
|
setVerticalVelocity(velocityY: number): void;
|
|
22
22
|
setY(y: number): void;
|
|
23
23
|
takePending(): MotionIntentBatch | null;
|
|
24
|
+
/** Non-draining copy of the pending intents for a whole-world save; unlike `takePending` it leaves the queue intact. */
|
|
25
|
+
snapshot(): MotionIntentBatch;
|
|
26
|
+
/** Replace the pending intents from a {@link snapshot} payload on save load. */
|
|
27
|
+
hydrate(batch: MotionIntentBatch): void;
|
|
24
28
|
}
|
|
25
29
|
export interface MotionIntentBatch {
|
|
26
30
|
impulses: readonly number[];
|
|
@@ -28,8 +32,13 @@ export interface MotionIntentBatch {
|
|
|
28
32
|
verticalVelocity: number | null;
|
|
29
33
|
y: number | null;
|
|
30
34
|
}
|
|
35
|
+
/** @internal */
|
|
31
36
|
export declare function createMotionIntents(): MotionIntents;
|
|
32
|
-
/** Fold a batch's vertical impulses into a controller's velocity, then apply an outright `setVerticalVelocity` override — the vertical counterpart of {@link applyHorizontalImpulses}.
|
|
37
|
+
/** Fold a batch's vertical impulses into a controller's velocity, then apply an outright `setVerticalVelocity` override — the vertical counterpart of {@link applyHorizontalImpulses}.
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
33
40
|
export declare function applyMotionImpulses(currentVelocity: number, batch: MotionIntentBatch | null): number;
|
|
34
|
-
/** Fold a batch's horizontal pushes into a controller's velocity pair — shared by the walk and voxel drivers.
|
|
41
|
+
/** Fold a batch's horizontal pushes into a controller's velocity pair — shared by the walk and voxel drivers.
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
35
44
|
export declare function applyHorizontalImpulses(velocityX: number, velocityZ: number, batch: MotionIntentBatch | null): readonly [number, number];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @internal */
|
|
1
2
|
export function createMotionIntents() {
|
|
2
3
|
let impulses = [];
|
|
3
4
|
let horizontalImpulses = [];
|
|
@@ -27,9 +28,20 @@ export function createMotionIntents() {
|
|
|
27
28
|
y = null;
|
|
28
29
|
return batch;
|
|
29
30
|
},
|
|
31
|
+
snapshot() {
|
|
32
|
+
return { impulses: [...impulses], horizontalImpulses: [...horizontalImpulses], verticalVelocity, y };
|
|
33
|
+
},
|
|
34
|
+
hydrate(batch) {
|
|
35
|
+
impulses = [...batch.impulses];
|
|
36
|
+
horizontalImpulses = batch.horizontalImpulses.map(([x, z]) => [x, z]);
|
|
37
|
+
verticalVelocity = batch.verticalVelocity;
|
|
38
|
+
y = batch.y;
|
|
39
|
+
},
|
|
30
40
|
};
|
|
31
41
|
}
|
|
32
|
-
/** Fold a batch's vertical impulses into a controller's velocity, then apply an outright `setVerticalVelocity` override — the vertical counterpart of {@link applyHorizontalImpulses}.
|
|
42
|
+
/** Fold a batch's vertical impulses into a controller's velocity, then apply an outright `setVerticalVelocity` override — the vertical counterpart of {@link applyHorizontalImpulses}.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
33
45
|
export function applyMotionImpulses(currentVelocity, batch) {
|
|
34
46
|
if (batch === null)
|
|
35
47
|
return currentVelocity;
|
|
@@ -40,7 +52,9 @@ export function applyMotionImpulses(currentVelocity, batch) {
|
|
|
40
52
|
velocity = batch.verticalVelocity;
|
|
41
53
|
return velocity;
|
|
42
54
|
}
|
|
43
|
-
/** Fold a batch's horizontal pushes into a controller's velocity pair — shared by the walk and voxel drivers.
|
|
55
|
+
/** Fold a batch's horizontal pushes into a controller's velocity pair — shared by the walk and voxel drivers.
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
44
58
|
export function applyHorizontalImpulses(velocityX, velocityZ, batch) {
|
|
45
59
|
if (batch === null || batch.horizontalImpulses.length === 0)
|
|
46
60
|
return [velocityX, velocityZ];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { GameContext } from "./gameContext.js";
|
|
2
|
+
/**
|
|
3
|
+
* Per-`GameContext` lazy state, keyed by context identity through a `WeakMap` so it is reclaimed when
|
|
4
|
+
* the context is — the seam a game uses instead of a module-global `Map`, which is process-global and
|
|
5
|
+
* bleeds across worlds when one host serves several `serverId`s (#632). `init` runs once per distinct
|
|
6
|
+
* context on first access; the same context always resolves to the same value. This mirrors the engine's
|
|
7
|
+
* built-in per-ctx pattern (`ctx.player.motion`, `stepPlayerMovement`).
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* const heroRuntimes = perContext(() => new Map<string, HeroRuntime>());
|
|
11
|
+
* // per world:
|
|
12
|
+
* heroRuntimes(ctx).set(userId, runtime);
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function perContext<T>(init: (ctx: GameContext) => T): (ctx: GameContext) => T;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-`GameContext` lazy state, keyed by context identity through a `WeakMap` so it is reclaimed when
|
|
3
|
+
* the context is — the seam a game uses instead of a module-global `Map`, which is process-global and
|
|
4
|
+
* bleeds across worlds when one host serves several `serverId`s (#632). `init` runs once per distinct
|
|
5
|
+
* context on first access; the same context always resolves to the same value. This mirrors the engine's
|
|
6
|
+
* built-in per-ctx pattern (`ctx.player.motion`, `stepPlayerMovement`).
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* const heroRuntimes = perContext(() => new Map<string, HeroRuntime>());
|
|
10
|
+
* // per world:
|
|
11
|
+
* heroRuntimes(ctx).set(userId, runtime);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function perContext(init) {
|
|
15
|
+
const byContext = new WeakMap();
|
|
16
|
+
return (ctx) => {
|
|
17
|
+
if (!byContext.has(ctx))
|
|
18
|
+
byContext.set(ctx, init(ctx));
|
|
19
|
+
return byContext.get(ctx);
|
|
20
|
+
};
|
|
21
|
+
}
|