@jgengine/core 0.10.0 → 0.11.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 +13 -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/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 +1 -0
- package/dist/authoring.js +1 -0
- 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 +34 -0
- package/dist/combat.js +34 -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/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/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/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/wallet.d.ts +26 -2
- package/dist/economy/wallet.js +35 -6
- package/dist/editor/commands.d.ts +190 -7
- package/dist/editor/commands.js +727 -55
- package/dist/editor/document.d.ts +159 -13
- package/dist/editor/document.js +750 -19
- 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 +73 -6
- package/dist/editor/index.js +6 -2
- package/dist/editor/liveSync.d.ts +127 -0
- package/dist/editor/liveSync.js +249 -0
- package/dist/editor/runtimeInspector.d.ts +88 -0
- package/dist/editor/runtimeInspector.js +239 -0
- package/dist/editor/types.d.ts +107 -1
- 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/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 +100 -2
- package/dist/game/defineGame.js +39 -2
- package/dist/game/defineSystem.d.ts +88 -0
- package/dist/game/defineSystem.js +45 -0
- package/dist/game/dialogue.d.ts +33 -0
- package/dist/game/dialogue.js +21 -0
- package/dist/game/events.d.ts +35 -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 +92 -7
- package/dist/game/quest.d.ts +8 -0
- package/dist/game/quest.js +29 -0
- 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/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 +91 -0
- package/dist/gameplay.js +91 -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/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 +5 -0
- 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 +16 -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 +35 -8
- package/dist/movement/movementModel.js +42 -14
- package/dist/movement/playerMovement.js +65 -10
- 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 +3 -0
- package/dist/multiplayer/lagCompensation.d.ts +5 -0
- package/dist/multiplayer/lagCompensation.js +5 -0
- package/dist/multiplayer/presenceModel.d.ts +9 -1
- package/dist/multiplayer/presenceModel.js +9 -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 +29 -0
- package/dist/physics/drivableVehicle.js +16 -0
- package/dist/physics/kinematicVehicle.d.ts +21 -1
- package/dist/physics/kinematicVehicle.js +23 -8
- package/dist/physics/physicsWorld.d.ts +24 -12
- package/dist/physics/physicsWorld.js +11 -5
- package/dist/physics/radialImpulse.d.ts +25 -0
- package/dist/physics/radialImpulse.js +27 -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 +22 -0
- package/dist/random/rng.js +28 -8
- 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 +42 -3
- package/dist/runtime/adapter.js +44 -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/combatFx.d.ts +23 -0
- package/dist/runtime/context/combatFx.js +161 -0
- package/dist/runtime/context/registries.d.ts +13 -0
- package/dist/runtime/context/registries.js +84 -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 +134 -0
- package/dist/runtime/descriptors/features.d.ts +74 -0
- package/dist/runtime/descriptors/features.js +281 -0
- package/dist/runtime/gameContext.d.ts +114 -13
- package/dist/runtime/gameContext.js +303 -395
- package/dist/runtime/gameRuntime.d.ts +1 -0
- package/dist/runtime/gameRuntime.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +60 -0
- package/dist/runtime/headlessRunner.js +44 -0
- package/dist/runtime/hostPersistence.d.ts +12 -0
- package/dist/runtime/hostPersistence.js +12 -0
- package/dist/runtime/hostedGameRunner.d.ts +8 -3
- package/dist/runtime/hostedGameRunner.js +26 -3
- package/dist/runtime/hostedWorldSession.d.ts +12 -4
- package/dist/runtime/hostedWorldSession.js +11 -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 +30 -3
- package/dist/runtime/worldSnapshot.js +20 -5
- package/dist/scene/assetCatalog.d.ts +21 -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 +259 -0
- package/dist/scene/authoredTriggers.d.ts +169 -0
- package/dist/scene/authoredTriggers.js +340 -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 +62 -0
- package/dist/scene/colliders.d.ts +13 -1
- package/dist/scene/colliders.js +37 -1
- package/dist/scene/entityStats.d.ts +11 -2
- package/dist/scene/entityStats.js +11 -2
- 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 +240 -0
- package/dist/scene/sceneKinds.js +214 -0
- package/dist/scene/sceneOwnership.d.ts +169 -0
- package/dist/scene/sceneOwnership.js +179 -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/statModifiers.d.ts +5 -0
- package/dist/stats/statModifiers.js +5 -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 +5 -0
- package/dist/store/observableKeyedStore.js +34 -2
- package/dist/survival/decayMeter.d.ts +55 -0
- package/dist/survival/decayMeter.js +130 -55
- package/dist/survival/moodle.d.ts +2 -0
- package/dist/survival/regionHealth.d.ts +6 -0
- package/dist/survival/regionHealth.js +5 -0
- 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 +33 -1
- package/dist/ui/hudLayout.js +204 -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/authoredObjects.d.ts +58 -0
- package/dist/world/authoredObjects.js +69 -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/features.d.ts +115 -7
- package/dist/world/features.js +56 -5
- 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/pathInstances.d.ts +27 -0
- package/dist/world/pathInstances.js +27 -0
- package/dist/world/pathTerrain.d.ts +80 -0
- package/dist/world/pathTerrain.js +142 -0
- package/dist/world/placeAsset.d.ts +81 -0
- package/dist/world/placeAsset.js +77 -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/polyline.d.ts +34 -0
- package/dist/world/polyline.js +81 -0
- package/dist/world/roads.d.ts +8 -0
- package/dist/world/roads.js +38 -0
- 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/terraform.d.ts +213 -1
- package/dist/world/terraform.js +655 -20
- package/dist/world/terrain.d.ts +119 -20
- package/dist/world/terrain.js +247 -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 +132 -0
- package/dist/world.js +132 -0
- package/package.json +32 -8
- package/skills/jgengine/SKILL.md +51 -0
- package/skills/jgengine/api.md +434 -0
- package/skills/jgengine/capabilities.md +29 -0
- package/skills/jgengine/reference-cartridge.md +72 -0
- package/skills/jgengine-combat/SKILL.md +34 -0
- package/skills/jgengine-combat/api.md +549 -0
- package/skills/jgengine-combat/capabilities.md +169 -0
- package/skills/jgengine-combat/reference.md +98 -0
- package/skills/jgengine-gameplay/SKILL.md +39 -0
- package/skills/jgengine-gameplay/api.md +1794 -0
- package/skills/jgengine-gameplay/capabilities.md +378 -0
- package/skills/jgengine-gameplay/reference-systems.md +60 -0
- package/skills/jgengine-world/SKILL.md +38 -0
- package/skills/jgengine-world/api.md +2652 -0
- package/skills/jgengine-world/capabilities.md +370 -0
- package/skills/jgengine-world/reference.md +222 -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
|
@@ -9,6 +9,13 @@ import type { WorldSnapshot } from "./worldSnapshot.js";
|
|
|
9
9
|
*/
|
|
10
10
|
export interface WorldDiff {
|
|
11
11
|
revision: number;
|
|
12
|
+
/**
|
|
13
|
+
* The revision this diff was computed against — `sinceRevision` echoed back. A {@link WorldMirror} only applies
|
|
14
|
+
* a diff whose `baseRevision` matches its own current revision exactly; a mismatch means frames were skipped and
|
|
15
|
+
* the mirror must resync from a fresh baseline instead of silently drifting. Absent on a diff built by an older
|
|
16
|
+
* producer — treated as legacy and always applied, matching pre-revision-checking behavior.
|
|
17
|
+
*/
|
|
18
|
+
baseRevision?: number;
|
|
12
19
|
entities: readonly SceneEntity[];
|
|
13
20
|
removedEntities: readonly string[];
|
|
14
21
|
stats: Record<string, StatValueMap>;
|
|
@@ -17,15 +24,27 @@ export interface WorldDiff {
|
|
|
17
24
|
removedStore: readonly string[];
|
|
18
25
|
/** Changed whole-module snapshots keyed by module name — everything a client can't reconstruct from deltas. */
|
|
19
26
|
modules: WorldSnapshot;
|
|
27
|
+
/** Module keys present in a prior baseline that no longer exist — a client drops them wholesale on apply. */
|
|
28
|
+
removedModules: readonly string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Optional acceleration for {@link createWorldReplicator}: a monotone world-dirty counter (aggregated from
|
|
32
|
+
* each {@link SnapshotModule.version}). When it hasn't advanced since the last commit nothing mutated, so the
|
|
33
|
+
* replicator skips re-reading and re-serializing the whole world — the change-detection short-circuit item #28
|
|
34
|
+
* asks for. Omit it (or pass a snapshot-only source) to keep the original full-re-serialize-per-commit behavior.
|
|
35
|
+
*/
|
|
36
|
+
export interface WorldReplicatorOptions {
|
|
37
|
+
worldVersion?: () => number;
|
|
20
38
|
}
|
|
21
39
|
/**
|
|
22
40
|
* Turns successive full {@link WorldSnapshot}s into per-client {@link WorldDiff}s. Each `commit()` re-reads the
|
|
23
41
|
* world, stamps every item that changed with the new revision, and remembers removals; `diff(sinceRevision)`
|
|
24
42
|
* then replays exactly the items stamped after that revision. Everything the tracker holds is JSON — the same
|
|
25
43
|
* shape that rides the wire — so a diff is inherently serializable. Change-detection is a full re-serialize per
|
|
26
|
-
* commit
|
|
27
|
-
|
|
28
|
-
|
|
44
|
+
* commit unless {@link WorldReplicatorOptions.worldVersion} lets an unchanged tick short-circuit before it.
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
47
|
+
export declare function createWorldReplicator(takeSnapshot: () => WorldSnapshot, options?: WorldReplicatorOptions): {
|
|
29
48
|
commit: () => number;
|
|
30
49
|
diff: (sinceRevision: number) => WorldDiff;
|
|
31
50
|
revision: () => number;
|
|
@@ -35,12 +54,16 @@ export type WorldReplicator = ReturnType<typeof createWorldReplicator>;
|
|
|
35
54
|
/**
|
|
36
55
|
* Diff two full {@link WorldSnapshot}s directly, stamping the result at `revision` — the stateless counterpart of
|
|
37
56
|
* {@link createWorldReplicator} for hosts that persist snapshots rather than keep a live tracker (Convex reconstructs
|
|
38
|
-
* per invocation). `applyWorldDiff(prev, diffSnapshots(prev, next, r))` reproduces `next`.
|
|
39
|
-
|
|
40
|
-
|
|
57
|
+
* per invocation). `applyWorldDiff(prev, diffSnapshots(prev, next, r))` reproduces `next`. `baseRevision`, when the
|
|
58
|
+
* caller knows the revision `prev` was stamped at, lets a {@link WorldMirror} verify continuity the same way a
|
|
59
|
+
* `createWorldReplicator` diff does; omitted, the diff is legacy/always-apply.
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
62
|
+
export declare function diffSnapshots(prev: WorldSnapshot, next: WorldSnapshot, revision: number, baseRevision?: number): WorldDiff;
|
|
41
63
|
/**
|
|
42
64
|
* Fold a {@link WorldDiff} onto a prior {@link WorldSnapshot} baseline, returning the next full snapshot — the
|
|
43
65
|
* client-side inverse of {@link createWorldReplicator}. Pure data in, pure data out: upserts changed entities,
|
|
44
66
|
* stats and store keys, drops the removed ones, and replaces changed module snapshots wholesale.
|
|
45
|
-
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
46
69
|
export declare function applyWorldDiff(baseline: WorldSnapshot, diff: WorldDiff): WorldSnapshot;
|
|
@@ -4,9 +4,12 @@ const CORE_KEYS = new Set(["entities", "stats", "store"]);
|
|
|
4
4
|
* world, stamps every item that changed with the new revision, and remembers removals; `diff(sinceRevision)`
|
|
5
5
|
* then replays exactly the items stamped after that revision. Everything the tracker holds is JSON — the same
|
|
6
6
|
* shape that rides the wire — so a diff is inherently serializable. Change-detection is a full re-serialize per
|
|
7
|
-
* commit
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
* commit unless {@link WorldReplicatorOptions.worldVersion} lets an unchanged tick short-circuit before it.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export function createWorldReplicator(takeSnapshot, options = {}) {
|
|
11
|
+
const worldVersion = options.worldVersion;
|
|
12
|
+
let committedVersion;
|
|
10
13
|
let revision = 0;
|
|
11
14
|
const entities = new Map();
|
|
12
15
|
const removedEntities = new Map();
|
|
@@ -15,6 +18,7 @@ export function createWorldReplicator(takeSnapshot) {
|
|
|
15
18
|
const store = new Map();
|
|
16
19
|
const removedStore = new Map();
|
|
17
20
|
const modules = new Map();
|
|
21
|
+
const removedModules = new Map();
|
|
18
22
|
function diffMap(live, tracked, removed, nextRevision) {
|
|
19
23
|
let changed = false;
|
|
20
24
|
for (const [key, json] of live) {
|
|
@@ -35,6 +39,12 @@ export function createWorldReplicator(takeSnapshot) {
|
|
|
35
39
|
return changed;
|
|
36
40
|
}
|
|
37
41
|
function commit() {
|
|
42
|
+
if (worldVersion !== undefined) {
|
|
43
|
+
const current = worldVersion();
|
|
44
|
+
if (committedVersion !== undefined && current === committedVersion)
|
|
45
|
+
return revision;
|
|
46
|
+
committedVersion = current;
|
|
47
|
+
}
|
|
38
48
|
const snapshot = takeSnapshot();
|
|
39
49
|
const nextRevision = revision + 1;
|
|
40
50
|
const liveEntities = new Map();
|
|
@@ -58,7 +68,7 @@ export function createWorldReplicator(takeSnapshot) {
|
|
|
58
68
|
let changed = diffMap(liveEntities, entities, removedEntities, nextRevision);
|
|
59
69
|
changed = diffMap(liveStats, stats, removedStats, nextRevision) || changed;
|
|
60
70
|
changed = diffMap(liveStore, store, removedStore, nextRevision) || changed;
|
|
61
|
-
changed = diffMap(liveModules, modules,
|
|
71
|
+
changed = diffMap(liveModules, modules, removedModules, nextRevision) || changed;
|
|
62
72
|
if (changed)
|
|
63
73
|
revision = nextRevision;
|
|
64
74
|
return revision;
|
|
@@ -86,6 +96,7 @@ export function createWorldReplicator(takeSnapshot) {
|
|
|
86
96
|
}
|
|
87
97
|
return {
|
|
88
98
|
revision,
|
|
99
|
+
baseRevision: sinceRevision,
|
|
89
100
|
entities: changedEntities,
|
|
90
101
|
removedEntities: keysAfter(removedEntities, sinceRevision),
|
|
91
102
|
stats: changedStats,
|
|
@@ -93,6 +104,7 @@ export function createWorldReplicator(takeSnapshot) {
|
|
|
93
104
|
store: changedStore,
|
|
94
105
|
removedStore: keysAfter(removedStore, sinceRevision),
|
|
95
106
|
modules: changedModules,
|
|
107
|
+
removedModules: keysAfter(removedModules, sinceRevision),
|
|
96
108
|
};
|
|
97
109
|
}
|
|
98
110
|
return { commit, diff, revision: () => revision };
|
|
@@ -108,9 +120,12 @@ function keysAfter(map, sinceRevision) {
|
|
|
108
120
|
/**
|
|
109
121
|
* Diff two full {@link WorldSnapshot}s directly, stamping the result at `revision` — the stateless counterpart of
|
|
110
122
|
* {@link createWorldReplicator} for hosts that persist snapshots rather than keep a live tracker (Convex reconstructs
|
|
111
|
-
* per invocation). `applyWorldDiff(prev, diffSnapshots(prev, next, r))` reproduces `next`.
|
|
112
|
-
|
|
113
|
-
|
|
123
|
+
* per invocation). `applyWorldDiff(prev, diffSnapshots(prev, next, r))` reproduces `next`. `baseRevision`, when the
|
|
124
|
+
* caller knows the revision `prev` was stamped at, lets a {@link WorldMirror} verify continuity the same way a
|
|
125
|
+
* `createWorldReplicator` diff does; omitted, the diff is legacy/always-apply.
|
|
126
|
+
* @internal
|
|
127
|
+
*/
|
|
128
|
+
export function diffSnapshots(prev, next, revision, baseRevision) {
|
|
114
129
|
const prevEntities = new Map();
|
|
115
130
|
for (const entity of (prev["entities"] ?? [])) {
|
|
116
131
|
prevEntities.set(entity.id, JSON.stringify(entity));
|
|
@@ -143,20 +158,35 @@ export function diffSnapshots(prev, next, revision) {
|
|
|
143
158
|
}
|
|
144
159
|
const removedStore = [...prevStore.keys()].filter((key) => !nextStore.has(key));
|
|
145
160
|
const modules = {};
|
|
161
|
+
const nextModuleKeys = new Set();
|
|
146
162
|
for (const [key, value] of Object.entries(next)) {
|
|
147
163
|
if (CORE_KEYS.has(key))
|
|
148
164
|
continue;
|
|
165
|
+
nextModuleKeys.add(key);
|
|
149
166
|
const json = JSON.stringify(value ?? null);
|
|
150
167
|
if (JSON.stringify(prev[key] ?? null) !== json)
|
|
151
168
|
modules[key] = JSON.parse(json);
|
|
152
169
|
}
|
|
153
|
-
|
|
170
|
+
const removedModules = Object.keys(prev).filter((key) => !CORE_KEYS.has(key) && !nextModuleKeys.has(key));
|
|
171
|
+
return {
|
|
172
|
+
revision,
|
|
173
|
+
...(baseRevision === undefined ? {} : { baseRevision }),
|
|
174
|
+
entities,
|
|
175
|
+
removedEntities,
|
|
176
|
+
stats,
|
|
177
|
+
removedStats,
|
|
178
|
+
store,
|
|
179
|
+
removedStore,
|
|
180
|
+
modules,
|
|
181
|
+
removedModules,
|
|
182
|
+
};
|
|
154
183
|
}
|
|
155
184
|
/**
|
|
156
185
|
* Fold a {@link WorldDiff} onto a prior {@link WorldSnapshot} baseline, returning the next full snapshot — the
|
|
157
186
|
* client-side inverse of {@link createWorldReplicator}. Pure data in, pure data out: upserts changed entities,
|
|
158
187
|
* stats and store keys, drops the removed ones, and replaces changed module snapshots wholesale.
|
|
159
|
-
|
|
188
|
+
* @internal
|
|
189
|
+
*/
|
|
160
190
|
export function applyWorldDiff(baseline, diff) {
|
|
161
191
|
const next = { ...baseline };
|
|
162
192
|
const entityById = new Map();
|
|
@@ -181,5 +211,7 @@ export function applyWorldDiff(baseline, diff) {
|
|
|
181
211
|
next["store"] = Array.from(storeByKey.entries());
|
|
182
212
|
for (const [key, value] of Object.entries(diff.modules))
|
|
183
213
|
next[key] = value;
|
|
214
|
+
for (const key of diff.removedModules)
|
|
215
|
+
delete next[key];
|
|
184
216
|
return next;
|
|
185
217
|
}
|
|
@@ -1,17 +1,44 @@
|
|
|
1
|
+
/** Who a host→client snapshot is being projected for — the identity a {@link SnapshotModule.project} filters against. */
|
|
2
|
+
export interface SnapshotViewer {
|
|
3
|
+
readonly userId: string;
|
|
4
|
+
}
|
|
1
5
|
/**
|
|
2
6
|
* The replication seam for host-authoritative shared worlds: the opt-in feature manifest *is* the
|
|
3
7
|
* replication schema. Each live subsystem a game opts into registers a {@link SnapshotModule} keyed
|
|
4
8
|
* by name; the host serializes exactly the registered set into a {@link WorldSnapshot} and a client
|
|
5
9
|
* hydrates the same keys back. Adding a replicated subsystem is a registration, never a new branch.
|
|
10
|
+
*
|
|
11
|
+
* Two optional members carry per-viewer projection and change detection *through the same contract*,
|
|
12
|
+
* so a feature opts into either without the engine growing a per-feature branch:
|
|
13
|
+
* - {@link project} narrows this module's snapshot to what one viewer may see (private state, area of
|
|
14
|
+
* interest). Absent → the module is world-public and every client receives it verbatim (the default).
|
|
15
|
+
* - {@link version} is a monotone counter the host reads to skip re-serializing an unchanged module.
|
|
6
16
|
*/
|
|
7
17
|
export interface SnapshotModule<T = unknown> {
|
|
8
18
|
readonly key: string;
|
|
9
19
|
snapshot(): T;
|
|
10
20
|
hydrate(data: T): void;
|
|
21
|
+
/**
|
|
22
|
+
* Narrow this module's full snapshot to what `viewer` is allowed to see — return the same shape
|
|
23
|
+
* carrying only the visible subset (drop other players' private state, cull entities outside the
|
|
24
|
+
* viewer's area of interest). `world` is the whole unprojected baseline, so a module can cross-
|
|
25
|
+
* reference another (e.g. drop stats for entities the viewer can't see). Absent → world-public: the
|
|
26
|
+
* full value is sent to every viewer.
|
|
27
|
+
*/
|
|
28
|
+
project?(data: T, viewer: SnapshotViewer, world: WorldSnapshot): T;
|
|
29
|
+
/** Monotone change counter; unchanged between host commits means this module didn't mutate and need not re-serialize. */
|
|
30
|
+
version?(): number;
|
|
11
31
|
}
|
|
12
32
|
/** Full world baseline keyed by {@link SnapshotModule.key} — one entry per opted-in subsystem. */
|
|
13
33
|
export type WorldSnapshot = Record<string, unknown>;
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Serialize every registered module into one keyed baseline — the host→client full-world send. When a
|
|
36
|
+
* `viewer` is supplied, each module that implements {@link SnapshotModule.project} narrows its value to
|
|
37
|
+
* what that viewer may see; modules without a projector are sent verbatim.
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export declare function composeWorldSnapshot(modules: readonly SnapshotModule[], viewer?: SnapshotViewer): WorldSnapshot;
|
|
41
|
+
/** Hydrate every registered module whose key is present in `snapshot`; keys absent from it are left untouched.
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
17
44
|
export declare function applyWorldSnapshot(modules: readonly SnapshotModule[], snapshot: WorldSnapshot): void;
|
|
@@ -1,11 +1,26 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Serialize every registered module into one keyed baseline — the host→client full-world send. When a
|
|
3
|
+
* `viewer` is supplied, each module that implements {@link SnapshotModule.project} narrows its value to
|
|
4
|
+
* what that viewer may see; modules without a projector are sent verbatim.
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export function composeWorldSnapshot(modules, viewer) {
|
|
8
|
+
const raw = {};
|
|
4
9
|
for (const module of modules)
|
|
5
|
-
|
|
10
|
+
raw[module.key] = module.snapshot();
|
|
11
|
+
if (viewer === undefined)
|
|
12
|
+
return raw;
|
|
13
|
+
const snapshot = {};
|
|
14
|
+
for (const module of modules) {
|
|
15
|
+
const value = raw[module.key];
|
|
16
|
+
snapshot[module.key] =
|
|
17
|
+
module.project !== undefined ? module.project(value, viewer, raw) : value;
|
|
18
|
+
}
|
|
6
19
|
return snapshot;
|
|
7
20
|
}
|
|
8
|
-
/** Hydrate every registered module whose key is present in `snapshot`; keys absent from it are left untouched.
|
|
21
|
+
/** Hydrate every registered module whose key is present in `snapshot`; keys absent from it are left untouched.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
9
24
|
export function applyWorldSnapshot(modules, snapshot) {
|
|
10
25
|
for (const module of modules) {
|
|
11
26
|
if (Object.prototype.hasOwnProperty.call(snapshot, module.key)) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AssetSpace } from "./assetSpace.js";
|
|
1
2
|
/** Measured horizontal footprint, footprint center, and lowest Y of a model in model space. */
|
|
2
3
|
export interface ModelDims {
|
|
3
4
|
footprint: {
|
|
@@ -14,7 +15,27 @@ export interface ModelAssetRef {
|
|
|
14
15
|
url: string;
|
|
15
16
|
/** Measured at asset reindex: horizontal footprint, footprint center, and lowest Y in model space (pre-scale). Lets the shell auto-center and ground-snap corner-pivot kit models. */
|
|
16
17
|
dims?: ModelDims;
|
|
18
|
+
/** Authored asset-space metadata — canonical facing (degrees), source-unit scale, footprint, anchor, bounds, and rotation policy. The upstream owner of placement corrections; see {@link "scene/assetSpace".AssetSpace}. */
|
|
19
|
+
space?: AssetSpace;
|
|
17
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* A catalog entry backed by a registered {@link registerAssetGenerator} instead of a GLB URL — a
|
|
23
|
+
* slider-driven parametric prop (bookcase, building). `defaults` seeds a fresh placement's params.
|
|
24
|
+
* Placed instances persist `{ assetId, params, seed }` in the scene and re-resolve at runtime.
|
|
25
|
+
*/
|
|
26
|
+
export interface GeneratorAssetRef {
|
|
27
|
+
kind: "generator";
|
|
28
|
+
/** Id of the registered generator this asset resolves through. */
|
|
29
|
+
generatorId: string;
|
|
30
|
+
/** Default params stamped onto a fresh placement's meta. */
|
|
31
|
+
defaults?: Record<string, unknown>;
|
|
32
|
+
/** Authored asset-space metadata — canonical facing (degrees), footprint, anchor, bounds, and rotation policy; see {@link "scene/assetSpace".AssetSpace}. */
|
|
33
|
+
space?: AssetSpace;
|
|
34
|
+
}
|
|
35
|
+
/** A catalog entry: a static GLB model, or a parametric generator. */
|
|
36
|
+
export type AssetRef = ModelAssetRef | GeneratorAssetRef;
|
|
37
|
+
/** True when a catalog entry is a parametric generator rather than a static GLB. @internal */
|
|
38
|
+
export declare function isGeneratorAsset(ref: AssetRef): ref is GeneratorAssetRef;
|
|
18
39
|
export interface AssetCatalog<TMeta extends ModelAssetRef = ModelAssetRef> {
|
|
19
40
|
register(id: string, asset: TMeta): void;
|
|
20
41
|
resolve(id: string): TMeta | null;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, zero-dependency classification of a model-asset fetch before it reaches
|
|
3
|
+
* a GLTF parser. Runtime loaders hand the raw response (status, content type,
|
|
4
|
+
* and the first bytes) to {@link classifyAssetResponse} so a missing or
|
|
5
|
+
* mis-served file surfaces as an actionable diagnostic naming the broken asset
|
|
6
|
+
* contract, instead of the opaque "Unexpected token < in JSON" parse error a
|
|
7
|
+
* dev-server HTML fallback otherwise produces. No `fetch`, DOM, or three.js
|
|
8
|
+
* dependency lives here — callers supply the already-read bytes.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* How a model-asset fetch resolved. `ok` means the bytes are a parseable GLB or
|
|
12
|
+
* glTF-JSON; every other kind is a distinct failure a loader should report
|
|
13
|
+
* rather than parse: `missing` (HTTP error / no bytes), `html` (a dev-server
|
|
14
|
+
* fallback page served in place of the file), `corrupt` (bytes present but not a
|
|
15
|
+
* recognizable model), `unsupported` (a recognizable but non-model format).
|
|
16
|
+
*/
|
|
17
|
+
export type AssetLoadKind = "ok" | "missing" | "html" | "corrupt" | "unsupported";
|
|
18
|
+
/** The signature read from a response's leading bytes, independent of HTTP metadata. @internal */
|
|
19
|
+
export type AssetByteSignature = "glb" | "gltf-json" | "html" | "png" | "jpeg" | "zip" | "unknown" | "empty";
|
|
20
|
+
/**
|
|
21
|
+
* A probe of a model-asset fetch: the URL, an optional logical asset id for the
|
|
22
|
+
* diagnostic, and whatever the caller managed to read. Any field may be absent
|
|
23
|
+
* (e.g. a network error yields no `status` or `bytes`); the classifier degrades
|
|
24
|
+
* gracefully.
|
|
25
|
+
*/
|
|
26
|
+
export interface AssetResponseProbe {
|
|
27
|
+
url: string;
|
|
28
|
+
/** Logical catalog id / alias behind the URL, surfaced in the diagnostic message when known. */
|
|
29
|
+
logicalId?: string;
|
|
30
|
+
/** HTTP status code; `0` or `>= 400` is treated as missing. Omit when the fetch never completed. */
|
|
31
|
+
status?: number;
|
|
32
|
+
statusText?: string;
|
|
33
|
+
/** `Content-Type` response header, lower-cased or not — matched case-insensitively. */
|
|
34
|
+
contentType?: string;
|
|
35
|
+
/** The leading bytes of the body (a few hundred is plenty); their signature decides GLB vs HTML vs corrupt. */
|
|
36
|
+
bytes?: Uint8Array;
|
|
37
|
+
}
|
|
38
|
+
/** The verdict for one model-asset fetch: its {@link AssetLoadKind} plus a ready-to-log message. */
|
|
39
|
+
export interface AssetLoadDiagnosis {
|
|
40
|
+
kind: AssetLoadKind;
|
|
41
|
+
/** True only for `kind: "ok"` — safe to hand the bytes to a GLTF parser. */
|
|
42
|
+
ok: boolean;
|
|
43
|
+
url: string;
|
|
44
|
+
logicalId?: string;
|
|
45
|
+
byteSignature: AssetByteSignature;
|
|
46
|
+
/** Human-readable, actionable one-liner naming the asset, the URL, and the likely fix. */
|
|
47
|
+
message: string;
|
|
48
|
+
}
|
|
49
|
+
/** GLB little-endian magic — the ASCII "glTF" at byte 0 of a binary glTF container. @internal */
|
|
50
|
+
export declare const GLB_MAGIC_ASCII = "glTF";
|
|
51
|
+
/**
|
|
52
|
+
* Classify the leading bytes of a response body by their format signature, with
|
|
53
|
+
* no HTTP context. Recognizes GLB (`glTF` magic), glTF-JSON (a leading `{`), an
|
|
54
|
+
* HTML fallback page (`<!doctype`, `<html`, or a bare `<`), and a few common
|
|
55
|
+
* non-model binaries (PNG, JPEG, ZIP) so they can be reported as unsupported
|
|
56
|
+
* rather than corrupt.
|
|
57
|
+
*/
|
|
58
|
+
export declare function readByteSignature(bytes: Uint8Array): AssetByteSignature;
|
|
59
|
+
/**
|
|
60
|
+
* Turn a {@link AssetResponseProbe} into an {@link AssetLoadDiagnosis}. HTTP
|
|
61
|
+
* status is checked first (a `>= 400` or `0` status is `missing`), then the
|
|
62
|
+
* `Content-Type` and byte signature decide between an HTML fallback, a
|
|
63
|
+
* parseable model (`ok`), an unsupported-but-recognizable format, and otherwise
|
|
64
|
+
* corrupt bytes. The returned `message` always names the asset and URL and, for
|
|
65
|
+
* failures, points at the likely fix (provision the pack, check the serving path).
|
|
66
|
+
*
|
|
67
|
+
* @capability asset-load-diagnostics classify a model fetch (missing / HTML fallback / corrupt / unsupported) before parsing
|
|
68
|
+
*/
|
|
69
|
+
export declare function classifyAssetResponse(probe: AssetResponseProbe): AssetLoadDiagnosis;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, zero-dependency classification of a model-asset fetch before it reaches
|
|
3
|
+
* a GLTF parser. Runtime loaders hand the raw response (status, content type,
|
|
4
|
+
* and the first bytes) to {@link classifyAssetResponse} so a missing or
|
|
5
|
+
* mis-served file surfaces as an actionable diagnostic naming the broken asset
|
|
6
|
+
* contract, instead of the opaque "Unexpected token < in JSON" parse error a
|
|
7
|
+
* dev-server HTML fallback otherwise produces. No `fetch`, DOM, or three.js
|
|
8
|
+
* dependency lives here — callers supply the already-read bytes.
|
|
9
|
+
*/
|
|
10
|
+
/** GLB little-endian magic — the ASCII "glTF" at byte 0 of a binary glTF container. @internal */
|
|
11
|
+
export const GLB_MAGIC_ASCII = "glTF";
|
|
12
|
+
function startsWithAscii(bytes, ascii) {
|
|
13
|
+
if (bytes.length < ascii.length)
|
|
14
|
+
return false;
|
|
15
|
+
for (let i = 0; i < ascii.length; i += 1) {
|
|
16
|
+
if (bytes[i] !== ascii.charCodeAt(i))
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
/** Skip a UTF-8 BOM and leading ASCII whitespace, returning the index of the first meaningful byte. */
|
|
22
|
+
function firstNonBlank(bytes) {
|
|
23
|
+
let i = 0;
|
|
24
|
+
if (bytes.length >= 3 && bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf)
|
|
25
|
+
i = 3;
|
|
26
|
+
while (i < bytes.length) {
|
|
27
|
+
const b = bytes[i];
|
|
28
|
+
// space, tab, CR, LF
|
|
29
|
+
if (b === 0x20 || b === 0x09 || b === 0x0d || b === 0x0a)
|
|
30
|
+
i += 1;
|
|
31
|
+
else
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
return i;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Classify the leading bytes of a response body by their format signature, with
|
|
38
|
+
* no HTTP context. Recognizes GLB (`glTF` magic), glTF-JSON (a leading `{`), an
|
|
39
|
+
* HTML fallback page (`<!doctype`, `<html`, or a bare `<`), and a few common
|
|
40
|
+
* non-model binaries (PNG, JPEG, ZIP) so they can be reported as unsupported
|
|
41
|
+
* rather than corrupt.
|
|
42
|
+
*/
|
|
43
|
+
export function readByteSignature(bytes) {
|
|
44
|
+
if (bytes.length === 0)
|
|
45
|
+
return "empty";
|
|
46
|
+
if (startsWithAscii(bytes, GLB_MAGIC_ASCII))
|
|
47
|
+
return "glb";
|
|
48
|
+
if (bytes.length >= 8 && bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4e && bytes[3] === 0x47) {
|
|
49
|
+
return "png";
|
|
50
|
+
}
|
|
51
|
+
if (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff)
|
|
52
|
+
return "jpeg";
|
|
53
|
+
if (bytes.length >= 4 && bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04) {
|
|
54
|
+
return "zip";
|
|
55
|
+
}
|
|
56
|
+
const start = firstNonBlank(bytes);
|
|
57
|
+
const head = bytes[start];
|
|
58
|
+
if (head === undefined)
|
|
59
|
+
return "empty";
|
|
60
|
+
// '<' — an HTML document served where a model was expected.
|
|
61
|
+
if (head === 0x3c)
|
|
62
|
+
return "html";
|
|
63
|
+
// '{' — glTF-JSON (the non-binary .gltf form) is a parseable model.
|
|
64
|
+
if (head === 0x7b)
|
|
65
|
+
return "gltf-json";
|
|
66
|
+
return "unknown";
|
|
67
|
+
}
|
|
68
|
+
function describe(logicalId, url) {
|
|
69
|
+
return logicalId === undefined ? `"${url}"` : `"${logicalId}" (${url})`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Turn a {@link AssetResponseProbe} into an {@link AssetLoadDiagnosis}. HTTP
|
|
73
|
+
* status is checked first (a `>= 400` or `0` status is `missing`), then the
|
|
74
|
+
* `Content-Type` and byte signature decide between an HTML fallback, a
|
|
75
|
+
* parseable model (`ok`), an unsupported-but-recognizable format, and otherwise
|
|
76
|
+
* corrupt bytes. The returned `message` always names the asset and URL and, for
|
|
77
|
+
* failures, points at the likely fix (provision the pack, check the serving path).
|
|
78
|
+
*
|
|
79
|
+
* @capability asset-load-diagnostics classify a model fetch (missing / HTML fallback / corrupt / unsupported) before parsing
|
|
80
|
+
*/
|
|
81
|
+
export function classifyAssetResponse(probe) {
|
|
82
|
+
const { url, logicalId, status, statusText, contentType, bytes } = probe;
|
|
83
|
+
const signature = bytes === undefined ? "empty" : readByteSignature(bytes);
|
|
84
|
+
const who = describe(logicalId, url);
|
|
85
|
+
const finish = (kind, message) => ({
|
|
86
|
+
kind,
|
|
87
|
+
ok: kind === "ok",
|
|
88
|
+
url,
|
|
89
|
+
...(logicalId === undefined ? {} : { logicalId }),
|
|
90
|
+
byteSignature: signature,
|
|
91
|
+
message,
|
|
92
|
+
});
|
|
93
|
+
if (status !== undefined && (status === 0 || status >= 400)) {
|
|
94
|
+
const suffix = statusText === undefined || statusText.length === 0 ? "" : ` ${statusText}`;
|
|
95
|
+
return finish("missing", `Asset ${who} did not load: HTTP ${status}${suffix}. The file is not being served — provision the pack (e.g. \`assets pull <source>\`) or check the model path.`);
|
|
96
|
+
}
|
|
97
|
+
const htmlContentType = contentType !== undefined && contentType.toLowerCase().includes("text/html");
|
|
98
|
+
if (signature === "html" || (htmlContentType && signature !== "glb" && signature !== "gltf-json")) {
|
|
99
|
+
return finish("html", `Asset ${who} resolved to an HTML page, not a model — the dev server returned its fallback document because the file is missing. Provision the pack (\`assets pull <source>\`) so the bytes exist under the served path.`);
|
|
100
|
+
}
|
|
101
|
+
if (signature === "glb" || signature === "gltf-json")
|
|
102
|
+
return finish("ok", `Asset ${who} loaded (${signature}).`);
|
|
103
|
+
if (signature === "png" || signature === "jpeg" || signature === "zip") {
|
|
104
|
+
return finish("unsupported", `Asset ${who} is a ${signature} file, not a GLB/glTF model — the reference points at the wrong file or the wrong loader is being used.`);
|
|
105
|
+
}
|
|
106
|
+
if (signature === "empty") {
|
|
107
|
+
return finish("corrupt", `Asset ${who} returned an empty body — the file exists but has no bytes. Re-provision the pack or remove the reference.`);
|
|
108
|
+
}
|
|
109
|
+
return finish("corrupt", `Asset ${who} is not a recognizable GLB/glTF model (leading bytes do not match any known signature). The file is likely truncated or corrupt — re-provision the pack.`);
|
|
110
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generator-asset seam: register a parametric asset generator (`generate(params, seed) → parts`)
|
|
3
|
+
* so a slider-driven prop (a bookcase with width/shelves/book-density, a building with floors/bays)
|
|
4
|
+
* lives in the catalog alongside static GLBs. A placed instance stores only `{ assetId, params, seed }`
|
|
5
|
+
* — the geometry is re-resolved at runtime, never baked. Schema drives the inspector via #809. The
|
|
6
|
+
* generic seam is engine; concrete generators (building, bookcase) are adopters registered from
|
|
7
|
+
* game/example code — the building generator is the one engine adopter, as a proof it composes.
|
|
8
|
+
*
|
|
9
|
+
* @capability asset-generator seeded parametric geometry registered as a placeable asset
|
|
10
|
+
*/
|
|
11
|
+
import { type ParamSchema, type ParsedParams } from "./sceneKinds.js";
|
|
12
|
+
/** One generated primitive part — a box/panel placed in the asset's local space. */
|
|
13
|
+
export interface GeneratedPart {
|
|
14
|
+
id: string;
|
|
15
|
+
/** Optional semantic tag (shelf, board, book, wall, window …) for materials/inspection. */
|
|
16
|
+
kind?: string;
|
|
17
|
+
/** Local-space center. */
|
|
18
|
+
position: readonly [number, number, number];
|
|
19
|
+
/** Full box dimensions (w, h, d) in meters. */
|
|
20
|
+
size: readonly [number, number, number];
|
|
21
|
+
rotationY?: number;
|
|
22
|
+
/** Hex color; the renderer falls back to a neutral material when absent. */
|
|
23
|
+
color?: string;
|
|
24
|
+
}
|
|
25
|
+
/** A resolved generator asset: its parts plus the overall local-space bounds (min/max corners). */
|
|
26
|
+
export interface GeneratedAsset {
|
|
27
|
+
parts: GeneratedPart[];
|
|
28
|
+
bounds: {
|
|
29
|
+
min: readonly [number, number, number];
|
|
30
|
+
max: readonly [number, number, number];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The declared local-space direction the asset's "front" faces (a bookcase's open/book face, a
|
|
34
|
+
* building's entrance) — so a camera rig or placement tool can orient it without hand-tuned
|
|
35
|
+
* `rotationY`. Omit to use the convention default, +Z (`DEFAULT_FORWARD` in `./facing`); every
|
|
36
|
+
* generator should build its front toward +Z unless it declares otherwise.
|
|
37
|
+
*/
|
|
38
|
+
forward?: readonly [number, number, number];
|
|
39
|
+
}
|
|
40
|
+
/** A registered asset generator — schema drives the inspector; `generate` is a pure seeded function. */
|
|
41
|
+
export interface AssetGeneratorDefinition {
|
|
42
|
+
id: string;
|
|
43
|
+
label: string;
|
|
44
|
+
schema: ParamSchema;
|
|
45
|
+
/** Deterministic geometry from validated params + a seed string. Same inputs → same parts. */
|
|
46
|
+
generate: (params: ParsedParams, seed: string) => GeneratedAsset;
|
|
47
|
+
}
|
|
48
|
+
/** Register a parametric asset generator. Idempotent per id (last wins); call at module load. */
|
|
49
|
+
export declare function registerAssetGenerator(definition: AssetGeneratorDefinition): void;
|
|
50
|
+
/** The registered generator for an id, or undefined. @internal */
|
|
51
|
+
export declare function getAssetGenerator(id: string): AssetGeneratorDefinition | undefined;
|
|
52
|
+
/** Every registered generator, in registration order. @internal */
|
|
53
|
+
export declare function listAssetGenerators(): AssetGeneratorDefinition[];
|
|
54
|
+
/**
|
|
55
|
+
* Compute bounds from parts (each part is an axis-aligned box at its center) — a helper generators
|
|
56
|
+
* return so callers can frame/ground the asset without re-deriving it.
|
|
57
|
+
*/
|
|
58
|
+
export declare function partsBounds(parts: readonly GeneratedPart[]): GeneratedAsset["bounds"];
|
|
59
|
+
/**
|
|
60
|
+
* Re-resolve a placed generator instance from its stored `meta` (`{ assetId, seed, ...params }`): look
|
|
61
|
+
* up the generator, parse its params off `meta` against the schema, and generate. Returns null when
|
|
62
|
+
* `assetId` names no registered generator. This is what a runtime renderer calls per placed instance.
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveGeneratorAsset(meta: Record<string, unknown> | undefined): GeneratedAsset | null;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generator-asset seam: register a parametric asset generator (`generate(params, seed) → parts`)
|
|
3
|
+
* so a slider-driven prop (a bookcase with width/shelves/book-density, a building with floors/bays)
|
|
4
|
+
* lives in the catalog alongside static GLBs. A placed instance stores only `{ assetId, params, seed }`
|
|
5
|
+
* — the geometry is re-resolved at runtime, never baked. Schema drives the inspector via #809. The
|
|
6
|
+
* generic seam is engine; concrete generators (building, bookcase) are adopters registered from
|
|
7
|
+
* game/example code — the building generator is the one engine adopter, as a proof it composes.
|
|
8
|
+
*
|
|
9
|
+
* @capability asset-generator seeded parametric geometry registered as a placeable asset
|
|
10
|
+
*/
|
|
11
|
+
import { parseParams } from "./sceneKinds.js";
|
|
12
|
+
const generators = new Map();
|
|
13
|
+
/** Register a parametric asset generator. Idempotent per id (last wins); call at module load. */
|
|
14
|
+
export function registerAssetGenerator(definition) {
|
|
15
|
+
generators.set(definition.id, definition);
|
|
16
|
+
}
|
|
17
|
+
/** The registered generator for an id, or undefined. @internal */
|
|
18
|
+
export function getAssetGenerator(id) {
|
|
19
|
+
return generators.get(id);
|
|
20
|
+
}
|
|
21
|
+
/** Every registered generator, in registration order. @internal */
|
|
22
|
+
export function listAssetGenerators() {
|
|
23
|
+
return [...generators.values()];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Compute bounds from parts (each part is an axis-aligned box at its center) — a helper generators
|
|
27
|
+
* return so callers can frame/ground the asset without re-deriving it.
|
|
28
|
+
*/
|
|
29
|
+
export function partsBounds(parts) {
|
|
30
|
+
if (parts.length === 0)
|
|
31
|
+
return { min: [0, 0, 0], max: [0, 0, 0] };
|
|
32
|
+
let minX = Infinity;
|
|
33
|
+
let minY = Infinity;
|
|
34
|
+
let minZ = Infinity;
|
|
35
|
+
let maxX = -Infinity;
|
|
36
|
+
let maxY = -Infinity;
|
|
37
|
+
let maxZ = -Infinity;
|
|
38
|
+
for (const part of parts) {
|
|
39
|
+
minX = Math.min(minX, part.position[0] - part.size[0] / 2);
|
|
40
|
+
minY = Math.min(minY, part.position[1] - part.size[1] / 2);
|
|
41
|
+
minZ = Math.min(minZ, part.position[2] - part.size[2] / 2);
|
|
42
|
+
maxX = Math.max(maxX, part.position[0] + part.size[0] / 2);
|
|
43
|
+
maxY = Math.max(maxY, part.position[1] + part.size[1] / 2);
|
|
44
|
+
maxZ = Math.max(maxZ, part.position[2] + part.size[2] / 2);
|
|
45
|
+
}
|
|
46
|
+
return { min: [minX, minY, minZ], max: [maxX, maxY, maxZ] };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Re-resolve a placed generator instance from its stored `meta` (`{ assetId, seed, ...params }`): look
|
|
50
|
+
* up the generator, parse its params off `meta` against the schema, and generate. Returns null when
|
|
51
|
+
* `assetId` names no registered generator. This is what a runtime renderer calls per placed instance.
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
export function resolveGeneratorAsset(meta) {
|
|
55
|
+
const assetId = typeof meta?.["assetId"] === "string" ? meta["assetId"] : undefined;
|
|
56
|
+
if (assetId === undefined)
|
|
57
|
+
return null;
|
|
58
|
+
const generator = generators.get(assetId);
|
|
59
|
+
if (generator === undefined)
|
|
60
|
+
return null;
|
|
61
|
+
const seed = typeof meta?.["seed"] === "string" ? meta["seed"] : assetId;
|
|
62
|
+
const params = parseParams(generator.schema, meta);
|
|
63
|
+
return generator.generate(params, seed);
|
|
64
|
+
}
|