@jgengine/core 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -2
- package/LICENSE +203 -661
- package/README.md +1 -1
- package/dist/ai/crowd.d.ts +55 -0
- package/dist/ai/crowd.js +114 -0
- package/dist/ai/flock.d.ts +5 -2
- package/dist/ai/flock.js +5 -2
- package/dist/ai/groupAssist.d.ts +1 -0
- package/dist/ai/groupAssist.js +1 -0
- package/dist/ai/heatSystem.d.ts +76 -0
- package/dist/ai/heatSystem.js +97 -0
- package/dist/ai/interestScheduler.d.ts +107 -0
- package/dist/ai/interestScheduler.js +118 -0
- package/dist/ai/jobBoard.d.ts +1 -0
- package/dist/ai/jobBoard.js +1 -0
- package/dist/ai/laneSelect.d.ts +5 -2
- package/dist/ai/laneSelect.js +5 -2
- package/dist/ai/mobBrain.d.ts +1 -0
- package/dist/ai/mobBrain.js +1 -0
- package/dist/ai/populationDirector.d.ts +103 -0
- package/dist/ai/populationDirector.js +190 -0
- package/dist/ai/pursuit.d.ts +56 -0
- package/dist/ai/pursuit.js +53 -0
- package/dist/ai/spawnDirector.d.ts +7 -2
- package/dist/ai/spawnDirector.js +18 -15
- package/dist/ai/spawnPoint.d.ts +3 -1
- package/dist/ai/spawnPoint.js +3 -1
- package/dist/ai/targetAcquisition.d.ts +84 -0
- package/dist/ai/targetAcquisition.js +92 -0
- package/dist/anim/easing.d.ts +19 -0
- package/dist/anim/easing.js +19 -0
- package/dist/anim/oscillator.d.ts +12 -0
- package/dist/anim/oscillator.js +25 -0
- package/dist/area/areaEffectField.d.ts +127 -0
- package/dist/area/areaEffectField.js +175 -0
- package/dist/area/stackPolicy.d.ts +47 -0
- package/dist/area/stackPolicy.js +99 -0
- package/dist/authoring.d.ts +2 -1
- package/dist/authoring.js +2 -1
- package/dist/board/laneBoard.d.ts +13 -0
- package/dist/board/laneBoard.js +13 -0
- package/dist/board/timelineBoard.d.ts +10 -0
- package/dist/board/timelineBoard.js +10 -0
- package/dist/combat/abilityKit.d.ts +18 -0
- package/dist/combat/abilityKit.js +24 -9
- package/dist/combat/animationState.d.ts +5 -0
- package/dist/combat/animationState.js +5 -0
- package/dist/combat/breakMeters.d.ts +10 -0
- package/dist/combat/breakMeters.js +10 -0
- package/dist/combat/castRunner.d.ts +5 -0
- package/dist/combat/castRunner.js +5 -0
- package/dist/combat/comboPoints.d.ts +5 -0
- package/dist/combat/comboPoints.js +5 -0
- package/dist/combat/comboString.d.ts +5 -0
- package/dist/combat/comboString.js +5 -0
- package/dist/combat/damageInterceptors.d.ts +192 -0
- package/dist/combat/damageInterceptors.js +251 -0
- package/dist/combat/damageMatchup.d.ts +68 -0
- package/dist/combat/damageMatchup.js +42 -0
- package/dist/combat/damageResolution.d.ts +63 -0
- package/dist/combat/damageResolution.js +50 -0
- package/dist/combat/death.d.ts +7 -1
- package/dist/combat/death.js +5 -0
- package/dist/combat/deathReason.d.ts +14 -0
- package/dist/combat/deathReason.js +1 -0
- package/dist/combat/defensiveWindow.d.ts +5 -0
- package/dist/combat/defensiveWindow.js +5 -0
- package/dist/combat/dotField.d.ts +5 -1
- package/dist/combat/dotField.js +5 -1
- package/dist/combat/downed.d.ts +5 -0
- package/dist/combat/downed.js +5 -0
- package/dist/combat/effects.d.ts +5 -0
- package/dist/combat/effects.js +5 -0
- package/dist/combat/encounterSequence.d.ts +258 -0
- package/dist/combat/encounterSequence.js +426 -0
- package/dist/combat/hitReaction.d.ts +57 -1
- package/dist/combat/hitReaction.js +45 -5
- package/dist/combat/magazine.d.ts +54 -0
- package/dist/combat/magazine.js +96 -0
- package/dist/combat/projectiles.d.ts +5 -0
- package/dist/combat/projectiles.js +32 -14
- package/dist/combat/receivedDamage.d.ts +117 -0
- package/dist/combat/receivedDamage.js +92 -0
- package/dist/combat/regenShield.d.ts +5 -1
- package/dist/combat/regenShield.js +5 -1
- package/dist/combat/renderCues.d.ts +51 -0
- package/dist/combat/renderCues.js +44 -0
- package/dist/combat/resourcePool.d.ts +5 -0
- package/dist/combat/resourcePool.js +5 -0
- package/dist/combat/rewardAllocation.d.ts +121 -0
- package/dist/combat/rewardAllocation.js +251 -0
- package/dist/combat/shotOrigin.d.ts +18 -1
- package/dist/combat/shotOrigin.js +39 -0
- package/dist/combat/statusApplication.d.ts +96 -0
- package/dist/combat/statusApplication.js +81 -0
- package/dist/combat/telegraph.d.ts +11 -2
- package/dist/combat/telegraph.js +11 -2
- package/dist/combat/thresholdCrossings.d.ts +85 -0
- package/dist/combat/thresholdCrossings.js +116 -0
- package/dist/combat.d.ts +35 -0
- package/dist/combat.js +35 -0
- package/dist/commands/commandRegistry.d.ts +11 -0
- package/dist/commands/commandRegistry.js +9 -2
- package/dist/crafting/crop.d.ts +18 -0
- package/dist/crafting/crop.js +18 -0
- package/dist/crafting/production.d.ts +5 -0
- package/dist/crafting/production.js +5 -0
- package/dist/devtools/controls.d.ts +38 -0
- package/dist/devtools/controls.js +181 -0
- package/dist/devtools/devtools.d.ts +5 -197
- package/dist/devtools/devtools.js +38 -774
- package/dist/devtools/discover.d.ts +32 -0
- package/dist/devtools/discover.js +240 -0
- package/dist/devtools/fallbackSeams.d.ts +50 -0
- package/dist/devtools/fallbackSeams.js +111 -0
- package/dist/devtools/frame.d.ts +15 -0
- package/dist/devtools/frame.js +247 -0
- package/dist/devtools/logs.d.ts +15 -0
- package/dist/devtools/logs.js +86 -0
- package/dist/devtools/overrides.d.ts +16 -0
- package/dist/devtools/overrides.js +66 -0
- package/dist/devtools/rewriteTunables.d.ts +17 -0
- package/dist/devtools/rewriteTunables.js +276 -0
- package/dist/devtools/saveEndpoint.d.ts +46 -0
- package/dist/devtools/saveEndpoint.js +48 -0
- package/dist/devtools/transformTunables.d.ts +3 -0
- package/dist/devtools/transformTunables.js +3 -0
- package/dist/devtools/tunableSchema.d.ts +31 -0
- package/dist/devtools/tunableSchema.js +31 -0
- package/dist/devtools/types.d.ts +212 -0
- package/dist/devtools/types.js +1 -0
- package/dist/economy/auctionBook.d.ts +122 -0
- package/dist/economy/auctionBook.js +213 -0
- package/dist/economy/currency.d.ts +12 -1
- package/dist/economy/currency.js +12 -1
- package/dist/economy/listingBook.d.ts +91 -0
- package/dist/economy/listingBook.js +144 -0
- package/dist/economy/priceHistory.d.ts +44 -0
- package/dist/economy/priceHistory.js +89 -0
- package/dist/economy/resourceLedger.d.ts +222 -0
- package/dist/economy/resourceLedger.js +353 -0
- package/dist/economy/sharedWallet.d.ts +14 -0
- package/dist/economy/sharedWallet.js +14 -0
- package/dist/economy/techTree.d.ts +12 -0
- package/dist/economy/techTree.js +12 -0
- package/dist/economy/unlockPoints.d.ts +92 -0
- package/dist/economy/unlockPoints.js +103 -0
- package/dist/economy/wallet.d.ts +26 -2
- package/dist/economy/wallet.js +35 -6
- package/dist/editor/commandApply.d.ts +5 -0
- package/dist/editor/commandApply.js +755 -0
- package/dist/editor/commands.d.ts +235 -7
- package/dist/editor/commands.js +82 -124
- package/dist/editor/directives.d.ts +94 -0
- package/dist/editor/directives.js +206 -0
- package/dist/editor/document.d.ts +194 -13
- package/dist/editor/document.js +1166 -19
- package/dist/editor/entityCatalog.d.ts +42 -0
- package/dist/editor/entityCatalog.js +101 -0
- package/dist/editor/environment.d.ts +74 -0
- package/dist/editor/environment.js +169 -0
- package/dist/editor/grid.d.ts +229 -0
- package/dist/editor/grid.js +366 -0
- package/dist/editor/gridAdapters.d.ts +80 -0
- package/dist/editor/gridAdapters.js +134 -0
- package/dist/editor/index.d.ts +98 -6
- package/dist/editor/index.js +13 -2
- package/dist/editor/liveSync.d.ts +127 -0
- package/dist/editor/liveSync.js +249 -0
- package/dist/editor/minimap.d.ts +31 -0
- package/dist/editor/minimap.js +73 -0
- package/dist/editor/runtimeInspector.d.ts +88 -0
- package/dist/editor/runtimeInspector.js +239 -0
- package/dist/editor/streamer.d.ts +66 -0
- package/dist/editor/streamer.js +68 -0
- package/dist/editor/types.d.ts +250 -1
- package/dist/editor/world.d.ts +136 -0
- package/dist/editor/world.js +303 -0
- package/dist/faction/reputation.d.ts +5 -0
- package/dist/faction/reputation.js +5 -0
- package/dist/format/distance.d.ts +17 -0
- package/dist/format/distance.js +18 -0
- package/dist/format/duration.d.ts +27 -0
- package/dist/format/duration.js +45 -0
- package/dist/format/speed.d.ts +17 -0
- package/dist/format/speed.js +25 -0
- package/dist/game/breeding.d.ts +161 -0
- package/dist/game/breeding.js +181 -0
- package/dist/game/cameraConfig.d.ts +451 -0
- package/dist/game/cameraConfig.js +1 -0
- package/dist/game/connectedPlayers.d.ts +6 -4
- package/dist/game/connectedPlayers.js +2 -2
- package/dist/game/cosmetics.d.ts +9 -0
- package/dist/game/cosmetics.js +16 -0
- package/dist/game/defineGame.d.ts +110 -5
- package/dist/game/defineGame.js +49 -4
- package/dist/game/defineSystem.d.ts +90 -0
- package/dist/game/defineSystem.js +47 -0
- package/dist/game/dialogue.d.ts +33 -0
- package/dist/game/dialogue.js +21 -0
- package/dist/game/events.d.ts +63 -13
- package/dist/game/events.js +5 -0
- package/dist/game/feed.d.ts +33 -0
- package/dist/game/feed.js +35 -2
- package/dist/game/gamePhase.d.ts +11 -0
- package/dist/game/gamePhase.js +16 -0
- package/dist/game/leaderboard.d.ts +5 -0
- package/dist/game/leaderboard.js +5 -0
- package/dist/game/loadout.d.ts +5 -0
- package/dist/game/loadout.js +5 -0
- package/dist/game/lootFilter.d.ts +2 -0
- package/dist/game/lootFilter.js +2 -0
- package/dist/game/lootPipeline.d.ts +164 -0
- package/dist/game/lootPipeline.js +216 -0
- package/dist/game/lootTable.d.ts +19 -2
- package/dist/game/lootTable.js +15 -5
- package/dist/game/objectives.d.ts +43 -0
- package/dist/game/objectives.js +36 -0
- package/dist/game/paramLayers.d.ts +148 -0
- package/dist/game/paramLayers.js +185 -0
- package/dist/game/ping.d.ts +5 -0
- package/dist/game/ping.js +5 -0
- package/dist/game/playableGame.d.ts +116 -432
- package/dist/game/playableGame.js +1 -1
- package/dist/game/progression.d.ts +35 -0
- package/dist/game/progression.js +19 -0
- package/dist/game/quest.d.ts +8 -0
- package/dist/game/quest.js +30 -3
- package/dist/game/race.d.ts +141 -0
- package/dist/game/race.js +169 -0
- package/dist/game/recordBook.d.ts +3 -1
- package/dist/game/recordBook.js +4 -1
- package/dist/game/ruleSelection.d.ts +75 -0
- package/dist/game/ruleSelection.js +127 -0
- package/dist/game/runDraft.d.ts +5 -0
- package/dist/game/runDraft.js +5 -0
- package/dist/game/saveStore.d.ts +111 -0
- package/dist/game/saveStore.js +312 -0
- package/dist/game/snapshotHistory.d.ts +67 -0
- package/dist/game/snapshotHistory.js +95 -0
- package/dist/game/social.d.ts +38 -1
- package/dist/game/social.js +71 -0
- package/dist/game/spawnPoints.d.ts +5 -0
- package/dist/game/spawnPoints.js +5 -0
- package/dist/game/systemRuntime.d.ts +50 -0
- package/dist/game/systemRuntime.js +157 -0
- package/dist/game/systemSchedule.d.ts +72 -0
- package/dist/game/systemSchedule.js +242 -0
- package/dist/game/toasts.d.ts +43 -0
- package/dist/game/toasts.js +44 -0
- package/dist/game/trade.d.ts +10 -0
- package/dist/game/trade.js +10 -0
- package/dist/game/tribe.d.ts +184 -0
- package/dist/game/tribe.js +432 -0
- package/dist/game/unlocks.d.ts +8 -0
- package/dist/game/unlocks.js +16 -0
- package/dist/game/vfxInstance.d.ts +138 -0
- package/dist/game/vfxInstance.js +96 -0
- package/dist/game/worldItem.d.ts +17 -4
- package/dist/game/worldItem.js +17 -4
- package/dist/gameplay.d.ts +93 -0
- package/dist/gameplay.js +93 -0
- package/dist/index.d.ts +5 -14
- package/dist/index.js +5 -14
- package/dist/input/actionBindings.d.ts +23 -6
- package/dist/input/actionBindings.js +23 -6
- package/dist/input/axisInput.d.ts +7 -2
- package/dist/input/axisInput.js +7 -2
- package/dist/input/controlGroups.d.ts +67 -0
- package/dist/input/controlGroups.js +41 -0
- package/dist/input/touchScheme.d.ts +82 -6
- package/dist/input/touchScheme.js +123 -10
- package/dist/interaction/lockpick.d.ts +61 -0
- package/dist/interaction/lockpick.js +168 -0
- package/dist/interaction/proximityPrompt.d.ts +2 -0
- package/dist/interaction/proximityPrompt.js +2 -0
- package/dist/interaction/qte.d.ts +5 -0
- package/dist/interaction/qte.js +5 -0
- package/dist/interaction/skillCheck.d.ts +5 -0
- package/dist/interaction/skillCheck.js +5 -0
- package/dist/inventory/encumbrance.d.ts +69 -0
- package/dist/inventory/encumbrance.js +68 -0
- package/dist/inventory/inventoryModel.d.ts +12 -0
- package/dist/inventory/inventoryModel.js +12 -0
- package/dist/inventory/shapedGrid.d.ts +16 -0
- package/dist/inventory/shapedGrid.js +16 -0
- package/dist/inventory/slotModel.d.ts +10 -0
- package/dist/inventory/slotModel.js +10 -0
- package/dist/item/durability.d.ts +5 -0
- package/dist/item/durability.js +6 -3
- package/dist/item/itemIdentity.d.ts +171 -0
- package/dist/item/itemIdentity.js +138 -0
- package/dist/item/itemInstanceRegistry.d.ts +32 -0
- package/dist/item/itemInstanceRegistry.js +34 -0
- package/dist/item/itemgen.d.ts +163 -0
- package/dist/item/itemgen.js +151 -0
- package/dist/item/modularItem.d.ts +5 -0
- package/dist/item/modularItem.js +5 -0
- package/dist/item/use.d.ts +5 -0
- package/dist/item/use.js +5 -0
- package/dist/item/useBehavior.d.ts +142 -0
- package/dist/item/useBehavior.js +105 -0
- package/dist/item/weapon.d.ts +5 -0
- package/dist/item/weapon.js +5 -0
- package/dist/math/scalar.d.ts +25 -0
- package/dist/math/scalar.js +47 -0
- package/dist/meta/changelog.d.ts +4 -1
- package/dist/meta/changelog.js +39 -2
- package/dist/movement/avoidance.d.ts +45 -0
- package/dist/movement/avoidance.js +123 -0
- package/dist/movement/cameraRig.d.ts +8 -0
- package/dist/movement/cameraRig.js +8 -0
- package/dist/movement/dash.d.ts +11 -0
- package/dist/movement/dash.js +11 -0
- package/dist/movement/formation.d.ts +135 -0
- package/dist/movement/formation.js +194 -0
- package/dist/movement/glideModel.d.ts +5 -0
- package/dist/movement/glideModel.js +5 -0
- package/dist/movement/grappleSwing.d.ts +5 -0
- package/dist/movement/grappleSwing.js +5 -0
- package/dist/movement/leaderTrail.d.ts +5 -0
- package/dist/movement/leaderTrail.js +5 -0
- package/dist/movement/movementModel.d.ts +50 -9
- package/dist/movement/movementModel.js +75 -29
- package/dist/movement/playerMovement.js +167 -12
- package/dist/movement/poseState.d.ts +13 -0
- package/dist/movement/poseState.js +16 -0
- package/dist/movement/steering.d.ts +8 -0
- package/dist/movement/steering.js +18 -0
- package/dist/multiplayer/combatSnapshot.d.ts +3 -0
- package/dist/multiplayer/combatSnapshot.js +16 -8
- package/dist/multiplayer/lagCompensation.d.ts +5 -0
- package/dist/multiplayer/lagCompensation.js +5 -0
- package/dist/multiplayer/presenceModel.d.ts +11 -1
- package/dist/multiplayer/presenceModel.js +17 -1
- package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
- package/dist/multiplayer/simultaneousCommit.js +3 -0
- package/dist/multiplayer.d.ts +11 -0
- package/dist/multiplayer.js +11 -0
- package/dist/nav/pathFollow.d.ts +57 -0
- package/dist/nav/pathFollow.js +109 -0
- package/dist/orders/orderKinds.d.ts +156 -0
- package/dist/orders/orderKinds.js +197 -0
- package/dist/orders/orderQueue.d.ts +208 -0
- package/dist/orders/orderQueue.js +211 -0
- package/dist/physics/drivableVehicle.d.ts +31 -0
- package/dist/physics/drivableVehicle.js +16 -0
- package/dist/physics/flightDynamics.d.ts +82 -0
- package/dist/physics/flightDynamics.js +165 -0
- package/dist/physics/gravityField.d.ts +25 -0
- package/dist/physics/gravityField.js +41 -0
- package/dist/physics/kinematicVehicle.d.ts +108 -1
- package/dist/physics/kinematicVehicle.js +212 -15
- package/dist/physics/physicsWorld.d.ts +50 -12
- package/dist/physics/physicsWorld.js +120 -122
- package/dist/physics/radialImpulse.d.ts +25 -0
- package/dist/physics/radialImpulse.js +27 -0
- package/dist/physics/vehicleObstacles.d.ts +44 -0
- package/dist/physics/vehicleObstacles.js +115 -0
- package/dist/procedural.d.ts +3 -0
- package/dist/procedural.js +3 -0
- package/dist/progression/statGraph.d.ts +116 -0
- package/dist/progression/statGraph.js +318 -0
- package/dist/puzzle/cellGrid.d.ts +9 -0
- package/dist/puzzle/cellGrid.js +9 -0
- package/dist/puzzle/fallingPiece.d.ts +9 -0
- package/dist/puzzle/fallingPiece.js +9 -0
- package/dist/puzzle/nonogram.d.ts +39 -0
- package/dist/puzzle/nonogram.js +136 -0
- package/dist/random/nameGen.d.ts +5 -0
- package/dist/random/nameGen.js +5 -0
- package/dist/random/pick.d.ts +8 -0
- package/dist/random/pick.js +31 -0
- package/dist/random/rng.d.ts +26 -1
- package/dist/random/rng.js +32 -9
- package/dist/random/seedLink.d.ts +4 -0
- package/dist/random/seedLink.js +4 -0
- package/dist/relation/keyedValues.d.ts +54 -0
- package/dist/relation/keyedValues.js +115 -0
- package/dist/relation/thresholds.d.ts +62 -0
- package/dist/relation/thresholds.js +62 -0
- package/dist/render/color.d.ts +12 -0
- package/dist/render/color.js +26 -0
- package/dist/render/lookPreset.d.ts +41 -0
- package/dist/render/lookPreset.js +29 -0
- package/dist/render/postProcessing.d.ts +20 -0
- package/dist/render/postProcessing.js +21 -1
- package/dist/rules/predicate.d.ts +53 -0
- package/dist/rules/predicate.js +64 -0
- package/dist/rules/ruleEffects.d.ts +38 -0
- package/dist/rules/ruleEffects.js +37 -0
- package/dist/rules/triggeredRules.d.ts +160 -0
- package/dist/rules/triggeredRules.js +241 -0
- package/dist/runtime/adapter.d.ts +55 -3
- package/dist/runtime/adapter.js +57 -1
- package/dist/runtime/cameraDirector.d.ts +1 -0
- package/dist/runtime/cameraDirector.js +1 -0
- package/dist/runtime/commandRunner.d.ts +1 -0
- package/dist/runtime/commandRunner.js +1 -0
- package/dist/runtime/context/combat.d.ts +51 -0
- package/dist/runtime/context/combat.js +130 -0
- package/dist/runtime/context/combatFx.d.ts +23 -0
- package/dist/runtime/context/combatFx.js +161 -0
- package/dist/runtime/context/deathLoot.d.ts +30 -0
- package/dist/runtime/context/deathLoot.js +39 -0
- package/dist/runtime/context/player.d.ts +48 -0
- package/dist/runtime/context/player.js +125 -0
- package/dist/runtime/context/registries.d.ts +13 -0
- package/dist/runtime/context/registries.js +84 -0
- package/dist/runtime/context/scene.d.ts +59 -0
- package/dist/runtime/context/scene.js +291 -0
- package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
- package/dist/runtime/context/snapshotCodecs.js +26 -0
- package/dist/runtime/context/worldItems.d.ts +21 -0
- package/dist/runtime/context/worldItems.js +37 -0
- package/dist/runtime/descriptors/baseline.d.ts +48 -0
- package/dist/runtime/descriptors/baseline.js +157 -0
- package/dist/runtime/descriptors/features.d.ts +79 -0
- package/dist/runtime/descriptors/features.js +299 -0
- package/dist/runtime/gameContext.d.ts +2 -327
- package/dist/runtime/gameContext.js +273 -778
- package/dist/runtime/gameContextTypes.d.ts +467 -0
- package/dist/runtime/gameContextTypes.js +1 -0
- package/dist/runtime/gameRuntime.d.ts +1 -0
- package/dist/runtime/gameRuntime.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +62 -0
- package/dist/runtime/headlessRunner.js +45 -0
- package/dist/runtime/hostPersistence.d.ts +12 -0
- package/dist/runtime/hostPersistence.js +12 -0
- package/dist/runtime/hostPolicy.d.ts +51 -0
- package/dist/runtime/hostPolicy.js +68 -0
- package/dist/runtime/hostedGameRunner.d.ts +11 -4
- package/dist/runtime/hostedGameRunner.js +27 -3
- package/dist/runtime/hostedWorldSession.d.ts +15 -5
- package/dist/runtime/hostedWorldSession.js +12 -4
- package/dist/runtime/inputSnapshot.d.ts +8 -3
- package/dist/runtime/inputSnapshot.js +6 -2
- package/dist/runtime/motionIntents.d.ts +11 -2
- package/dist/runtime/motionIntents.js +16 -2
- package/dist/runtime/perContext.d.ts +15 -0
- package/dist/runtime/perContext.js +21 -0
- package/dist/runtime/runtimeSave.d.ts +79 -0
- package/dist/runtime/runtimeSave.js +105 -0
- package/dist/runtime/save.d.ts +4 -0
- package/dist/runtime/save.js +4 -0
- package/dist/runtime/snapshot.d.ts +7 -0
- package/dist/runtime/snapshot.js +7 -0
- package/dist/runtime/visibility.d.ts +2 -1
- package/dist/runtime/visibility.js +2 -1
- package/dist/runtime/worldChannel.d.ts +7 -3
- package/dist/runtime/worldChannel.js +51 -6
- package/dist/runtime/worldMirror.d.ts +14 -2
- package/dist/runtime/worldMirror.js +15 -2
- package/dist/runtime/worldProjection.d.ts +47 -0
- package/dist/runtime/worldProjection.js +52 -0
- package/dist/runtime/worldReplication.d.ts +30 -7
- package/dist/runtime/worldReplication.js +41 -9
- package/dist/runtime/worldSnapshot.d.ts +42 -3
- package/dist/runtime/worldSnapshot.js +34 -7
- package/dist/scene/assetCatalog.d.ts +26 -0
- package/dist/scene/assetCatalog.js +4 -0
- package/dist/scene/assetDiagnostics.d.ts +69 -0
- package/dist/scene/assetDiagnostics.js +110 -0
- package/dist/scene/assetGenerator.d.ts +65 -0
- package/dist/scene/assetGenerator.js +64 -0
- package/dist/scene/assetSpace.d.ts +137 -0
- package/dist/scene/assetSpace.js +257 -0
- package/dist/scene/authoredTriggers.d.ts +219 -0
- package/dist/scene/authoredTriggers.js +454 -0
- package/dist/scene/behaviorRuntime.d.ts +75 -0
- package/dist/scene/behaviorRuntime.js +217 -0
- package/dist/scene/behaviors.d.ts +14 -2
- package/dist/scene/behaviors.js +7 -2
- package/dist/scene/bodyBind.d.ts +60 -0
- package/dist/scene/bodyBind.js +51 -0
- package/dist/scene/builtinSceneKinds.d.ts +5 -0
- package/dist/scene/builtinSceneKinds.js +67 -0
- package/dist/scene/colliders.d.ts +71 -1
- package/dist/scene/colliders.js +145 -1
- package/dist/scene/collisionMesh.d.ts +94 -0
- package/dist/scene/collisionMesh.js +699 -0
- package/dist/scene/companion.d.ts +147 -0
- package/dist/scene/companion.js +193 -0
- package/dist/scene/entityStats.d.ts +18 -11
- package/dist/scene/entityStats.js +21 -16
- package/dist/scene/entityStore.d.ts +12 -1
- package/dist/scene/entityStore.js +15 -0
- package/dist/scene/facing.d.ts +18 -0
- package/dist/scene/facing.js +26 -0
- package/dist/scene/modelSockets.d.ts +33 -0
- package/dist/scene/modelSockets.js +29 -0
- package/dist/scene/objectQuery.d.ts +2 -0
- package/dist/scene/objectQuery.js +2 -0
- package/dist/scene/objectStore.d.ts +4 -0
- package/dist/scene/objectStore.js +6 -0
- package/dist/scene/possession.d.ts +8 -0
- package/dist/scene/possession.js +14 -0
- package/dist/scene/roster.d.ts +3 -0
- package/dist/scene/roster.js +12 -0
- package/dist/scene/sceneKinds.d.ts +256 -0
- package/dist/scene/sceneKinds.js +218 -0
- package/dist/scene/sceneOwnership.d.ts +169 -0
- package/dist/scene/sceneOwnership.js +179 -0
- package/dist/scene/sceneRaycast.js +15 -0
- package/dist/scene/selectionBookmarks.d.ts +93 -0
- package/dist/scene/selectionBookmarks.js +122 -0
- package/dist/scene/vehicleSeat.d.ts +68 -0
- package/dist/scene/vehicleSeat.js +59 -0
- package/dist/sensor/concealment.d.ts +3 -0
- package/dist/sensor/concealment.js +3 -0
- package/dist/sensor/freezeMonitor.d.ts +1 -0
- package/dist/sensor/freezeMonitor.js +1 -0
- package/dist/sensor/frustumSensor.d.ts +7 -3
- package/dist/sensor/frustumSensor.js +7 -3
- package/dist/sensor/hiddenStateProbe.d.ts +5 -2
- package/dist/sensor/hiddenStateProbe.js +5 -2
- package/dist/sensor/recordingBuffer.d.ts +2 -1
- package/dist/sensor/recordingBuffer.js +2 -1
- package/dist/sensor/replayLoop.d.ts +6 -2
- package/dist/sensor/replayLoop.js +6 -2
- package/dist/sensor/revealQuery.d.ts +2 -1
- package/dist/sensor/revealQuery.js +2 -1
- package/dist/sensor/visionCone.d.ts +10 -3
- package/dist/sensor/visionCone.js +10 -3
- package/dist/session/contestedChannel.d.ts +1 -0
- package/dist/session/contestedChannel.js +1 -0
- package/dist/session/extraction.d.ts +1 -0
- package/dist/session/extraction.js +1 -0
- package/dist/session/roles.d.ts +6 -0
- package/dist/session/roles.js +6 -0
- package/dist/session/roundState.d.ts +8 -0
- package/dist/session/roundState.js +2 -0
- package/dist/settings/settingsModel.d.ts +1 -0
- package/dist/settings/settingsModel.js +1 -0
- package/dist/stats/accumulatorMeter.d.ts +6 -0
- package/dist/stats/accumulatorMeter.js +6 -0
- package/dist/stats/eventMeter.d.ts +5 -0
- package/dist/stats/eventMeter.js +5 -0
- package/dist/stats/rollCheck.d.ts +5 -0
- package/dist/stats/rollCheck.js +5 -0
- package/dist/stats/spawnLevelStats.d.ts +110 -0
- package/dist/stats/spawnLevelStats.js +140 -0
- package/dist/stats/statModifiers.d.ts +5 -0
- package/dist/stats/statModifiers.js +5 -0
- package/dist/stats/statPool.d.ts +70 -0
- package/dist/stats/statPool.js +59 -0
- package/dist/store/changeSignal.d.ts +3 -0
- package/dist/store/changeSignal.js +2 -0
- package/dist/store/defineKeyedStore.d.ts +38 -0
- package/dist/store/defineKeyedStore.js +42 -0
- package/dist/store/defineStore.d.ts +33 -0
- package/dist/store/defineStore.js +35 -0
- package/dist/store/observableKeyedStore.d.ts +7 -0
- package/dist/store/observableKeyedStore.js +35 -2
- package/dist/survival/decayMeter.d.ts +55 -0
- package/dist/survival/decayMeter.js +130 -57
- package/dist/survival/moodle.d.ts +2 -0
- package/dist/survival/regionHealth.d.ts +6 -0
- package/dist/survival/regionHealth.js +6 -3
- package/dist/tactics/fallingGrid.d.ts +4 -2
- package/dist/tactics/fallingGrid.js +4 -2
- package/dist/tactics/predictiveQuery.d.ts +3 -0
- package/dist/tactics/predictiveQuery.js +3 -0
- package/dist/tactics/snapshot.d.ts +2 -0
- package/dist/tactics/snapshot.js +2 -0
- package/dist/tactics/surface.d.ts +1 -0
- package/dist/tactics/surface.js +1 -0
- package/dist/tactics/tacticalGrid.d.ts +1 -0
- package/dist/tactics/tacticalGrid.js +1 -0
- package/dist/time/beatClock.d.ts +14 -4
- package/dist/time/beatClock.js +14 -4
- package/dist/time/calendarClock.d.ts +3 -0
- package/dist/time/calendarClock.js +3 -0
- package/dist/time/idleProgress.d.ts +4 -0
- package/dist/time/idleProgress.js +4 -0
- package/dist/time/simClock.d.ts +2 -0
- package/dist/time/simClock.js +20 -5
- package/dist/ui/actionModel.d.ts +110 -0
- package/dist/ui/actionModel.js +159 -0
- package/dist/ui/gameLayout.d.ts +30 -11
- package/dist/ui/gameLayout.js +30 -11
- package/dist/ui/hudDocument.d.ts +114 -0
- package/dist/ui/hudDocument.js +220 -0
- package/dist/ui/hudLayout.d.ts +38 -1
- package/dist/ui/hudLayout.js +220 -17
- package/dist/ui/selectionModel.d.ts +92 -0
- package/dist/ui/selectionModel.js +88 -0
- package/dist/ui/tooltipModel.d.ts +63 -0
- package/dist/ui/tooltipModel.js +82 -0
- package/dist/ui.d.ts +15 -0
- package/dist/ui.js +15 -0
- package/dist/visibility/bounds.d.ts +8 -1
- package/dist/visibility/bounds.js +8 -1
- package/dist/visibility/frustum.d.ts +12 -3
- package/dist/visibility/frustum.js +12 -3
- package/dist/work/jobQueue.d.ts +201 -0
- package/dist/work/jobQueue.js +253 -0
- package/dist/work/unitTraining.d.ts +58 -0
- package/dist/work/unitTraining.js +52 -0
- package/dist/world/authoredEntities.d.ts +29 -0
- package/dist/world/authoredEntities.js +29 -0
- package/dist/world/authoredObjects.d.ts +72 -0
- package/dist/world/authoredObjects.js +81 -0
- package/dist/world/authoredSpawn.d.ts +39 -0
- package/dist/world/authoredSpawn.js +37 -0
- package/dist/world/buildSockets.d.ts +152 -0
- package/dist/world/buildSockets.js +188 -0
- package/dist/world/buildingGenerator.d.ts +18 -0
- package/dist/world/buildingGenerator.js +62 -0
- package/dist/world/buildings.d.ts +5 -0
- package/dist/world/buildings.js +5 -0
- package/dist/world/catenary.d.ts +22 -0
- package/dist/world/catenary.js +69 -0
- package/dist/world/cityBlocks.d.ts +152 -0
- package/dist/world/cityBlocks.js +670 -0
- package/dist/world/cityContent.d.ts +77 -0
- package/dist/world/cityContent.js +261 -0
- package/dist/world/cityGeometry.d.ts +114 -0
- package/dist/world/cityGeometry.js +573 -0
- package/dist/world/cityKind.d.ts +314 -0
- package/dist/world/cityKind.js +1578 -0
- package/dist/world/features.d.ts +133 -10
- package/dist/world/features.js +66 -6
- package/dist/world/footprintGrid.d.ts +59 -0
- package/dist/world/footprintGrid.js +141 -0
- package/dist/world/geometry.d.ts +64 -0
- package/dist/world/geometry.js +94 -0
- package/dist/world/grassKind.d.ts +51 -0
- package/dist/world/grassKind.js +101 -0
- package/dist/world/markers.d.ts +50 -4
- package/dist/world/markers.js +49 -0
- package/dist/world/massing.js +1 -1
- package/dist/world/minimapBake.d.ts +78 -0
- package/dist/world/minimapBake.js +208 -0
- package/dist/world/minimapTrack.d.ts +17 -0
- package/dist/world/minimapTrack.js +22 -0
- package/dist/world/pathInstances.d.ts +27 -0
- package/dist/world/pathInstances.js +27 -0
- package/dist/world/pathNetwork.d.ts +159 -0
- package/dist/world/pathNetwork.js +684 -0
- package/dist/world/pathTerrain.d.ts +80 -0
- package/dist/world/pathTerrain.js +142 -0
- package/dist/world/place.d.ts +166 -0
- package/dist/world/place.js +96 -0
- package/dist/world/placeAsset.d.ts +81 -0
- package/dist/world/placeAsset.js +79 -0
- package/dist/world/placement.d.ts +4 -0
- package/dist/world/placement.js +4 -0
- package/dist/world/placementController.d.ts +6 -0
- package/dist/world/placementController.js +6 -0
- package/dist/world/poleLineKind.d.ts +40 -0
- package/dist/world/poleLineKind.js +97 -0
- package/dist/world/polyline.d.ts +34 -0
- package/dist/world/polyline.js +88 -0
- package/dist/world/resourceNode.d.ts +109 -0
- package/dist/world/resourceNode.js +140 -0
- package/dist/world/roads.d.ts +8 -0
- package/dist/world/roads.js +38 -0
- package/dist/world/scatter.js +2 -20
- package/dist/world/scatterRegion.d.ts +164 -0
- package/dist/world/scatterRegion.js +409 -0
- package/dist/world/sceneShapes.d.ts +43 -0
- package/dist/world/sceneShapes.js +1 -0
- package/dist/world/segment.d.ts +27 -0
- package/dist/world/segment.js +43 -0
- package/dist/world/soilKind.d.ts +48 -0
- package/dist/world/soilKind.js +92 -0
- package/dist/world/spatialSample.d.ts +241 -0
- package/dist/world/spatialSample.js +465 -0
- package/dist/world/streets.d.ts +29 -0
- package/dist/world/streets.js +55 -0
- package/dist/world/terraform.d.ts +213 -1
- package/dist/world/terraform.js +627 -22
- package/dist/world/terrain.d.ts +164 -20
- package/dist/world/terrain.js +325 -41
- package/dist/world/terrainGuides.d.ts +182 -0
- package/dist/world/terrainGuides.js +343 -0
- package/dist/world/vec2.d.ts +81 -0
- package/dist/world/vec2.js +128 -0
- package/dist/world/vec3.d.ts +49 -0
- package/dist/world/vec3.js +76 -0
- package/dist/world/vegetation.d.ts +71 -0
- package/dist/world/vegetation.js +151 -0
- package/dist/world/visibilityField.d.ts +154 -0
- package/dist/world/visibilityField.js +271 -0
- package/dist/world/volumetricClouds.d.ts +52 -0
- package/dist/world/volumetricClouds.js +43 -0
- package/dist/world/walls.d.ts +9 -0
- package/dist/world/walls.js +9 -0
- package/dist/world/waterKind.d.ts +55 -0
- package/dist/world/waterKind.js +99 -0
- package/dist/world.d.ts +141 -0
- package/dist/world.js +141 -0
- package/package.json +32 -8
- package/skills/game-design/SKILL.md +28 -0
- package/skills/game-design/agents/openai.yaml +4 -0
- package/skills/game-design/references/application-playbook.md +170 -0
- package/skills/game-design/references/field-guide.md +288 -0
- package/skills/jgengine/SKILL.md +54 -0
- package/skills/jgengine/api.md +527 -0
- package/skills/jgengine/capabilities.md +131 -0
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-combat/SKILL.md +38 -0
- package/skills/jgengine-combat/api.md +585 -0
- package/skills/jgengine-combat/capabilities.md +213 -0
- package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
- package/skills/jgengine-combat/reference.md +108 -0
- package/skills/jgengine-gameplay/SKILL.md +39 -0
- package/skills/jgengine-gameplay/api.md +1920 -0
- package/skills/jgengine-gameplay/capabilities.md +454 -0
- package/skills/jgengine-gameplay/reference-systems.md +56 -0
- package/skills/jgengine-world/SKILL.md +51 -0
- package/skills/jgengine-world/api.md +3056 -0
- package/skills/jgengine-world/capabilities.md +476 -0
- package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
- package/skills/jgengine-world/reference.md +261 -0
- package/dist/cartridge/runtime.d.ts +0 -15
- package/dist/cartridge/runtime.js +0 -556
- package/dist/cartridge/spec.d.ts +0 -188
- package/dist/cartridge/spec.js +0 -19
- package/dist/cartridge/validate.d.ts +0 -2
- package/dist/cartridge/validate.js +0 -78
- package/dist/store/engineStore.d.ts +0 -22
- package/dist/store/engineStore.js +0 -50
- package/dist/store/features.d.ts +0 -10
- package/dist/store/features.js +0 -23
- package/llms.txt +0 -5389
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
import { pointInAabb } from "./geometry.js";
|
|
2
|
+
import { pointInPolygon, polygonBounds } from "./scatterRegion.js";
|
|
3
|
+
const DEFAULT_MAX_ATTEMPTS = 30;
|
|
4
|
+
const TWO_PI = Math.PI * 2;
|
|
5
|
+
function distanceSq(a, b) {
|
|
6
|
+
const n = a.length < b.length ? a.length : b.length;
|
|
7
|
+
let sum = 0;
|
|
8
|
+
for (let i = 0; i < n; i += 1) {
|
|
9
|
+
const d = a[i] - b[i];
|
|
10
|
+
sum += d * d;
|
|
11
|
+
}
|
|
12
|
+
return sum;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A uniform spatial hash over cells of `cellSize`, used to enforce minimum separation in O(1)
|
|
16
|
+
* neighborhood checks instead of an O(n²) scan — the allocation-aware index behind batch spacing.
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
class SeparationIndex {
|
|
20
|
+
cellSize;
|
|
21
|
+
dimensions;
|
|
22
|
+
buckets = new Map();
|
|
23
|
+
minSq;
|
|
24
|
+
constructor(cellSize, dimensions) {
|
|
25
|
+
this.cellSize = cellSize;
|
|
26
|
+
this.dimensions = dimensions;
|
|
27
|
+
this.minSq = cellSize * cellSize;
|
|
28
|
+
}
|
|
29
|
+
key(cell) {
|
|
30
|
+
return cell.join(":");
|
|
31
|
+
}
|
|
32
|
+
cellOf(point) {
|
|
33
|
+
const cell = [];
|
|
34
|
+
for (let i = 0; i < this.dimensions; i += 1)
|
|
35
|
+
cell.push(Math.floor(point[i] / this.cellSize));
|
|
36
|
+
return cell;
|
|
37
|
+
}
|
|
38
|
+
/** True when `point` sits within `cellSize` of any inserted point. */
|
|
39
|
+
tooClose(point) {
|
|
40
|
+
const base = this.cellOf(point);
|
|
41
|
+
const dims = this.dimensions;
|
|
42
|
+
const stack = [];
|
|
43
|
+
const walk = (axis) => {
|
|
44
|
+
if (axis === dims) {
|
|
45
|
+
const bucket = this.buckets.get(this.key(stack));
|
|
46
|
+
if (bucket !== undefined)
|
|
47
|
+
for (const other of bucket)
|
|
48
|
+
if (distanceSq(point, other) < this.minSq)
|
|
49
|
+
return true;
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
for (let d = -1; d <= 1; d += 1) {
|
|
53
|
+
stack[axis] = base[axis] + d;
|
|
54
|
+
if (walk(axis + 1))
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
};
|
|
59
|
+
return walk(0);
|
|
60
|
+
}
|
|
61
|
+
insert(point) {
|
|
62
|
+
const key = this.key(this.cellOf(point));
|
|
63
|
+
const bucket = this.buckets.get(key);
|
|
64
|
+
if (bucket !== undefined)
|
|
65
|
+
bucket.push(point);
|
|
66
|
+
else
|
|
67
|
+
this.buckets.set(key, [point]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function passesConstraints(point, constraints, index) {
|
|
71
|
+
if (constraints === undefined)
|
|
72
|
+
return index === null || !index.tooClose(point);
|
|
73
|
+
if (constraints.include !== undefined)
|
|
74
|
+
for (const region of constraints.include)
|
|
75
|
+
if (!region.contains(point))
|
|
76
|
+
return false;
|
|
77
|
+
if (constraints.exclude !== undefined)
|
|
78
|
+
for (const region of constraints.exclude)
|
|
79
|
+
if (region.contains(point))
|
|
80
|
+
return false;
|
|
81
|
+
if (index !== null && index.tooClose(point))
|
|
82
|
+
return false;
|
|
83
|
+
if (constraints.accept !== undefined && !constraints.accept(point))
|
|
84
|
+
return false;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
function resolveFallback(fallback, last, attempts, reason) {
|
|
88
|
+
if (fallback !== undefined && fallback !== "none") {
|
|
89
|
+
if (fallback === "last-candidate") {
|
|
90
|
+
if (last !== null)
|
|
91
|
+
return { ok: false, point: last, attempts, reason, usedFallback: true };
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
return { ok: false, point: fallback.point, attempts, reason, usedFallback: true };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { ok: false, point: null, attempts, reason, usedFallback: false };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Draw one point from `region` that clears every constraint, retrying up to `maxAttempts` times with
|
|
101
|
+
* the injected `rng`, then apply the `fallback` policy. Returns a structured {@link SampleResult} —
|
|
102
|
+
* a clean hit is `ok: true`; exhaustion or a degenerate region is reported with the attempt count and
|
|
103
|
+
* an explicit fallback flag, never a silently-accepted bad point.
|
|
104
|
+
*
|
|
105
|
+
* @capability spatial-sample draw one deterministic position from a region under include/exclude/distance constraints
|
|
106
|
+
*/
|
|
107
|
+
export function samplePoint(options) {
|
|
108
|
+
const { region, rng, constraints } = options;
|
|
109
|
+
const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
110
|
+
if (region.isEmpty)
|
|
111
|
+
return resolveFallback(options.fallback, null, 0, "empty-region");
|
|
112
|
+
let index = null;
|
|
113
|
+
const minSeparation = constraints?.minSeparation ?? 0;
|
|
114
|
+
const placed = options.placed ?? [];
|
|
115
|
+
if (minSeparation > 0 && placed.length > 0) {
|
|
116
|
+
index = new SeparationIndex(minSeparation, region.dimensions);
|
|
117
|
+
for (const point of placed)
|
|
118
|
+
index.insert(point);
|
|
119
|
+
}
|
|
120
|
+
let last = null;
|
|
121
|
+
let attempts = 0;
|
|
122
|
+
while (attempts < maxAttempts) {
|
|
123
|
+
attempts += 1;
|
|
124
|
+
let candidate = region.sample(rng);
|
|
125
|
+
if (constraints?.project !== undefined)
|
|
126
|
+
candidate = constraints.project(candidate);
|
|
127
|
+
if (candidate === null)
|
|
128
|
+
continue;
|
|
129
|
+
last = candidate;
|
|
130
|
+
if (passesConstraints(candidate, constraints, index)) {
|
|
131
|
+
return { ok: true, point: candidate, attempts, reason: "accepted", usedFallback: false };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return resolveFallback(options.fallback, last, attempts, "exhausted");
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Place up to `count` points from `region`, each clearing the shared constraints and honoring
|
|
138
|
+
* `minSeparation` against every point already placed in this batch (via a spatial hash, not an
|
|
139
|
+
* O(n²) scan). Order is deterministic for a given `rng` stream. Batches never silently under-fill:
|
|
140
|
+
* the result reports `placed`, `complete`, and the total attempt count.
|
|
141
|
+
*
|
|
142
|
+
* @capability spatial-sample-batch place many deterministic spaced points from a region with minimum separation
|
|
143
|
+
*/
|
|
144
|
+
export function sampleBatch(options) {
|
|
145
|
+
const { region, rng, constraints } = options;
|
|
146
|
+
const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
147
|
+
const requested = Math.max(0, Math.floor(options.count));
|
|
148
|
+
const points = [];
|
|
149
|
+
if (requested === 0 || region.isEmpty) {
|
|
150
|
+
return { points, requested, placed: 0, complete: requested === 0, attempts: 0 };
|
|
151
|
+
}
|
|
152
|
+
const minSeparation = constraints?.minSeparation ?? 0;
|
|
153
|
+
const index = minSeparation > 0 ? new SeparationIndex(minSeparation, region.dimensions) : null;
|
|
154
|
+
let attempts = 0;
|
|
155
|
+
for (let i = 0; i < requested; i += 1) {
|
|
156
|
+
let placed = null;
|
|
157
|
+
let tries = 0;
|
|
158
|
+
while (tries < maxAttempts) {
|
|
159
|
+
tries += 1;
|
|
160
|
+
attempts += 1;
|
|
161
|
+
let candidate = region.sample(rng);
|
|
162
|
+
if (constraints?.project !== undefined)
|
|
163
|
+
candidate = constraints.project(candidate);
|
|
164
|
+
if (candidate === null)
|
|
165
|
+
continue;
|
|
166
|
+
if (passesConstraints(candidate, constraints, index)) {
|
|
167
|
+
placed = candidate;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (placed === null)
|
|
172
|
+
break;
|
|
173
|
+
points.push(placed);
|
|
174
|
+
if (index !== null)
|
|
175
|
+
index.insert(placed);
|
|
176
|
+
}
|
|
177
|
+
return { points, requested, placed: points.length, complete: points.length === requested, attempts };
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* A fixed set of candidate points sampled by (optionally weighted) selection — the "spawn point
|
|
181
|
+
* table" region. `contains` is exact membership. Empty when the set is empty.
|
|
182
|
+
*
|
|
183
|
+
* @capability spatial-region-point-set sample from a fixed, optionally weighted candidate point table
|
|
184
|
+
*/
|
|
185
|
+
export function pointSetRegion(points, options = {}) {
|
|
186
|
+
const pool = points.map((p) => [p[0], p[1]]);
|
|
187
|
+
const weights = options.weights;
|
|
188
|
+
const total = weights === undefined ? pool.length : weights.reduce((sum, w) => sum + Math.max(0, w), 0);
|
|
189
|
+
return {
|
|
190
|
+
dimensions: 2,
|
|
191
|
+
isEmpty: pool.length === 0 || total <= 0,
|
|
192
|
+
sample(rng) {
|
|
193
|
+
if (weights === undefined)
|
|
194
|
+
return pool[Math.min(pool.length - 1, Math.floor(rng() * pool.length))];
|
|
195
|
+
let roll = rng() * total;
|
|
196
|
+
for (let i = 0; i < pool.length; i += 1) {
|
|
197
|
+
roll -= Math.max(0, weights[i] ?? 0);
|
|
198
|
+
if (roll <= 0)
|
|
199
|
+
return pool[i];
|
|
200
|
+
}
|
|
201
|
+
return pool[pool.length - 1];
|
|
202
|
+
},
|
|
203
|
+
contains(point) {
|
|
204
|
+
return pool.some((p) => p[0] === point[0] && p[1] === point[1]);
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* An axis-aligned rectangle on the XZ plane. `"uniform"` spreads evenly (draws x then z);
|
|
210
|
+
* `"edge"` biases onto a boundary band of `edgeThickness` meters (perimeter-weighted side, then
|
|
211
|
+
* inward depth) — the two are never conflated, the caller opts in.
|
|
212
|
+
*/
|
|
213
|
+
export function rectRegion(area, options = {}) {
|
|
214
|
+
const width = area.maxX - area.minX;
|
|
215
|
+
const depth = area.maxZ - area.minZ;
|
|
216
|
+
const distribution = options.distribution ?? "uniform";
|
|
217
|
+
const edgeThickness = Math.max(0, options.edgeThickness ?? Math.min(width, depth) * 0.25);
|
|
218
|
+
return {
|
|
219
|
+
dimensions: 2,
|
|
220
|
+
isEmpty: !(width > 0) || !(depth > 0),
|
|
221
|
+
sample(rng) {
|
|
222
|
+
if (distribution === "edge") {
|
|
223
|
+
const perim = 2 * (width + depth);
|
|
224
|
+
const sidePick = rng() * perim;
|
|
225
|
+
const t = rng();
|
|
226
|
+
const inset = Math.min(edgeThickness, Math.min(width, depth) / 2) * rng();
|
|
227
|
+
if (sidePick < width)
|
|
228
|
+
return [area.minX + t * width, area.minZ + inset];
|
|
229
|
+
if (sidePick < width + depth)
|
|
230
|
+
return [area.maxX - inset, area.minZ + t * depth];
|
|
231
|
+
if (sidePick < 2 * width + depth)
|
|
232
|
+
return [area.minX + t * width, area.maxZ - inset];
|
|
233
|
+
return [area.minX + inset, area.minZ + t * depth];
|
|
234
|
+
}
|
|
235
|
+
const x = area.minX + rng() * width;
|
|
236
|
+
const z = area.minZ + rng() * depth;
|
|
237
|
+
return [x, z];
|
|
238
|
+
},
|
|
239
|
+
contains(point) {
|
|
240
|
+
return pointInAabb(point, area);
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function radialRadius(rng, inner, outer, distribution) {
|
|
245
|
+
const u = rng();
|
|
246
|
+
if (distribution === "area")
|
|
247
|
+
return Math.sqrt(inner * inner + u * (outer * outer - inner * inner));
|
|
248
|
+
return inner + u * (outer - inner);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* A filled circle. `"area"` is area-uniform (√-corrected radius, even density); `"radial"` is
|
|
252
|
+
* radius-uniform (clumps toward the center). Angle is drawn first, then radius — matching the common
|
|
253
|
+
* `angle = rng()·2π; r = rng()·R` idiom so migrations keep their stream.
|
|
254
|
+
*/
|
|
255
|
+
export function discRegion(center, radius, options = {}) {
|
|
256
|
+
const distribution = options.distribution ?? "area";
|
|
257
|
+
const r = Math.max(0, radius);
|
|
258
|
+
return {
|
|
259
|
+
dimensions: 2,
|
|
260
|
+
isEmpty: !(r > 0),
|
|
261
|
+
sample(rng) {
|
|
262
|
+
const angle = rng() * TWO_PI;
|
|
263
|
+
const dist = radialRadius(rng, 0, r, distribution);
|
|
264
|
+
return [center[0] + Math.cos(angle) * dist, center[1] + Math.sin(angle) * dist];
|
|
265
|
+
},
|
|
266
|
+
contains(point) {
|
|
267
|
+
return distanceSq(point, center) <= r * r;
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* A ring (annulus) between `innerRadius` and `outerRadius`. `"area"` fills the band with even
|
|
273
|
+
* density; `"radial"` spreads uniformly in radius. Angle first, then radius.
|
|
274
|
+
*/
|
|
275
|
+
export function annulusRegion(center, innerRadius, outerRadius, options = {}) {
|
|
276
|
+
const distribution = options.distribution ?? "area";
|
|
277
|
+
const inner = Math.max(0, Math.min(innerRadius, outerRadius));
|
|
278
|
+
const outer = Math.max(innerRadius, outerRadius, 0);
|
|
279
|
+
return {
|
|
280
|
+
dimensions: 2,
|
|
281
|
+
isEmpty: !(outer > 0) || outer <= inner,
|
|
282
|
+
sample(rng) {
|
|
283
|
+
const angle = rng() * TWO_PI;
|
|
284
|
+
const dist = radialRadius(rng, inner, outer, distribution);
|
|
285
|
+
return [center[0] + Math.cos(angle) * dist, center[1] + Math.sin(angle) * dist];
|
|
286
|
+
},
|
|
287
|
+
contains(point) {
|
|
288
|
+
const d2 = distanceSq(point, center);
|
|
289
|
+
return d2 >= inner * inner && d2 <= outer * outer;
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* An arbitrary closed polygon on the XZ plane. Candidates are drawn uniformly from the polygon's
|
|
295
|
+
* bounding box and gated by point-in-polygon `contains`, so a run's draw count stays fixed (the
|
|
296
|
+
* sampler's attempt budget bounds the rejection, not a hidden inner loop).
|
|
297
|
+
*
|
|
298
|
+
* @capability spatial-region-polygon sample within an arbitrary closed polygon on the XZ plane
|
|
299
|
+
*/
|
|
300
|
+
export function polygonRegion(polygon) {
|
|
301
|
+
const bounds = polygonBounds(polygon);
|
|
302
|
+
const width = bounds === null ? 0 : bounds.maxX - bounds.minX;
|
|
303
|
+
const depth = bounds === null ? 0 : bounds.maxZ - bounds.minZ;
|
|
304
|
+
return {
|
|
305
|
+
dimensions: 2,
|
|
306
|
+
isEmpty: bounds === null || polygon.length < 3 || !(width > 0) || !(depth > 0),
|
|
307
|
+
sample(rng) {
|
|
308
|
+
const b = bounds ?? { minX: 0, minZ: 0, maxX: 0, maxZ: 0 };
|
|
309
|
+
return [b.minX + rng() * width, b.minZ + rng() * depth];
|
|
310
|
+
},
|
|
311
|
+
contains(point) {
|
|
312
|
+
return pointInPolygon(point, polygon);
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* A composite that first picks one member by weight, then delegates to its sampler — the
|
|
318
|
+
* "weighted subregions" distribution policy. `contains` is true when any member contains the point.
|
|
319
|
+
*
|
|
320
|
+
* @capability spatial-region-weighted compose sub-regions behind a weighted selection policy
|
|
321
|
+
*/
|
|
322
|
+
export function weightedRegion(entries) {
|
|
323
|
+
const usable = entries.filter((e) => e.weight > 0 && !e.region.isEmpty);
|
|
324
|
+
const total = usable.reduce((sum, e) => sum + e.weight, 0);
|
|
325
|
+
const dimensions = entries[0]?.region.dimensions ?? 2;
|
|
326
|
+
return {
|
|
327
|
+
dimensions,
|
|
328
|
+
isEmpty: usable.length === 0,
|
|
329
|
+
sample(rng) {
|
|
330
|
+
let roll = rng() * total;
|
|
331
|
+
for (const entry of usable) {
|
|
332
|
+
roll -= entry.weight;
|
|
333
|
+
if (roll <= 0)
|
|
334
|
+
return entry.region.sample(rng);
|
|
335
|
+
}
|
|
336
|
+
return usable[usable.length - 1].region.sample(rng);
|
|
337
|
+
},
|
|
338
|
+
contains(point) {
|
|
339
|
+
return entries.some((e) => e.region.contains(point));
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Wrap a caller-defined sampler and bounds test as a {@link SampleRegion} — the escape hatch for
|
|
345
|
+
* regions the built-ins do not cover (a navmesh cell, a heightfield mask, a spline tube).
|
|
346
|
+
*
|
|
347
|
+
* @capability spatial-region-custom wrap a caller-defined sampler and bounds test as a region
|
|
348
|
+
*/
|
|
349
|
+
export function customRegion(spec) {
|
|
350
|
+
return {
|
|
351
|
+
dimensions: spec.dimensions,
|
|
352
|
+
isEmpty: spec.isEmpty ?? false,
|
|
353
|
+
sample: spec.sample,
|
|
354
|
+
contains: spec.contains,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
// ---------------------------------------------------------------------------
|
|
358
|
+
// 3D region builders
|
|
359
|
+
// ---------------------------------------------------------------------------
|
|
360
|
+
/**
|
|
361
|
+
* An axis-aligned box `[min..max]` in 3D. Uniform density; draws x, y, z in order.
|
|
362
|
+
*
|
|
363
|
+
* @capability spatial-region-box sample uniformly within an axis-aligned 3D box
|
|
364
|
+
*/
|
|
365
|
+
export function boxRegion(min, max) {
|
|
366
|
+
const size = [max[0] - min[0], max[1] - min[1], max[2] - min[2]];
|
|
367
|
+
return {
|
|
368
|
+
dimensions: 3,
|
|
369
|
+
isEmpty: !(size[0] > 0) || !(size[1] > 0) || !(size[2] > 0),
|
|
370
|
+
sample(rng) {
|
|
371
|
+
return [min[0] + rng() * size[0], min[1] + rng() * size[1], min[2] + rng() * size[2]];
|
|
372
|
+
},
|
|
373
|
+
contains(point) {
|
|
374
|
+
return (point[0] >= min[0] && point[0] <= max[0] &&
|
|
375
|
+
point[1] >= min[1] && point[1] <= max[1] &&
|
|
376
|
+
point[2] >= min[2] && point[2] <= max[2]);
|
|
377
|
+
},
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function sphereDirection(rng) {
|
|
381
|
+
const cosTheta = 1 - 2 * rng();
|
|
382
|
+
const sinTheta = Math.sqrt(Math.max(0, 1 - cosTheta * cosTheta));
|
|
383
|
+
const phi = rng() * TWO_PI;
|
|
384
|
+
return [sinTheta * Math.cos(phi), sinTheta * Math.sin(phi), cosTheta];
|
|
385
|
+
}
|
|
386
|
+
function volumeRadius(rng, inner, outer, distribution) {
|
|
387
|
+
const u = rng();
|
|
388
|
+
if (distribution === "volume")
|
|
389
|
+
return Math.cbrt(inner ** 3 + u * (outer ** 3 - inner ** 3));
|
|
390
|
+
return inner + u * (outer - inner);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* A filled ball. `"volume"` is volume-uniform (∛-corrected radius); `"radial"` is radius-uniform.
|
|
394
|
+
* Direction is drawn first (two draws), then radius.
|
|
395
|
+
*
|
|
396
|
+
* @capability spatial-region-sphere sample within a filled 3D ball, volume- or radius-uniform
|
|
397
|
+
*/
|
|
398
|
+
export function sphereRegion(center, radius, options = {}) {
|
|
399
|
+
const distribution = options.distribution ?? "volume";
|
|
400
|
+
const r = Math.max(0, radius);
|
|
401
|
+
return {
|
|
402
|
+
dimensions: 3,
|
|
403
|
+
isEmpty: !(r > 0),
|
|
404
|
+
sample(rng) {
|
|
405
|
+
const dir = sphereDirection(rng);
|
|
406
|
+
const dist = volumeRadius(rng, 0, r, distribution);
|
|
407
|
+
return [center[0] + dir[0] * dist, center[1] + dir[1] * dist, center[2] + dir[2] * dist];
|
|
408
|
+
},
|
|
409
|
+
contains(point) {
|
|
410
|
+
return distanceSq(point, center) <= r * r;
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* A spherical shell between `innerRadius` and `outerRadius`. `"volume"` fills the shell with even
|
|
416
|
+
* density; `"radial"` spreads uniformly in radius. Direction first, then radius.
|
|
417
|
+
*
|
|
418
|
+
* @capability spatial-region-shell sample within a 3D spherical shell, volume- or radius-uniform
|
|
419
|
+
*/
|
|
420
|
+
export function shellRegion(center, innerRadius, outerRadius, options = {}) {
|
|
421
|
+
const distribution = options.distribution ?? "volume";
|
|
422
|
+
const inner = Math.max(0, Math.min(innerRadius, outerRadius));
|
|
423
|
+
const outer = Math.max(innerRadius, outerRadius, 0);
|
|
424
|
+
return {
|
|
425
|
+
dimensions: 3,
|
|
426
|
+
isEmpty: !(outer > 0) || outer <= inner,
|
|
427
|
+
sample(rng) {
|
|
428
|
+
const dir = sphereDirection(rng);
|
|
429
|
+
const dist = volumeRadius(rng, inner, outer, distribution);
|
|
430
|
+
return [center[0] + dir[0] * dist, center[1] + dir[1] * dist, center[2] + dir[2] * dist];
|
|
431
|
+
},
|
|
432
|
+
contains(point) {
|
|
433
|
+
const d2 = distanceSq(point, center);
|
|
434
|
+
return d2 >= inner * inner && d2 <= outer * outer;
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Stratified 2D sampling: one jittered point per grid cell over `area`, in deterministic row-major
|
|
440
|
+
* order. Unlike pure rejection sampling this guarantees even coverage (no clumps, no gaps) — the
|
|
441
|
+
* distinct "stratified" distribution policy, kept separate from area-uniform draws.
|
|
442
|
+
*
|
|
443
|
+
* @capability spatial-sample-stratified evenly cover an area with one jittered point per grid cell, deterministic
|
|
444
|
+
*/
|
|
445
|
+
export function sampleStratified(options) {
|
|
446
|
+
const { area, rng } = options;
|
|
447
|
+
const cols = Math.max(0, Math.floor(options.cols));
|
|
448
|
+
const rows = Math.max(0, Math.floor(options.rows));
|
|
449
|
+
const width = area.maxX - area.minX;
|
|
450
|
+
const depth = area.maxZ - area.minZ;
|
|
451
|
+
if (cols === 0 || rows === 0 || !(width > 0) || !(depth > 0))
|
|
452
|
+
return [];
|
|
453
|
+
const jitter = Math.min(1, Math.max(0, options.jitter ?? 1));
|
|
454
|
+
const cellW = width / cols;
|
|
455
|
+
const cellD = depth / rows;
|
|
456
|
+
const points = [];
|
|
457
|
+
for (let row = 0; row < rows; row += 1) {
|
|
458
|
+
for (let col = 0; col < cols; col += 1) {
|
|
459
|
+
const jx = 0.5 + jitter * (rng() - 0.5);
|
|
460
|
+
const jz = 0.5 + jitter * (rng() - 0.5);
|
|
461
|
+
points.push([area.minX + (col + jx) * cellW, area.minZ + (row + jz) * cellD]);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return points;
|
|
465
|
+
}
|
package/dist/world/streets.d.ts
CHANGED
|
@@ -73,6 +73,35 @@ export interface ParkingSpot {
|
|
|
73
73
|
* coordinates in the middle of the carriageway.
|
|
74
74
|
*/
|
|
75
75
|
export declare function parkingSpots(road: RoadEnvironmentDescriptor, options?: ParkingSpotOptions): readonly ParkingSpot[];
|
|
76
|
+
/**
|
|
77
|
+
* Signed planar distance from `(x, z)` to the nearest road *surface edge* across every segment of
|
|
78
|
+
* every road (#1051): negative inside the asphalt (magnitude = how far in from the closest edge, so
|
|
79
|
+
* `-width/2` on the centerline), `~0` right at the curb, and positive off the road (the gap to the
|
|
80
|
+
* nearest edge). Point-to-segment distance minus the road's half width, minimised over all segments —
|
|
81
|
+
* the "am I on the road, and by how much" seam driving grip, tyre audio, and off-road penalties.
|
|
82
|
+
*
|
|
83
|
+
* Allocation-free per call (only scalars — no arrays or objects) so a per-tick car sim can sample it
|
|
84
|
+
* on the hot path; degenerate roads (fewer than two path points) contribute nothing, and with no road
|
|
85
|
+
* surface at all it returns {@link Number.POSITIVE_INFINITY} (everywhere is off-road).
|
|
86
|
+
*/
|
|
87
|
+
export declare function distanceToRoadEdge(roads: readonly RoadEnvironmentDescriptor[], x: number, z: number): number;
|
|
88
|
+
/** Grip levels and blend width for {@link roadSurfaceSampler}; each field is optional and defaulted. */
|
|
89
|
+
export interface RoadSurfaceOptions {
|
|
90
|
+
/** Grip multiplier on the asphalt. Default 1. */
|
|
91
|
+
onRoad?: number;
|
|
92
|
+
/** Grip multiplier once fully off the road past the shoulder. Default 0.72. */
|
|
93
|
+
offRoad?: number;
|
|
94
|
+
/** Width (world units) of the blend band outside the curb from full to off-road grip. Default 3. */
|
|
95
|
+
shoulder?: number;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* A `surfaceFriction`-compatible sampler (the `(x, z) => grip` hook a kinematic car reads each tick)
|
|
99
|
+
* that turns road geometry into grip (#1051): full `onRoad` grip on the asphalt, a monotonic linear ramp
|
|
100
|
+
* down across a `shoulder`-wide band at the curb, and flat `offRoad` grip beyond it — so a car that
|
|
101
|
+
* clips onto the grass loses bite progressively instead of snapping. Closes over {@link
|
|
102
|
+
* distanceToRoadEdge}, so the returned sampler is itself allocation-free per call.
|
|
103
|
+
*/
|
|
104
|
+
export declare function roadSurfaceSampler(roads: readonly RoadEnvironmentDescriptor[], options?: RoadSurfaceOptions): (x: number, z: number) => number;
|
|
76
105
|
/**
|
|
77
106
|
* A deterministic point on one of a road's sidewalks at a normalized position — `side` picks the
|
|
78
107
|
* band, `fraction` (0..1) picks how far along. The canonical pedestrian spawn helper.
|
package/dist/world/streets.js
CHANGED
|
@@ -130,6 +130,61 @@ export function parkingSpots(road, options = {}) {
|
|
|
130
130
|
}
|
|
131
131
|
return spots;
|
|
132
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Signed planar distance from `(x, z)` to the nearest road *surface edge* across every segment of
|
|
135
|
+
* every road (#1051): negative inside the asphalt (magnitude = how far in from the closest edge, so
|
|
136
|
+
* `-width/2` on the centerline), `~0` right at the curb, and positive off the road (the gap to the
|
|
137
|
+
* nearest edge). Point-to-segment distance minus the road's half width, minimised over all segments —
|
|
138
|
+
* the "am I on the road, and by how much" seam driving grip, tyre audio, and off-road penalties.
|
|
139
|
+
*
|
|
140
|
+
* Allocation-free per call (only scalars — no arrays or objects) so a per-tick car sim can sample it
|
|
141
|
+
* on the hot path; degenerate roads (fewer than two path points) contribute nothing, and with no road
|
|
142
|
+
* surface at all it returns {@link Number.POSITIVE_INFINITY} (everywhere is off-road).
|
|
143
|
+
*/
|
|
144
|
+
export function distanceToRoadEdge(roads, x, z) {
|
|
145
|
+
let best = Number.POSITIVE_INFINITY;
|
|
146
|
+
for (let r = 0; r < roads.length; r += 1) {
|
|
147
|
+
const road = roads[r];
|
|
148
|
+
const path = road.path;
|
|
149
|
+
if (path.length < 2)
|
|
150
|
+
continue;
|
|
151
|
+
const half = road.width / 2;
|
|
152
|
+
for (let i = 0; i < path.length - 1; i += 1) {
|
|
153
|
+
const a = path[i];
|
|
154
|
+
const b = path[i + 1];
|
|
155
|
+
const abx = b[0] - a[0];
|
|
156
|
+
const abz = b[1] - a[1];
|
|
157
|
+
const lengthSq = abx * abx + abz * abz;
|
|
158
|
+
const t = lengthSq === 0 ? 0 : Math.max(0, Math.min(1, ((x - a[0]) * abx + (z - a[1]) * abz) / lengthSq));
|
|
159
|
+
const px = a[0] + abx * t;
|
|
160
|
+
const pz = a[1] + abz * t;
|
|
161
|
+
const edge = Math.hypot(x - px, z - pz) - half;
|
|
162
|
+
if (edge < best)
|
|
163
|
+
best = edge;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return best;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* A `surfaceFriction`-compatible sampler (the `(x, z) => grip` hook a kinematic car reads each tick)
|
|
170
|
+
* that turns road geometry into grip (#1051): full `onRoad` grip on the asphalt, a monotonic linear ramp
|
|
171
|
+
* down across a `shoulder`-wide band at the curb, and flat `offRoad` grip beyond it — so a car that
|
|
172
|
+
* clips onto the grass loses bite progressively instead of snapping. Closes over {@link
|
|
173
|
+
* distanceToRoadEdge}, so the returned sampler is itself allocation-free per call.
|
|
174
|
+
*/
|
|
175
|
+
export function roadSurfaceSampler(roads, options = {}) {
|
|
176
|
+
const onRoad = options.onRoad ?? 1;
|
|
177
|
+
const offRoad = options.offRoad ?? 0.72;
|
|
178
|
+
const shoulder = options.shoulder ?? 3;
|
|
179
|
+
return (x, z) => {
|
|
180
|
+
const edge = distanceToRoadEdge(roads, x, z);
|
|
181
|
+
if (edge <= 0)
|
|
182
|
+
return onRoad;
|
|
183
|
+
if (shoulder <= 0 || edge >= shoulder)
|
|
184
|
+
return offRoad;
|
|
185
|
+
return onRoad + (offRoad - onRoad) * (edge / shoulder);
|
|
186
|
+
};
|
|
187
|
+
}
|
|
133
188
|
/**
|
|
134
189
|
* A deterministic point on one of a road's sidewalks at a normalized position — `side` picks the
|
|
135
190
|
* band, `fraction` (0..1) picks how far along. The canonical pedestrian spawn helper.
|