@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
package/dist/world/features.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { BuildingPaletteOverrides, BuildingStyle } from "./buildings.js";
|
|
2
|
+
import type { AvoidZone } from "./geometry.js";
|
|
3
|
+
import type { TerrainPathProfile } from "./pathTerrain.js";
|
|
4
|
+
import type { PlaceWorldFeature } from "./place.js";
|
|
5
|
+
import type { TerraformSnapshot } from "./terraform.js";
|
|
6
|
+
import type { VolumetricCloudsConfig } from "./volumetricClouds.js";
|
|
2
7
|
export interface WorldBounds {
|
|
3
8
|
w: number;
|
|
4
9
|
d: number;
|
|
@@ -42,6 +47,35 @@ export interface TerrainDetailConfig {
|
|
|
42
47
|
roughness?: number;
|
|
43
48
|
/** Overall detail intensity 0..1. Default 1. */
|
|
44
49
|
strength?: number;
|
|
50
|
+
/** Real PBR texture maps blended over the procedural detail — the seam for `@jgengine/assets` `buildMaterialCatalog` output. Omit to keep the procedural-only look. */
|
|
51
|
+
material?: TerrainDetailMaterialConfig;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* PBR map URLs for a real ground texture — the same shape
|
|
55
|
+
* `buildMaterialCatalog({ basePath }).resolve(id)!.maps` from `@jgengine/assets` returns. Kept
|
|
56
|
+
* dependency-free here so `core` never imports the assets package; any URLs (pulled maps, a CDN, a
|
|
57
|
+
* data URI) satisfy it.
|
|
58
|
+
*/
|
|
59
|
+
export interface TerrainMaterialMaps {
|
|
60
|
+
color: string;
|
|
61
|
+
normal: string;
|
|
62
|
+
roughness: string;
|
|
63
|
+
ao: string;
|
|
64
|
+
displacement: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Real PBR texture applied over the ground surface — the seam that lets a game put a
|
|
68
|
+
* `buildMaterialCatalog` material on terrain. Blends with, never replaces, the procedural detail
|
|
69
|
+
* shader: color/roughness/ao tile the maps by world position, `strength` fades them over the
|
|
70
|
+
* existing vertex-colour + noise look.
|
|
71
|
+
*/
|
|
72
|
+
export interface TerrainDetailMaterialConfig {
|
|
73
|
+
/** e.g. `buildMaterialCatalog({ basePath: "/materials" }).resolve("material/grass")!.maps`. */
|
|
74
|
+
maps: TerrainMaterialMaps;
|
|
75
|
+
/** World units per texture tile; smaller tiles the texture more densely. Default 4. */
|
|
76
|
+
repeat?: number;
|
|
77
|
+
/** Blend strength of the texture over the procedural/vertex-colour base, 0..1. Default 1. */
|
|
78
|
+
strength?: number;
|
|
45
79
|
}
|
|
46
80
|
export interface TerrainFlattenMask {
|
|
47
81
|
center: EnvironmentVec2;
|
|
@@ -88,11 +122,26 @@ export interface TerrainRectRegion extends TerrainRegionStyle {
|
|
|
88
122
|
* and blend back across `falloff`; later regions in the list win overlaps.
|
|
89
123
|
*/
|
|
90
124
|
export type TerrainMaterialRegion = TerrainCircleRegion | TerrainPolylineRegion | TerrainRectRegion;
|
|
125
|
+
/** Per-band fog override cross-faded along z by `createBiomeFogSampler`; unset fields fall through to the base sky fog. */
|
|
126
|
+
export interface BiomeFog {
|
|
127
|
+
color?: string;
|
|
128
|
+
near?: number;
|
|
129
|
+
far?: number;
|
|
130
|
+
density?: number;
|
|
131
|
+
}
|
|
132
|
+
/** Per-band sky/light override cross-faded along z by `createBiomeSkySampler`; unset fields fall through to the base sky. */
|
|
133
|
+
export interface BiomeSky {
|
|
134
|
+
horizonColor?: string;
|
|
135
|
+
zenithColor?: string;
|
|
136
|
+
sunIntensity?: number;
|
|
137
|
+
ambientIntensity?: number;
|
|
138
|
+
}
|
|
91
139
|
/**
|
|
92
140
|
* A z-ordered ground palette zone — the linear-boundary counterpart to the radial `materialRegions`.
|
|
93
141
|
* Adjacent bands cross-fade into each other across a `fade`-wide window centered on the midpoint z
|
|
94
142
|
* between their centers, so a multi-biome world (vale → marsh → peaks along z) blends its ground
|
|
95
|
-
* color instead of hard-switching.
|
|
143
|
+
* color instead of hard-switching. Bands may also carry per-zone `fog`, `sky`, and `weather`. Order
|
|
144
|
+
* the list by ascending `z`.
|
|
96
145
|
*/
|
|
97
146
|
export interface BiomeBand {
|
|
98
147
|
/** World-space center z of the zone. */
|
|
@@ -103,6 +152,12 @@ export interface BiomeBand {
|
|
|
103
152
|
material?: TerrainMaterial;
|
|
104
153
|
/** Explicit low/high/waterline hex colors for the zone. */
|
|
105
154
|
colors?: TerrainColors;
|
|
155
|
+
/** Fog color/near/far/density for the zone, cross-faded per camera z; unset fields keep the base sky fog. */
|
|
156
|
+
fog?: BiomeFog;
|
|
157
|
+
/** Sky horizon/zenith colors and sun/ambient intensity for the zone, cross-faded per camera z; unset fields keep the base sky. */
|
|
158
|
+
sky?: BiomeSky;
|
|
159
|
+
/** Precipitation covering the zone — expands into a full-width weather strip centered at `[0, z]`, `fade`-deep. */
|
|
160
|
+
weather?: "rain" | "snow";
|
|
106
161
|
}
|
|
107
162
|
export interface TerrainEnvironmentConfig {
|
|
108
163
|
bounds?: WorldBounds;
|
|
@@ -131,22 +186,50 @@ export interface TerrainEnvironmentConfig {
|
|
|
131
186
|
waterLevel?: number;
|
|
132
187
|
/** Flat pads carved into the noise field, e.g. for building pads or spawn circles. */
|
|
133
188
|
flatten?: readonly TerrainFlattenMask[];
|
|
189
|
+
/** Authored path profiles that flatten/grade/carve the heightfield along a centerline (roads, rivers, ramps) with optional retaining walls. Applied after `flatten`. */
|
|
190
|
+
pathProfiles?: readonly TerrainPathProfile[];
|
|
134
191
|
/** Procedural detail surface (noise-driven rock/sand/snow over the biome base). Omit for the flat vertex-colour ground. */
|
|
135
192
|
detail?: TerrainDetailConfig;
|
|
136
193
|
}
|
|
137
194
|
export interface RainEnvironmentConfig {
|
|
195
|
+
/**
|
|
196
|
+
* `w`/`d`/`h` size a wrap-volume of raindrops **anchored to and re-centered on the camera every
|
|
197
|
+
* frame** — not a world-space region. `area.position` (and the `position` sugar below) has **no
|
|
198
|
+
* visual effect** on rain/snow: the shell's `RainField`/`SnowField` always run `followCamera` and
|
|
199
|
+
* never apply the mesh's transform, only `camera.position`. Keep `w`/`d`/`h` near camera scale
|
|
200
|
+
* (roughly 50-120 per axis) so drops stay a visible size at normal view distance — sizing the
|
|
201
|
+
* volume to a world region (e.g. matching a district's footprint) spreads the same drop count
|
|
202
|
+
* across that much more space until they're sub-pixel and the storm reads as empty sky, even
|
|
203
|
+
* though `summarizeEnvironment` shows the layer exists. Reach for `density`, `width`, and `opacity`
|
|
204
|
+
* to make a storm read heavier/taller instead of enlarging `area`.
|
|
205
|
+
*/
|
|
138
206
|
area?: EnvironmentArea;
|
|
139
|
-
/** World-space center `[x, z]` of the band, matching `building()`/`ocean()` — sugar for `area.position
|
|
207
|
+
/** World-space center `[x, z]` of the band, matching `building()`/`ocean()` — sugar for `area.position`. No visual effect on rain/snow (see `area`); kept for API symmetry with other weather-adjacent features. */
|
|
140
208
|
position?: EnvironmentVec2;
|
|
141
209
|
density?: number;
|
|
142
210
|
speed?: number;
|
|
143
211
|
dropLength?: number;
|
|
144
212
|
wind?: EnvironmentVec2;
|
|
145
213
|
color?: string;
|
|
214
|
+
/** Streak width of each raindrop quad, in world units. Default 0.018 — raise for a heavier-reading storm without enlarging `area`. */
|
|
215
|
+
width?: number;
|
|
216
|
+
/** Drop opacity, 0-1. Default 0.48 — raise for a denser-reading storm without enlarging `area`. */
|
|
217
|
+
opacity?: number;
|
|
146
218
|
}
|
|
147
219
|
export interface SnowEnvironmentConfig {
|
|
220
|
+
/**
|
|
221
|
+
* `w`/`d`/`h` size a wrap-volume of snowflakes **anchored to and re-centered on the camera every
|
|
222
|
+
* frame** — not a world-space region. `area.position` (and the `position` sugar below) has **no
|
|
223
|
+
* visual effect** on rain/snow: the shell's `RainField`/`SnowField` always run `followCamera` and
|
|
224
|
+
* never apply the mesh's transform, only `camera.position`. Keep `w`/`d`/`h` near camera scale
|
|
225
|
+
* (roughly 50-120 per axis) so flakes stay a visible size at normal view distance — sizing the
|
|
226
|
+
* volume to a world region (e.g. matching a district's footprint) spreads the same flake count
|
|
227
|
+
* across that much more space until they're sub-pixel and the storm reads as empty sky, even
|
|
228
|
+
* though `summarizeEnvironment` shows the layer exists. Reach for `density`, `flakeSize`, and
|
|
229
|
+
* `opacity` to make a storm read heavier instead of enlarging `area`.
|
|
230
|
+
*/
|
|
148
231
|
area?: EnvironmentArea;
|
|
149
|
-
/** World-space center `[x, z]` of the band, matching `building()`/`ocean()` — sugar for `area.position
|
|
232
|
+
/** World-space center `[x, z]` of the band, matching `building()`/`ocean()` — sugar for `area.position`. No visual effect on rain/snow (see `area`); kept for API symmetry with other weather-adjacent features. */
|
|
150
233
|
position?: EnvironmentVec2;
|
|
151
234
|
density?: number;
|
|
152
235
|
speed?: number;
|
|
@@ -154,6 +237,8 @@ export interface SnowEnvironmentConfig {
|
|
|
154
237
|
drift?: number;
|
|
155
238
|
wind?: EnvironmentVec2;
|
|
156
239
|
color?: string;
|
|
240
|
+
/** Flake opacity, 0-1. Default 0.86 — raise for a denser-reading storm without enlarging `area`. */
|
|
241
|
+
opacity?: number;
|
|
157
242
|
}
|
|
158
243
|
export interface GrassEnvironmentConfig {
|
|
159
244
|
area?: EnvironmentArea;
|
|
@@ -192,11 +277,19 @@ export interface SkyEnvironmentConfig {
|
|
|
192
277
|
zenithColor?: string;
|
|
193
278
|
sunIntensity?: number;
|
|
194
279
|
ambientIntensity?: number;
|
|
280
|
+
/** Sky-dome sphere radius in world units. Enlarge for a playfield sited far from the origin so the viewer never exits the dome. Default 260. */
|
|
281
|
+
radius?: number;
|
|
282
|
+
/** Horizon haze-band strength: 0 removes the dusty band, ~1 makes it heavy. Default 0.5. */
|
|
283
|
+
hazeStrength?: number;
|
|
284
|
+
/** Sun-glow brightness multiplier around the sun disc. Default 1. */
|
|
285
|
+
sunGlowStrength?: number;
|
|
195
286
|
fog?: {
|
|
196
287
|
color?: string;
|
|
197
288
|
near?: number;
|
|
198
289
|
far?: number;
|
|
199
290
|
};
|
|
291
|
+
/** Raymarched volumetric cloud layer over the sky dome. Off by default — omit for no clouds. */
|
|
292
|
+
volumetricClouds?: VolumetricCloudsConfig;
|
|
200
293
|
}
|
|
201
294
|
export interface BuildingEnvironmentConfig {
|
|
202
295
|
count?: number;
|
|
@@ -239,10 +332,10 @@ export type TerrainIslandDescriptor = Omit<TerrainEnvironmentDescriptor, "kind">
|
|
|
239
332
|
};
|
|
240
333
|
export type RainEnvironmentDescriptor = {
|
|
241
334
|
kind: "rain";
|
|
242
|
-
} & Required<Pick<RainEnvironmentConfig, "area" | "density" | "speed" | "dropLength" | "wind" | "color">>;
|
|
335
|
+
} & Required<Pick<RainEnvironmentConfig, "area" | "density" | "speed" | "dropLength" | "wind" | "color" | "width" | "opacity">>;
|
|
243
336
|
export type SnowEnvironmentDescriptor = {
|
|
244
337
|
kind: "snow";
|
|
245
|
-
} & Required<Pick<SnowEnvironmentConfig, "area" | "density" | "speed" | "flakeSize" | "drift" | "wind" | "color">>;
|
|
338
|
+
} & Required<Pick<SnowEnvironmentConfig, "area" | "density" | "speed" | "flakeSize" | "drift" | "wind" | "color" | "opacity">>;
|
|
246
339
|
export type GrassEnvironmentDescriptor = {
|
|
247
340
|
kind: "grass";
|
|
248
341
|
} & Required<Pick<GrassEnvironmentConfig, "area" | "density" | "bladeHeight" | "bladeWidth" | "windStrength" | "colors">> & Pick<GrassEnvironmentConfig, "seed">;
|
|
@@ -306,6 +399,18 @@ export interface EnvironmentWorldConfig {
|
|
|
306
399
|
roads?: EnvironmentDescriptorList<RoadEnvironmentDescriptor>;
|
|
307
400
|
/** Ground pads, e.g. platforms or paved patches; each implicitly flattens the terrain beneath it. */
|
|
308
401
|
pads?: readonly PadEnvironmentDescriptor[];
|
|
402
|
+
/**
|
|
403
|
+
* An authored editor {@link TerraformSnapshot} whose offsets layer over the base terrain — the
|
|
404
|
+
* editor-to-runtime ground seam. The same snapshot in a game's `editorLayers.terrain` renders and
|
|
405
|
+
* collides identically at runtime.
|
|
406
|
+
*/
|
|
407
|
+
sculpt?: TerraformSnapshot;
|
|
408
|
+
/**
|
|
409
|
+
* Clearance discs flattened into the ground (spawns, plots, paths) — the terrain half of a
|
|
410
|
+
* clearance zone whose foliage half is scatter's `avoid`. Derive them from a document with
|
|
411
|
+
* `clearanceZonesFrom`.
|
|
412
|
+
*/
|
|
413
|
+
clearings?: readonly AvoidZone[];
|
|
309
414
|
}
|
|
310
415
|
export interface EnvironmentWorldFeature {
|
|
311
416
|
kind: "environment";
|
|
@@ -318,6 +423,10 @@ export interface EnvironmentWorldFeature {
|
|
|
318
423
|
structures?: readonly StructureEnvironmentDescriptor[];
|
|
319
424
|
roads?: readonly RoadEnvironmentDescriptor[];
|
|
320
425
|
pads?: readonly PadEnvironmentDescriptor[];
|
|
426
|
+
/** Authored sculpt snapshot layered over the base terrain — see {@link EnvironmentWorldConfig.sculpt}. */
|
|
427
|
+
sculpt?: TerraformSnapshot;
|
|
428
|
+
/** Clearance discs flattened into the ground — see {@link EnvironmentWorldConfig.clearings}. */
|
|
429
|
+
clearings?: readonly AvoidZone[];
|
|
321
430
|
}
|
|
322
431
|
export interface WorldGridCell {
|
|
323
432
|
x: number;
|
|
@@ -356,8 +465,13 @@ export interface PlotsWorldConfig extends WorldGridConfig {
|
|
|
356
465
|
export interface TilemapWorldConfig extends WorldGridConfig {
|
|
357
466
|
map: string;
|
|
358
467
|
}
|
|
359
|
-
/**
|
|
360
|
-
|
|
468
|
+
/**
|
|
469
|
+
* A declared world shape passed to `defineGame`. The preferred model is the place feature from
|
|
470
|
+
* `world()` (`@jgengine/core/world/place`): substrate + laws, with all dressing authored in the
|
|
471
|
+
* editor. The remaining members — biomes, voxel grid, plots, tilemap, environment, flat — are the
|
|
472
|
+
* legacy code-declared shapes kept for existing games.
|
|
473
|
+
*/
|
|
474
|
+
export type WorldFeature = PlaceWorldFeature | ({
|
|
361
475
|
kind: "biomes";
|
|
362
476
|
} & BiomesWorldConfig) | ({
|
|
363
477
|
kind: "voxel";
|
|
@@ -370,14 +484,23 @@ export type WorldFeature = ({
|
|
|
370
484
|
};
|
|
371
485
|
/** Derives implicit `TerrainFlattenMask`s carving each pad's footprint into the terrain beneath it. Elevated pads (absolute `elevation`) float free and carve nothing. */
|
|
372
486
|
export declare function padFlattenMasks(pads: readonly PadEnvironmentDescriptor[]): readonly TerrainFlattenMask[];
|
|
373
|
-
/** Composes an `environment()`
|
|
487
|
+
/** Composes an `environment()` feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
|
|
488
|
+
*
|
|
489
|
+
* Legacy dressing-in-code path — not how a world is defined. A world is the place you play in
|
|
490
|
+
* (`world()` from `world/place`: ground + laws); sky look, foliage scatter, props, and sculpt are
|
|
491
|
+
* scene content authored in the editor. Reach for `environment()` only when consuming
|
|
492
|
+
* editor/preset-written scene data (`environmentContentFromDocument`) or maintaining an existing
|
|
493
|
+
* game; never scaffold new worlds from it.
|
|
494
|
+
*
|
|
495
|
+
* @capability world-environment compose editor/preset-derived outdoor dressing — terrain, weather, water, structures — into a legacy environment feature
|
|
496
|
+
*/
|
|
374
497
|
export declare function environment(config?: EnvironmentWorldConfig): EnvironmentWorldFeature;
|
|
375
498
|
/** Declares a heightfield terrain patch for `environment()` — bounds, noise, materials, and flatten masks. */
|
|
376
499
|
export declare function terrain(config?: TerrainEnvironmentConfig): TerrainEnvironmentDescriptor;
|
|
377
500
|
export declare function sky(config?: SkyEnvironmentConfig): SkyEnvironmentDescriptor;
|
|
378
|
-
/** Declares a rainfall weather effect for `environment()` — area, density, speed, and
|
|
501
|
+
/** Declares a rainfall weather effect for `environment()` — area, density, speed, wind, and drop width/opacity. */
|
|
379
502
|
export declare function rain(config?: RainEnvironmentConfig): RainEnvironmentDescriptor;
|
|
380
|
-
/** Declares a snowfall weather effect for `environment()` — area, density, drift, and
|
|
503
|
+
/** Declares a snowfall weather effect for `environment()` — area, density, drift, wind, and flake opacity. */
|
|
381
504
|
export declare function snow(config?: SnowEnvironmentConfig): SnowEnvironmentDescriptor;
|
|
382
505
|
/** Declares a grass vegetation patch for `environment()` — area, blade sizing, density, and colors. */
|
|
383
506
|
export declare function grass(config?: GrassEnvironmentConfig): GrassEnvironmentDescriptor;
|
package/dist/world/features.js
CHANGED
|
@@ -27,9 +27,37 @@ function withPadFlatten(terrainDescriptor, pads) {
|
|
|
27
27
|
flatten: [...(terrainDescriptor.flatten ?? []), ...padFlattenMasks(pads)],
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
-
/**
|
|
30
|
+
/** Expands each `biomeBand.weather` into a full-width precipitation strip centered on the band's z, `fade`-deep. */
|
|
31
|
+
function bandWeatherDescriptors(terrainDescriptor) {
|
|
32
|
+
const bands = terrainDescriptor?.biomeBands;
|
|
33
|
+
if (bands === undefined || bands.length === 0)
|
|
34
|
+
return [];
|
|
35
|
+
const width = terrainDescriptor.bounds.w;
|
|
36
|
+
const out = [];
|
|
37
|
+
for (const band of bands) {
|
|
38
|
+
if (band.weather === undefined)
|
|
39
|
+
continue;
|
|
40
|
+
const area = { w: width, d: band.fade ?? 64, h: 80 };
|
|
41
|
+
const position = [0, band.z];
|
|
42
|
+
out.push(band.weather === "rain" ? rain({ area, position }) : snow({ area, position }));
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
/** Composes an `environment()` feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
|
|
47
|
+
*
|
|
48
|
+
* Legacy dressing-in-code path — not how a world is defined. A world is the place you play in
|
|
49
|
+
* (`world()` from `world/place`: ground + laws); sky look, foliage scatter, props, and sculpt are
|
|
50
|
+
* scene content authored in the editor. Reach for `environment()` only when consuming
|
|
51
|
+
* editor/preset-written scene data (`environmentContentFromDocument`) or maintaining an existing
|
|
52
|
+
* game; never scaffold new worlds from it.
|
|
53
|
+
*
|
|
54
|
+
* @capability world-environment compose editor/preset-derived outdoor dressing — terrain, weather, water, structures — into a legacy environment feature
|
|
55
|
+
*/
|
|
31
56
|
export function environment(config = {}) {
|
|
32
|
-
const
|
|
57
|
+
const explicitWeather = list(config.weather);
|
|
58
|
+
const bandWeather = bandWeatherDescriptors(config.terrain);
|
|
59
|
+
const weatherAll = [...(explicitWeather ?? []), ...bandWeather];
|
|
60
|
+
const weather = weatherAll.length === 0 ? undefined : weatherAll;
|
|
33
61
|
const vegetation = list(config.vegetation);
|
|
34
62
|
const water = list(config.water);
|
|
35
63
|
const structures = list(config.structures);
|
|
@@ -46,6 +74,8 @@ export function environment(config = {}) {
|
|
|
46
74
|
...(structures === undefined ? {} : { structures }),
|
|
47
75
|
...(roads === undefined ? {} : { roads }),
|
|
48
76
|
...(config.pads === undefined ? {} : { pads: config.pads }),
|
|
77
|
+
...(config.sculpt === undefined ? {} : { sculpt: config.sculpt }),
|
|
78
|
+
...(config.clearings === undefined || config.clearings.length === 0 ? {} : { clearings: config.clearings }),
|
|
49
79
|
};
|
|
50
80
|
}
|
|
51
81
|
/** Declares a heightfield terrain patch for `environment()` — bounds, noise, materials, and flatten masks. */
|
|
@@ -75,6 +105,7 @@ export function terrain(config = {}) {
|
|
|
75
105
|
...(config.baseHeight === undefined ? {} : { baseHeight: config.baseHeight }),
|
|
76
106
|
...(config.waterLevel === undefined ? {} : { waterLevel: config.waterLevel }),
|
|
77
107
|
...(config.flatten === undefined ? {} : { flatten: config.flatten }),
|
|
108
|
+
...(config.pathProfiles === undefined ? {} : { pathProfiles: config.pathProfiles }),
|
|
78
109
|
...(config.detail === undefined ? {} : { detail: config.detail }),
|
|
79
110
|
});
|
|
80
111
|
}
|
|
@@ -88,35 +119,64 @@ export function sky(config = {}) {
|
|
|
88
119
|
...(config.zenithColor === undefined ? {} : { zenithColor: config.zenithColor }),
|
|
89
120
|
...(config.sunIntensity === undefined ? {} : { sunIntensity: config.sunIntensity }),
|
|
90
121
|
...(config.ambientIntensity === undefined ? {} : { ambientIntensity: config.ambientIntensity }),
|
|
122
|
+
...(config.radius === undefined ? {} : { radius: config.radius }),
|
|
123
|
+
...(config.hazeStrength === undefined ? {} : { hazeStrength: config.hazeStrength }),
|
|
124
|
+
...(config.sunGlowStrength === undefined ? {} : { sunGlowStrength: config.sunGlowStrength }),
|
|
91
125
|
...(config.fog === undefined ? {} : { fog: config.fog }),
|
|
126
|
+
...(config.volumetricClouds === undefined ? {} : { volumetricClouds: config.volumetricClouds }),
|
|
92
127
|
});
|
|
93
128
|
}
|
|
94
129
|
function withAreaPosition(area, position) {
|
|
95
130
|
return position !== undefined && area.position === undefined ? { ...area, position } : area;
|
|
96
131
|
}
|
|
97
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* Practical ceiling (world units per axis) past which an author-specified rain/snow `area` is almost
|
|
134
|
+
* certainly a world-region size mistakenly handed to the camera-anchored wrap-volume — see the
|
|
135
|
+
* `area` doc on `RainEnvironmentConfig`/`SnowEnvironmentConfig`.
|
|
136
|
+
*/
|
|
137
|
+
const WEATHER_AREA_CAMERA_SCALE_HINT = 120;
|
|
138
|
+
function warnIfOversizedWeatherArea(kind, area) {
|
|
139
|
+
if (typeof console === "undefined")
|
|
140
|
+
return;
|
|
141
|
+
if (area.w <= WEATHER_AREA_CAMERA_SCALE_HINT &&
|
|
142
|
+
area.d <= WEATHER_AREA_CAMERA_SCALE_HINT &&
|
|
143
|
+
(area.h ?? 0) <= WEATHER_AREA_CAMERA_SCALE_HINT) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
console.warn(`[jgengine:${kind}] area ${area.w}x${area.d}x${area.h ?? "default"} is far larger than the camera-anchored wrap-volume ${kind}() actually renders — area.position is ignored, and an oversized area.w/d/h just spreads drops/flakes thinner until they're sub-pixel at normal view distance, not wider visible coverage. Keep area near camera scale (~50-120 per axis); use density/width/opacity (or flakeSize for snow) to make a storm read heavier instead.`);
|
|
147
|
+
}
|
|
148
|
+
/** Declares a rainfall weather effect for `environment()` — area, density, speed, wind, and drop width/opacity. */
|
|
98
149
|
export function rain(config = {}) {
|
|
150
|
+
const area = withAreaPosition(config.area ?? { w: 256, d: 256, h: 80 }, config.position);
|
|
151
|
+
if (config.area !== undefined)
|
|
152
|
+
warnIfOversizedWeatherArea("rain", area);
|
|
99
153
|
return {
|
|
100
154
|
kind: "rain",
|
|
101
|
-
area
|
|
155
|
+
area,
|
|
102
156
|
density: config.density ?? 0.65,
|
|
103
157
|
speed: config.speed ?? 18,
|
|
104
158
|
dropLength: config.dropLength ?? 0.8,
|
|
105
159
|
wind: config.wind ?? [0, 0],
|
|
106
160
|
color: config.color ?? "#9ec8ff",
|
|
161
|
+
width: config.width ?? 0.018,
|
|
162
|
+
opacity: config.opacity ?? 0.48,
|
|
107
163
|
};
|
|
108
164
|
}
|
|
109
|
-
/** Declares a snowfall weather effect for `environment()` — area, density, drift, and
|
|
165
|
+
/** Declares a snowfall weather effect for `environment()` — area, density, drift, wind, and flake opacity. */
|
|
110
166
|
export function snow(config = {}) {
|
|
167
|
+
const area = withAreaPosition(config.area ?? { w: 256, d: 256, h: 80 }, config.position);
|
|
168
|
+
if (config.area !== undefined)
|
|
169
|
+
warnIfOversizedWeatherArea("snow", area);
|
|
111
170
|
return {
|
|
112
171
|
kind: "snow",
|
|
113
|
-
area
|
|
172
|
+
area,
|
|
114
173
|
density: config.density ?? 0.35,
|
|
115
174
|
speed: config.speed ?? 2.4,
|
|
116
175
|
flakeSize: config.flakeSize ?? 0.08,
|
|
117
176
|
drift: config.drift ?? 0.4,
|
|
118
177
|
wind: config.wind ?? [0, 0],
|
|
119
178
|
color: config.color ?? "#ffffff",
|
|
179
|
+
opacity: config.opacity ?? 0.86,
|
|
120
180
|
};
|
|
121
181
|
}
|
|
122
182
|
/** Declares a grass vegetation patch for `environment()` — area, blade sizing, density, and colors. */
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Footprint, Vec2 } from "./geometry.js";
|
|
2
|
+
import type { PlacementObstacle } from "./placement.js";
|
|
3
|
+
/** One integer cell address on a {@link FootprintGrid}. */
|
|
4
|
+
export interface GridCell {
|
|
5
|
+
col: number;
|
|
6
|
+
row: number;
|
|
7
|
+
}
|
|
8
|
+
/** Config for {@link createFootprintGrid}. */
|
|
9
|
+
export interface FootprintGridOptions {
|
|
10
|
+
/** World units per cell. Default 1. */
|
|
11
|
+
cellSize?: number;
|
|
12
|
+
}
|
|
13
|
+
/** A live claim on a {@link FootprintGrid}: which cells `id` (a `kind` tag for adjacency checks) holds. */
|
|
14
|
+
export interface FootprintReservation {
|
|
15
|
+
id: string;
|
|
16
|
+
kind: string;
|
|
17
|
+
cells: readonly GridCell[];
|
|
18
|
+
}
|
|
19
|
+
/** Handle returned by {@link createFootprintGrid}. */
|
|
20
|
+
export interface FootprintGrid {
|
|
21
|
+
readonly cellSize: number;
|
|
22
|
+
/** The cells a `footprint` centered on `origin` (world units) covers, honoring `quarterTurns` — feed straight into `reserve`/`isFree`. */
|
|
23
|
+
cellsFor(origin: Vec2, footprint: Footprint, quarterTurns?: number): GridCell[];
|
|
24
|
+
isFree(cells: readonly GridCell[]): boolean;
|
|
25
|
+
/** Claims every cell for `id`/`kind`; fails (no partial reservation) if `id` already holds a reservation or any cell is occupied. */
|
|
26
|
+
reserve(id: string, kind: string, cells: readonly GridCell[]): boolean;
|
|
27
|
+
release(id: string): boolean;
|
|
28
|
+
occupantAt(cell: GridCell): string | null;
|
|
29
|
+
kindAt(cell: GridCell): string | null;
|
|
30
|
+
reservationOf(id: string): FootprintReservation | null;
|
|
31
|
+
list(): readonly FootprintReservation[];
|
|
32
|
+
clear(): void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Multi-cell footprint occupancy/reservation on a shared build grid — `world/placementController`
|
|
36
|
+
* only owns the ghost preview; this is the persistent claim a committed placement holds so the next
|
|
37
|
+
* hover's `isFree` check (or another player's, in a shared world) sees it. Bridge into
|
|
38
|
+
* `world/placement`'s `PlacementRules.obstacles` with {@link footprintObstacles} instead of
|
|
39
|
+
* hand-rolling an occupancy map per game.
|
|
40
|
+
*
|
|
41
|
+
* @capability footprint-grid multi-cell footprint occupancy/reservation on a shared build grid
|
|
42
|
+
*/
|
|
43
|
+
export declare function createFootprintGrid(options?: FootprintGridOptions): FootprintGrid;
|
|
44
|
+
/** One occupied neighbor cell reported by {@link boundaryNeighbors}. */
|
|
45
|
+
export interface AdjacentCell {
|
|
46
|
+
cell: GridCell;
|
|
47
|
+
kind: string;
|
|
48
|
+
}
|
|
49
|
+
/** Every occupied cell orthogonally touching `cells` but outside them — the connective-piece neighbor set. */
|
|
50
|
+
export declare function boundaryNeighbors(grid: FootprintGrid, cells: readonly GridCell[]): AdjacentCell[];
|
|
51
|
+
/**
|
|
52
|
+
* Connective-piece adjacency validity: every occupied neighbor of `cells` must satisfy `accepts`
|
|
53
|
+
* (no incompatible piece touching), and when `requireConnection` is true at least one neighbor must
|
|
54
|
+
* (a road/pipe/belt segment placed with nothing to connect to is invalid). An empty-bordered footprint
|
|
55
|
+
* (no occupied neighbors at all) passes unless `requireConnection` demands one.
|
|
56
|
+
*/
|
|
57
|
+
export declare function hasValidAdjacency(grid: FootprintGrid, cells: readonly GridCell[], accepts: (neighborKind: string) => boolean, requireConnection?: boolean): boolean;
|
|
58
|
+
/** Bridges live reservations into `world/placement`'s `PlacementRules.obstacles` so `validatePlacement`/`createPlacementController` see the grid's committed footprints unchanged. */
|
|
59
|
+
export declare function footprintObstacles(grid: FootprintGrid): PlacementObstacle[];
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
function cellKey(cell) {
|
|
2
|
+
return `${cell.col}:${cell.row}`;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Multi-cell footprint occupancy/reservation on a shared build grid — `world/placementController`
|
|
6
|
+
* only owns the ghost preview; this is the persistent claim a committed placement holds so the next
|
|
7
|
+
* hover's `isFree` check (or another player's, in a shared world) sees it. Bridge into
|
|
8
|
+
* `world/placement`'s `PlacementRules.obstacles` with {@link footprintObstacles} instead of
|
|
9
|
+
* hand-rolling an occupancy map per game.
|
|
10
|
+
*
|
|
11
|
+
* @capability footprint-grid multi-cell footprint occupancy/reservation on a shared build grid
|
|
12
|
+
*/
|
|
13
|
+
export function createFootprintGrid(options = {}) {
|
|
14
|
+
const cellSize = options.cellSize ?? 1;
|
|
15
|
+
const occupied = new Map();
|
|
16
|
+
const reservations = new Map();
|
|
17
|
+
return {
|
|
18
|
+
cellSize,
|
|
19
|
+
cellsFor(origin, footprint, quarterTurns = 0) {
|
|
20
|
+
const turned = ((quarterTurns % 2) + 2) % 2 === 1;
|
|
21
|
+
const cols = Math.max(1, Math.round((turned ? footprint.d : footprint.w) / cellSize));
|
|
22
|
+
const rows = Math.max(1, Math.round((turned ? footprint.w : footprint.d) / cellSize));
|
|
23
|
+
const originCol = Math.round(origin[0] / cellSize - cols / 2);
|
|
24
|
+
const originRow = Math.round(origin[1] / cellSize - rows / 2);
|
|
25
|
+
const cells = [];
|
|
26
|
+
for (let row = 0; row < rows; row += 1) {
|
|
27
|
+
for (let col = 0; col < cols; col += 1)
|
|
28
|
+
cells.push({ col: originCol + col, row: originRow + row });
|
|
29
|
+
}
|
|
30
|
+
return cells;
|
|
31
|
+
},
|
|
32
|
+
isFree(cells) {
|
|
33
|
+
return cells.every((cell) => !occupied.has(cellKey(cell)));
|
|
34
|
+
},
|
|
35
|
+
reserve(id, kind, cells) {
|
|
36
|
+
if (reservations.has(id))
|
|
37
|
+
return false;
|
|
38
|
+
if (!cells.every((cell) => !occupied.has(cellKey(cell))))
|
|
39
|
+
return false;
|
|
40
|
+
for (const cell of cells)
|
|
41
|
+
occupied.set(cellKey(cell), id);
|
|
42
|
+
reservations.set(id, { id, kind, cells: cells.slice() });
|
|
43
|
+
return true;
|
|
44
|
+
},
|
|
45
|
+
release(id) {
|
|
46
|
+
const reservation = reservations.get(id);
|
|
47
|
+
if (reservation === undefined)
|
|
48
|
+
return false;
|
|
49
|
+
for (const cell of reservation.cells)
|
|
50
|
+
occupied.delete(cellKey(cell));
|
|
51
|
+
reservations.delete(id);
|
|
52
|
+
return true;
|
|
53
|
+
},
|
|
54
|
+
occupantAt(cell) {
|
|
55
|
+
return occupied.get(cellKey(cell)) ?? null;
|
|
56
|
+
},
|
|
57
|
+
kindAt(cell) {
|
|
58
|
+
const id = occupied.get(cellKey(cell));
|
|
59
|
+
if (id === undefined)
|
|
60
|
+
return null;
|
|
61
|
+
return reservations.get(id)?.kind ?? null;
|
|
62
|
+
},
|
|
63
|
+
reservationOf(id) {
|
|
64
|
+
return reservations.get(id) ?? null;
|
|
65
|
+
},
|
|
66
|
+
list() {
|
|
67
|
+
return Array.from(reservations.values());
|
|
68
|
+
},
|
|
69
|
+
clear() {
|
|
70
|
+
occupied.clear();
|
|
71
|
+
reservations.clear();
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const CARDINAL_OFFSETS = [
|
|
76
|
+
{ col: 0, row: -1 },
|
|
77
|
+
{ col: 1, row: 0 },
|
|
78
|
+
{ col: 0, row: 1 },
|
|
79
|
+
{ col: -1, row: 0 },
|
|
80
|
+
];
|
|
81
|
+
/** Every occupied cell orthogonally touching `cells` but outside them — the connective-piece neighbor set. */
|
|
82
|
+
export function boundaryNeighbors(grid, cells) {
|
|
83
|
+
const own = new Set(cells.map(cellKey));
|
|
84
|
+
const seen = new Set();
|
|
85
|
+
const out = [];
|
|
86
|
+
for (const cell of cells) {
|
|
87
|
+
for (const offset of CARDINAL_OFFSETS) {
|
|
88
|
+
const neighbor = { col: cell.col + offset.col, row: cell.row + offset.row };
|
|
89
|
+
const key = cellKey(neighbor);
|
|
90
|
+
if (own.has(key) || seen.has(key))
|
|
91
|
+
continue;
|
|
92
|
+
seen.add(key);
|
|
93
|
+
const kind = grid.kindAt(neighbor);
|
|
94
|
+
if (kind !== null)
|
|
95
|
+
out.push({ cell: neighbor, kind });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Connective-piece adjacency validity: every occupied neighbor of `cells` must satisfy `accepts`
|
|
102
|
+
* (no incompatible piece touching), and when `requireConnection` is true at least one neighbor must
|
|
103
|
+
* (a road/pipe/belt segment placed with nothing to connect to is invalid). An empty-bordered footprint
|
|
104
|
+
* (no occupied neighbors at all) passes unless `requireConnection` demands one.
|
|
105
|
+
*/
|
|
106
|
+
export function hasValidAdjacency(grid, cells, accepts, requireConnection = false) {
|
|
107
|
+
const neighbors = boundaryNeighbors(grid, cells);
|
|
108
|
+
if (requireConnection && neighbors.length === 0)
|
|
109
|
+
return false;
|
|
110
|
+
if (!neighbors.every((neighbor) => accepts(neighbor.kind)))
|
|
111
|
+
return false;
|
|
112
|
+
return !requireConnection || neighbors.some((neighbor) => accepts(neighbor.kind));
|
|
113
|
+
}
|
|
114
|
+
/** Bridges live reservations into `world/placement`'s `PlacementRules.obstacles` so `validatePlacement`/`createPlacementController` see the grid's committed footprints unchanged. */
|
|
115
|
+
export function footprintObstacles(grid) {
|
|
116
|
+
return grid.list().map((reservation) => {
|
|
117
|
+
let minCol = Infinity;
|
|
118
|
+
let minRow = Infinity;
|
|
119
|
+
let maxCol = -Infinity;
|
|
120
|
+
let maxRow = -Infinity;
|
|
121
|
+
for (const cell of reservation.cells) {
|
|
122
|
+
if (cell.col < minCol)
|
|
123
|
+
minCol = cell.col;
|
|
124
|
+
if (cell.col > maxCol)
|
|
125
|
+
maxCol = cell.col;
|
|
126
|
+
if (cell.row < minRow)
|
|
127
|
+
minRow = cell.row;
|
|
128
|
+
if (cell.row > maxRow)
|
|
129
|
+
maxRow = cell.row;
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
id: reservation.id,
|
|
133
|
+
aabb: {
|
|
134
|
+
minX: minCol * grid.cellSize,
|
|
135
|
+
maxX: (maxCol + 1) * grid.cellSize,
|
|
136
|
+
minZ: minRow * grid.cellSize,
|
|
137
|
+
maxZ: (maxRow + 1) * grid.cellSize,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
}
|
package/dist/world/geometry.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export type Vec2 = readonly [number, number];
|
|
2
|
+
/** A 3D point/vector as an `[x, y, z]` tuple — the engine's zero-allocation spatial primitive. */
|
|
3
|
+
export type Vec3 = readonly [number, number, number];
|
|
2
4
|
export interface Footprint {
|
|
3
5
|
w: number;
|
|
4
6
|
d: number;
|
|
@@ -13,11 +15,73 @@ export interface MoveOptions {
|
|
|
13
15
|
bounds?: Aabb;
|
|
14
16
|
radius?: number;
|
|
15
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* A circular clearance around a gameplay spot (spawn, plot, path point, POI): scatter is repelled
|
|
20
|
+
* from it and terrain is flattened toward its center. `feather` (meters) is the soft outer band —
|
|
21
|
+
* full effect within `radius - feather`, ramping to zero at `radius`.
|
|
22
|
+
*/
|
|
23
|
+
export interface AvoidZone {
|
|
24
|
+
x: number;
|
|
25
|
+
z: number;
|
|
26
|
+
radius: number;
|
|
27
|
+
feather?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A clearance *corridor* along a polyline (a path/road): scatter is repelled within `halfWidth` of
|
|
31
|
+
* the centerline, feathered over the outer band. Clean straight edges — unlike approximating a
|
|
32
|
+
* corridor with a scalloped chain of discs.
|
|
33
|
+
*/
|
|
34
|
+
export interface AvoidCorridor {
|
|
35
|
+
points: readonly Vec2[];
|
|
36
|
+
halfWidth: number;
|
|
37
|
+
feather?: number;
|
|
38
|
+
}
|
|
39
|
+
/** A clearance region: point discs (spawns/plots) plus centerline corridors (paths). */
|
|
40
|
+
export interface AvoidMasks {
|
|
41
|
+
discs: readonly AvoidZone[];
|
|
42
|
+
corridors: readonly AvoidCorridor[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* How strongly a point falls inside a clearance zone: 1 at/inside the solid core, ramping to 0 at
|
|
46
|
+
* the zone's outer `radius` across its `feather` band, 0 outside. The max over all zones.
|
|
47
|
+
* @internal — the falloff math behind scatter avoid and terrain flatten.
|
|
48
|
+
*/
|
|
49
|
+
export declare function zoneInfluence(x: number, z: number, zones: readonly AvoidZone[]): number;
|
|
50
|
+
/** Clearance influence of a corridor: nearest-segment distance vs `halfWidth`, feathered. @internal */
|
|
51
|
+
export declare function corridorInfluence(x: number, z: number, corridor: AvoidCorridor): number;
|
|
52
|
+
/** Combined clearance influence of discs + corridors — the max over every mask. @internal */
|
|
53
|
+
export declare function masksInfluence(x: number, z: number, masks: AvoidMasks): number;
|
|
54
|
+
/** @internal */
|
|
16
55
|
export declare function snapToGrid(point: Vec2, size: number): Vec2;
|
|
56
|
+
/** @internal */
|
|
17
57
|
export declare function footprintAabb(center: Vec2, footprint: Footprint, quarterTurns?: number): Aabb;
|
|
58
|
+
/** @internal */
|
|
18
59
|
export declare function expandAabb(aabb: Aabb, margin: number): Aabb;
|
|
60
|
+
/** @internal */
|
|
19
61
|
export declare function aabbOverlap(a: Aabb, b: Aabb): boolean;
|
|
62
|
+
/** @internal */
|
|
20
63
|
export declare function aabbContains(outer: Aabb, inner: Aabb): boolean;
|
|
64
|
+
/** @internal */
|
|
21
65
|
export declare function pointInAabb(point: Vec2, aabb: Aabb): boolean;
|
|
66
|
+
/** @internal */
|
|
22
67
|
export declare function clampToAabb(point: Vec2, aabb: Aabb): Vec2;
|
|
68
|
+
/** @internal */
|
|
23
69
|
export declare function resolveMove(from: Vec2, delta: Vec2, blockers: readonly Aabb[], options?: MoveOptions): Vec2;
|
|
70
|
+
/** An axis-aligned ellipse: `center` with semi-axes `radiusX` and `radiusY`. */
|
|
71
|
+
export interface Ellipse {
|
|
72
|
+
center: Vec2;
|
|
73
|
+
radiusX: number;
|
|
74
|
+
radiusY: number;
|
|
75
|
+
}
|
|
76
|
+
/** True when `point` sits inside (or on) the ellipse — the oval-arena containment test.
|
|
77
|
+
* @internal
|
|
78
|
+
*/
|
|
79
|
+
export declare function pointInEllipse(point: Vec2, ellipse: Ellipse): boolean;
|
|
80
|
+
/** Clamp `point` to the ellipse boundary when it strays outside, else return it unchanged.
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
export declare function clampToEllipse(point: Vec2, ellipse: Ellipse): Vec2;
|
|
84
|
+
/** Outward unit normal of the ellipse at the point nearest `point` — the boundary bounce direction.
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
87
|
+
export declare function ellipseNormal(point: Vec2, ellipse: Ellipse): Vec2;
|