@jgengine/shell 0.11.0 → 0.13.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.
Files changed (151) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/CombatPresentation.d.ts +5 -0
  3. package/dist/CombatPresentation.js +8 -0
  4. package/dist/GameHost.d.ts +27 -1
  5. package/dist/GameHost.js +83 -4
  6. package/dist/GamePlayer.d.ts +5 -0
  7. package/dist/GamePlayer.js +5 -0
  8. package/dist/GamePlayerShell.d.ts +5 -0
  9. package/dist/GamePlayerShell.js +63 -359
  10. package/dist/GameUiPreview.js +3 -0
  11. package/dist/Shell3dPresentation.d.ts +63 -0
  12. package/dist/Shell3dPresentation.js +302 -0
  13. package/dist/ShellChrome.d.ts +51 -0
  14. package/dist/ShellChrome.js +51 -0
  15. package/dist/ShellHudPresentation.d.ts +41 -0
  16. package/dist/ShellHudPresentation.js +22 -0
  17. package/dist/audio/audioEngine.d.ts +4 -0
  18. package/dist/audio/audioEngine.js +111 -26
  19. package/dist/audio/audioWire.d.ts +22 -4
  20. package/dist/audio/audioWire.js +46 -3
  21. package/dist/audio/loopParams.d.ts +20 -0
  22. package/dist/audio/loopParams.js +28 -0
  23. package/dist/camera/GameCameraRig.js +6 -1
  24. package/dist/camera/GameOrbitCamera.js +7 -1
  25. package/dist/camera/cameraCollision.d.ts +28 -0
  26. package/dist/camera/cameraCollision.js +34 -0
  27. package/dist/camera/cameraRigs.d.ts +3 -1
  28. package/dist/camera/cameraRigs.js +24 -10
  29. package/dist/camera/index.d.ts +1 -0
  30. package/dist/camera/index.js +1 -0
  31. package/dist/camera/rigMath.d.ts +27 -0
  32. package/dist/camera/rigMath.js +45 -0
  33. package/dist/defineGame.d.ts +15 -1
  34. package/dist/defineGame.js +26 -4
  35. package/dist/devtools/DevtoolsOverlay.d.ts +4 -4
  36. package/dist/devtools/DevtoolsOverlay.js +28 -12
  37. package/dist/devtools/agentBridge.js +4 -0
  38. package/dist/devtools/perfDiagnose.js +1 -1
  39. package/dist/diagnostics/RuntimeDiagnostics.d.ts +7 -0
  40. package/dist/diagnostics/RuntimeDiagnostics.js +23 -12
  41. package/dist/environment/EnvironmentScene.js +17 -3
  42. package/dist/environment/RoadJunctions.d.ts +12 -0
  43. package/dist/environment/RoadJunctions.js +69 -0
  44. package/dist/environment/RoadRibbons.d.ts +8 -2
  45. package/dist/environment/RoadRibbons.js +26 -8
  46. package/dist/environment/terrainGroundColor.d.ts +9 -0
  47. package/dist/environment/terrainGroundColor.js +22 -0
  48. package/dist/gameKit.d.ts +27 -0
  49. package/dist/gameKit.js +29 -0
  50. package/dist/map/MapMarkerBeacons.d.ts +3 -2
  51. package/dist/postfx/PostProcessing.d.ts +9 -1
  52. package/dist/postfx/PostProcessing.js +11 -4
  53. package/dist/presentationResolve.d.ts +39 -0
  54. package/dist/presentationResolve.js +53 -0
  55. package/dist/registry.d.ts +1 -0
  56. package/dist/render/PartMotion.d.ts +18 -0
  57. package/dist/render/PartMotion.js +91 -0
  58. package/dist/render/SceneModels.d.ts +9 -2
  59. package/dist/render/SceneModels.js +31 -180
  60. package/dist/render/assetBase.d.ts +17 -0
  61. package/dist/render/assetBase.js +35 -0
  62. package/dist/render/measureBounds.d.ts +34 -0
  63. package/dist/render/measureBounds.js +127 -0
  64. package/dist/render/modelLoad.js +4 -1
  65. package/dist/render/resolveModel.d.ts +15 -0
  66. package/dist/render/resolveModel.js +43 -2
  67. package/dist/render/useModelAnimation.d.ts +10 -0
  68. package/dist/render/useModelAnimation.js +198 -0
  69. package/dist/scatter/InstancedScatter.js +5 -0
  70. package/dist/scatter/scatterProxies.js +24 -0
  71. package/dist/scene/AuthoredScene.d.ts +3 -1
  72. package/dist/scene/AuthoredScene.js +7 -2
  73. package/dist/scene/CityRenderer.d.ts +2 -0
  74. package/dist/scene/CityRenderer.js +1031 -0
  75. package/dist/scene/GrassFieldRenderer.js +53 -5
  76. package/dist/scene/PoleLineRenderer.d.ts +2 -0
  77. package/dist/scene/PoleLineRenderer.js +287 -0
  78. package/dist/scene/SoilPatchRenderer.js +70 -7
  79. package/dist/scene/WaterRenderer.js +34 -10
  80. package/dist/scene/builtinSceneKindRenderers.js +4 -0
  81. package/dist/scene/cityWindowMaterial.d.ts +16 -0
  82. package/dist/scene/cityWindowMaterial.js +81 -0
  83. package/dist/scene/sceneKindRenderers.d.ts +2 -0
  84. package/dist/settings/appliedSettings.d.ts +2 -1
  85. package/dist/settings/appliedSettings.js +4 -2
  86. package/dist/structures/GeneratedBuilding.d.ts +4 -0
  87. package/dist/structures/GeneratedBuilding.js +17 -7
  88. package/dist/structures/TransformGizmo.d.ts +11 -1
  89. package/dist/structures/TransformGizmo.js +9 -5
  90. package/dist/terrain/GrassField.d.ts +11 -3
  91. package/dist/terrain/GrassField.js +16 -6
  92. package/dist/terrain/grassGeometry.d.ts +33 -1
  93. package/dist/terrain/grassGeometry.js +83 -21
  94. package/dist/terrain/grassMaterial.d.ts +18 -0
  95. package/dist/terrain/grassMaterial.js +66 -13
  96. package/dist/terrain/heightfieldGeometry.d.ts +34 -0
  97. package/dist/terrain/heightfieldGeometry.js +109 -0
  98. package/dist/terrain/index.d.ts +1 -0
  99. package/dist/terrain/index.js +1 -0
  100. package/dist/terrain/soilPatchMaterial.d.ts +15 -2
  101. package/dist/terrain/soilPatchMaterial.js +46 -8
  102. package/dist/terrain/terrainDetailMaterial.js +15 -2
  103. package/dist/water/Ocean.d.ts +7 -1
  104. package/dist/water/Ocean.js +16 -3
  105. package/dist/water/OceanConfig.d.ts +9 -0
  106. package/dist/water/OceanConfig.js +6 -0
  107. package/dist/water/OceanMaterial.d.ts +12 -0
  108. package/dist/water/OceanMaterial.js +9 -0
  109. package/dist/water/OceanShader.d.ts +2 -2
  110. package/dist/water/OceanShader.js +78 -10
  111. package/dist/world/PlaceScene.d.ts +11 -0
  112. package/dist/world/PlaceScene.js +27 -0
  113. package/dist/world/WorldHud.d.ts +3 -1
  114. package/dist/world/WorldHud.js +2 -2
  115. package/dist/world/WorldScene.js +32 -4
  116. package/dist/worldSky.d.ts +7 -1
  117. package/dist/worldSky.js +11 -1
  118. package/package.json +4 -4
  119. package/skills/game-design/SKILL.md +28 -0
  120. package/skills/game-design/agents/openai.yaml +4 -0
  121. package/skills/game-design/references/application-playbook.md +170 -0
  122. package/skills/game-design/references/field-guide.md +288 -0
  123. package/skills/jgengine/SKILL.md +8 -4
  124. package/skills/jgengine/api.md +182 -81
  125. package/skills/jgengine/capabilities.md +104 -2
  126. package/skills/jgengine/recipes/minimal-game.md +88 -0
  127. package/skills/jgengine-ui/SKILL.md +17 -10
  128. package/skills/jgengine-ui/api.md +316 -51
  129. package/skills/jgengine-ui/capabilities.md +135 -2
  130. package/skills/jgengine-ui/recipes/portable-minimap.md +150 -0
  131. package/skills/jgengine-ui/reference.md +59 -9
  132. package/skills/jgengine-ui/references/visual-scorecard.md +1 -1
  133. package/skills/jgengine-world/SKILL.md +13 -0
  134. package/skills/jgengine-world/api.md +453 -21
  135. package/skills/jgengine-world/capabilities.md +112 -2
  136. package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
  137. package/skills/jgengine-world/reference.md +43 -4
  138. package/skills/level-design/SKILL.md +54 -0
  139. package/skills/level-design/agents/openai.yaml +4 -0
  140. package/skills/level-design/references/application-playbook.md +192 -0
  141. package/skills/level-design/references/field-guide.md +337 -0
  142. package/skills/level-design/references/live-editor-loop.md +179 -0
  143. package/dist/cartridge/runtime.d.ts +0 -15
  144. package/dist/cartridge/runtime.js +0 -556
  145. package/dist/cartridge/spec.d.ts +0 -188
  146. package/dist/cartridge/spec.js +0 -19
  147. package/dist/cartridge/validate.d.ts +0 -2
  148. package/dist/cartridge/validate.js +0 -78
  149. package/dist/cartridge.d.ts +0 -145
  150. package/dist/cartridge.js +0 -246
  151. package/skills/jgengine/reference-cartridge.md +0 -72
@@ -77,6 +77,27 @@
77
77
  - `MobVec3` (type): type MobVec3 = readonly [number, number, number] — ⚠ undocumented
78
78
  - `MobWanderConfig` (interface): interface MobWanderConfig — ⚠ undocumented
79
79
 
80
+ ## @jgengine/core/ai/populationDirector
81
+
82
+ - `PopulationCensus` (type): type PopulationCensus = Record<string, Record<string, number>> — Live census of alive counts keyed `region -> species -> count`, used to reconcile the director to reality.
83
+ - `PopulationDirector` (interface): interface PopulationDirector — Stateful ambient population manager for one world; drive it with `tick` and lifecycle notifications.
84
+ - `PopulationDirectorConfig` (interface): interface PopulationDirectorConfig — Full ambient-population configuration: per-region species budgets plus global refill limits and PRNG seed.
85
+ - `PopulationDirectorState` (interface): interface PopulationDirectorState — Opaque, JSON-serializable persistence for a {@link PopulationDirector}. Round-trip it through `snapshot`/`hydrate`; never read or mutate the fields directly.
86
+ - `PopulationRegionConfig` (interface): interface PopulationRegionConfig — Ambient population budget for a single region: its species ceilings, refill timing, and spawn geometry.
87
+ - `PopulationSpawnRequest` (interface): interface PopulationSpawnRequest — A single ambient spawn the game should realise, refilling a region toward its species caps.
88
+ - `PopulationSpeciesEntry` (interface): interface PopulationSpeciesEntry — One species that ambiently populates a region: how heavily it is favoured and its alive ceiling.
89
+ - `PopulationTickContext` (interface): interface PopulationTickContext — Per-call spawn-point selection hook, letting a game apply bias (distance from players, etc.) at tick time.
90
+ - `createPopulationDirector` (function): function createPopulationDirector(config: PopulationDirectorConfig): PopulationDirector — Ambient open-world population director. Holds a target creature population per region and refills it over time, distinct from wave/horde spawning: instead of a budget draining down a wave, each region has per-species caps and a timed respawn queue. Removing a creature frees a slot; after a respawn delay `tick` emits weighted spawn requests (bounded per tick) that refill toward the caps without ever exceeding them. Species are chosen through a persisted, serializable {@link RandomSeed} cursor, so the same seed and the same lifecycle events always yield the same requests. Regions are independent, spawn points are optional, and the whole state round-trips through `snapshot`/`hydrate`.
91
+
92
+ ## @jgengine/core/ai/pursuit
93
+
94
+ - `CooldownMode` (type): type CooldownMode = "always" | "inRange" — When the attack cooldown ticks down. - `"always"` (default): every step, like a wall-clock weapon timer that keeps counting during the chase, so the entity can swing the instant it reaches its target. - `"inRange"`: only while within `stopDistance`, so the timer freezes during the chase and the full interval is paid out after each contact.
95
+ - `PursuitAction` (type): type PursuitAction = | "leash" /** Out of range — advance toward the target. */ | "pursue" /** In range and the cooldown is ready — perform the attack, then {@link armPursuit}. */ | "attack" /** In range but the cooldown has not elapsed — hold (face the target, idle, etc.). */ | "wait" /** No engage… — Composable pursuit/aggro step: the "I have a target — now chase it, stop at reach, hit it on a cooldown, and break off if led too far from home" loop that melee mobs, RTS units, and stationary turrets all re-implement by hand. This owns exactly that state machine and the per-entity attack cooldown; target *selection* stays separate (see {@link ./targetAcquisition}), and every side effect — move, attack, break off — is performed by the caller in response to the returned action.
96
+ - `PursuitState` (interface): interface PursuitState — Per-entity cooldown state owned by the primitive. One serializable number; no methods.
97
+ - `advancePursuit` (function): function advancePursuit(state: PursuitState, dt: number, targetDistance: number | null, stopDistance: number, cooldownMode: CooldownMode = "always", homeDistance = Number.NEGATIVE_INFINITY, leashRange = Number.POSITIVE_INFINITY): PursuitAction — Advance one pursuit step for a single entity, mutating `state.attackCooldown`, and return the action the caller should perform. All spatial input is scalar and measured this frame:
98
+ - `armPursuit` (function): function armPursuit(state: PursuitState, intervalSeconds: number): void — Set the cooldown after an attack fires (clamped at `0`). Call on the step that returned `"attack"`.
99
+ - `createPursuitState` (function): function createPursuitState(attackCooldown = 0): PursuitState — A fresh pursuit state, ready to attack immediately (`attackCooldown` at `0`).
100
+
80
101
  ## @jgengine/core/ai/spawnDirector
81
102
 
82
103
  - `DirectorContext` (interface): interface DirectorContext — ⚠ undocumented
@@ -647,6 +668,18 @@
647
668
  - `DrivableVehicleStep` (interface): interface DrivableVehicleStep — {@link tickDrivableVehicle}'s result — the ready-to-apply pose patch plus the raw sim step for HUD/telemetry reads.
648
669
  - `tickDrivableVehicle` (function): function tickDrivableVehicle(vehicle: KinematicVehicle, dt: number, axis: AxisInput, options: DrivableVehicleOptions = {}): DrivableVehicleStep — Connects an `AxisInput` sample straight through a {@link KinematicVehicle} to a scene entity's pose for one tick (#533.1) — the throttle/steer/handbrake → sim → `setPose` loop every drivable-vehicle game hand-rolled. Ground-snaps the result when `groundHeight` is given (terrain-following cars, not just flat racetracks). Pair with `scene/vehicleSeat` for who is allowed to drive and where the camera points; this function only steps the sim and shapes the pose patch, nothing else.
649
670
 
671
+ ## @jgengine/core/physics/flightDynamics
672
+
673
+ - `AircraftDynamics` (interface): interface AircraftDynamics — Stateful six-degree-of-freedom aircraft simulation.
674
+ - `AircraftKind` (type): type AircraftKind = "fixedWing" | "rotorcraft" | "vtol" — Supported aerodynamic/propulsion families.
675
+ - `AircraftOptions` (interface): interface AircraftOptions — Spawn state and injectable world-field samplers for an aircraft instance.
676
+ - `AircraftStep` (interface): interface AircraftStep — Pose and aerodynamic telemetry returned after one flight tick.
677
+ - `AircraftTuning` (interface): interface AircraftTuning — Data-first physical tuning shared by all aircraft instances of one catalog type.
678
+ - `FlightControlInput` (interface): interface FlightControlInput — Normalized pilot inputs for one flight-simulation tick.
679
+ - `FlightControlRates` (interface): interface FlightControlRates — Angular authority, response, damping, and self-leveling configuration.
680
+ - `FlightVector` (type): type FlightVector = readonly [number, number, number] — Three-dimensional world-space vector used by the flight model.
681
+ - `createAircraftDynamics` (function): function createAircraftDynamics(tuning: AircraftTuning, options: AircraftOptions = {}): AircraftDynamics — Six-degree-of-freedom arcade flight model for fixed-wing, helicopter, and VTOL aircraft.
682
+
650
683
  ## @jgengine/core/physics/flowTube
651
684
 
652
685
  - `FlowTube` (interface): interface FlowTube — An axial corridor of directional flow with radial core falloff and a spool scalar — fan tunnels, updraft shafts, river narrows, thruster wash. Pure math: sample `velocityAt(point, spool)` and add it to whatever integrator moves the body (walk controller drift, `BuoyantBody`, a custom sim).
@@ -668,8 +701,21 @@
668
701
  - `applyVolumeForce` (function): function applyVolumeForce(velocity: readonly [number, number, number], force: readonly [number, number, number], mode: ForceMode, dt: number): readonly [number, number, number] — One tick's force math for a body outside `PhysicsWorld` — apply the returned velocity in any custom integrator.
669
702
  - `createVolumeTrigger` (function): function createVolumeTrigger<TId = string>(config: VolumeTriggerConfig): VolumeTrigger<TId> — ⚠ undocumented
670
703
 
704
+ ## @jgengine/core/physics/gravityField
705
+
706
+ - `GravityField` (interface): interface GravityField — Position-dependent gravity source used by movement and vehicle simulations.
707
+ - `GravityVector` (type): type GravityVector = readonly [number, number, number] — Three-dimensional acceleration vector sampled from a gravity field.
708
+ - `PointGravityOptions` (interface): interface PointGravityOptions — Center, strength, and falloff for radial gravity.
709
+ - `combineGravity` (function): function combineGravity(fields: readonly GravityField[]): GravityField — Adds several gravity sources into one field.
710
+ - `pointGravity` (function): function pointGravity(options: PointGravityOptions): GravityField — Radial gravity toward one center, with optional inverse-square falloff for planetary worlds.
711
+ - `uniformGravity` (function): function uniformGravity(vector: GravityVector = [0, -9.81, 0]): GravityField — Constant vector gravity for ordinary worlds, space stations, and sideways-gravity levels.
712
+
671
713
  ## @jgengine/core/physics/kinematicVehicle
672
714
 
715
+ - `KinematicChassisTuning` (interface): interface KinematicChassisTuning — Mass-and-force chassis layer (#1051); when present it supersedes `engineAccel`/`brakeAccel` with force/mass dynamics. Drive/brake become forces divided by `massKg`, a per-tick tire friction budget (`tireGrip` * grip curve * surface * downforce * m * g) is split lateral-first then longitudinal so hard slides and launches saturate, and `comHeight`/`trackWidth` set weight-transfer washout and body lean. Coasting decelerates from physical road load, not a per-vehicle constant: rolling resistance `μ_rr · m · g` always, plus engine braking `ENGINE_BRAKE_FRACTION · engineForce` routed through the current gear (so it strengthens as the car downshifts) whenever the throttle is lifted and a `powertrain` is configured. All fields are required; omit the whole block for the legacy model.
716
+ - `KinematicDynamicsTuning` (interface): interface KinematicDynamicsTuning — Aerodynamic and electronic-assist settings layered over tire grip.
717
+ - `KinematicPowertrainTuning` (interface): interface KinematicPowertrainTuning — Data-first gearbox and torque-curve tuning for a kinematic ground vehicle.
718
+ - `KinematicSteeringTuning` (interface): interface KinematicSteeringTuning — Bicycle-model steering settings; all angles are radians.
673
719
  - `KinematicVehicle` (interface): interface KinematicVehicle — The pure-kinematic arcade car every racing game hand-rolled (#282.1): steer-yaw scaled by speed, throttle/brake acceleration, and a grip-curve lateral-slip bleed — no `PhysicsWorld`, no wheels, just the drift-friendly integration the three shipped racers proved out. Games keep their flavor (drift meters, boost, off-track rules) via `surfaceFriction`/`dragAt` hooks and the returned slip.
674
720
  - `KinematicVehicleModifiers` (interface): interface KinematicVehicleModifiers — Per-tick multipliers layered over the base tuning — the transient overrides games apply for one frame without rebuilding the vehicle: nitro/boost, a braced-plow bonus, or entering a speed zone or slow field. Each defaults to `1` (no change), so passing nothing leaves the base tuning untouched.
675
721
  - `KinematicVehicleOptions` (interface): interface KinematicVehicleOptions — ⚠ undocumented
@@ -750,6 +796,12 @@
750
796
  - `createVehicleBody` (function): function createVehicleBody(world: PhysicsWorld, config: VehicleBodyConfig): VehicleBody — ⚠ undocumented
751
797
  - `sampleGripCurve` (function): function sampleGripCurve(curve: GripCurve, slip: number): number — Piecewise-linear tire-grip curve: normalized lateral slip → available grip (0..1). Grip peaks near the breakaway slip then falls off as the tire slides — the shape that separates a planted corner from a drift. Points are read in ascending slip order; ends clamp.
752
798
 
799
+ ## @jgengine/core/physics/vehicleObstacles
800
+
801
+ - `VehicleImpact` (interface): interface VehicleImpact — A single blocked-move event a car can react to (#1051): crash damage, screen shake, a metal-crunch cue. Reported once, when a move is first vetoed, then consumed by {@link VehicleObstacleClamp.takeImpact}.
802
+ - `VehicleObstacleClamp` (interface): interface VehicleObstacleClamp — A planar move clamp for a kinematic car: feed {@link clampMove} to a vehicle's `clampMove` hook so an attempted XZ displacement slides along world solids instead of driving through them, and read {@link takeImpact} once per tick for the crash it produced.
803
+ - `createVehicleObstacleClamp` (function): function createVehicleObstacleClamp(options: { /** Solids near the car this tick (already filtered to the relevant, solid set). */ obstacles: () => readonly CollisionObstacle[]; /** Vehicle body radius (units). Default {@link DEFAULT_VEHICLE_RADIUS}. */ radius?: number; /** Current tick dt (seconds)… — Build a slide-along move clamp for a kinematic car (#1051). `obstacles` is sampled fresh each tick — the caller hands back the already-filtered set of solids near the car — and `dt` supplies the current tick length so a blocked move's lost displacement converts to a closing speed. `radius` inflates each obstacle footprint by the car's body radius (default {@link DEFAULT_VEHICLE_RADIUS}).
804
+
753
805
  ## @jgengine/core/procedural
754
806
 
755
807
  - `DecayMeterSet` (interface): interface DecayMeterSet — Set of named survival meters (hunger/thirst/…) that drain and refill over game time.
@@ -814,16 +866,21 @@
814
866
 
815
867
  - `AuthoredTrigger` (interface): interface AuthoredTrigger — One resolved trigger binding from a document object.
816
868
  - `AuthoredTriggerRuntime` (interface): interface AuthoredTriggerRuntime — Runtime handle that watches authored triggers against moving actors each tick.
869
+ - `BUILTIN_TRIGGER_ACTIONS` (const): const BUILTIN_TRIGGER_ACTIONS: readonly TriggerActionDefinition[] — The engine's built-in trigger actions — the shared `announce` / `win` / `advance` vocabulary every game gets for free, so "enter this zone → win" is authored entirely in the editor with no bespoke action code. Their params land flat on the object's `meta` like any registered action; drive them at runtime with the handlers from {@link createTriggerOutcome}.
817
870
  - `TriggerActionDefinition` (interface): interface TriggerActionDefinition — A game-declared action the editor can assign to a volume/marker trigger. Schema drives the inspector params; `targets`/`events` optionally narrow where it appears.
818
871
  - `TriggerDispatchEvent` (interface): interface TriggerDispatchEvent — Fired when a watched actor trips an authored trigger edge.
819
872
  - `TriggerEvent` (type): type TriggerEvent = "enter" | "exit" | "interact" — Event edge that can fire an authored trigger.
820
873
  - `TriggerHandlers` (type): type TriggerHandlers = Readonly<Record<string, (event: TriggerDispatchEvent) => void>> — Handler map keyed by action id — unknown actions are skipped unless `onDispatch` is set.
874
+ - `TriggerOutcome` (interface): interface TriggerOutcome — Serializable read-model the built-in trigger actions write — the HUD/game reads it each frame.
875
+ - `TriggerOutcomeStore` (interface): interface TriggerOutcomeStore — Outcome store: the built-in action handlers plus a subscribable snapshot of what they produced.
821
876
  - `TriggerSourceKind` (type): type TriggerSourceKind = "marker" | "volume" — Document collection a trigger source lives on.
822
877
  - `collectAuthoredTriggers` (function): function collectAuthoredTriggers(document: SceneDocumentLike): AuthoredTrigger[] — Collect every authored trigger on a document's markers and volumes. Pure — no runtime state. Action params use the live {@link registerTriggerAction} registry when present.
823
878
  - `createAuthoredTriggerRuntime` (function): function createAuthoredTriggerRuntime(options: { document: SceneDocumentLike; handlers?: TriggerHandlers; /** Invoked for every dispatch after the matching handler (if any). */ onDispatch?: (event: TriggerDispatchEvent) => void; /** Override the collected trigger list (tests / hot-reload). Default: … — Build a runtime that watches a document's authored triggers against moving actors and dispatches to per-action handlers (and optional catch-all). Pure membership math; the game supplies actors each tick from its own player/entity poses.
879
+ - `createTriggerOutcome` (function): function createTriggerOutcome(): TriggerOutcomeStore — Default runtime for the built-in {@link BUILTIN_TRIGGER_ACTIONS}: a small serializable outcome the HUD renders, with no engine-side UI. Pass {@link TriggerOutcomeStore.handlers} to {@link createAuthoredTriggerRuntime} and read {@link TriggerOutcomeStore.get} from the HUD via `useSyncExternalStore` — that is the whole zero-code "reach the zone to win" wiring.
824
880
  - `getTriggerAction` (function): function getTriggerAction(id: string): TriggerActionDefinition | undefined — Registered definition for an action id, or undefined when the game never declared it.
825
881
  - `listTriggerActions` (function): function listTriggerActions(target?: TriggerSourceKind): TriggerActionDefinition[] — Every registered action, optionally filtered by target collection.
826
882
  - `pointInVolume` (function): function pointInVolume(volume: SceneVolumeLike, point: { x: number; y: number; z: number }): boolean — True when `point` is inside an editor volume (sphere / cylinder / box). Cylinder height defaults to diameter when omitted; sphere ignores y for the common ground-plane case only when the volume radius covers the full vertical span — here y is tested for sphere and box too.
883
+ - `registerBuiltinTriggerActions` (function): function registerBuiltinTriggerActions(): void — Register the engine's built-in {@link BUILTIN_TRIGGER_ACTIONS} so they appear in the editor's trigger inspector. Idempotent; call at module load (a game may still register its own actions or re-register a built-in id to override it).
827
884
  - `registerTriggerAction` (function): function registerTriggerAction(definition: TriggerActionDefinition): void — Declare a game action the editor can assign to volume/marker triggers. Idempotent per `id` (last registration wins). Call at module load next to catalogs.
828
885
 
829
886
  ## @jgengine/core/scene/autoTarget
@@ -880,22 +937,48 @@
880
937
 
881
938
  - `ColliderDef` (interface): interface ColliderDef — ⚠ undocumented
882
939
  - `ColliderPurpose` (type): type ColliderPurpose = "physical" | "damage" — ⚠ undocumented
883
- - `ColliderShape` (type): type ColliderShape = | { kind: "sphere"; radius: number; offset?: EntityPosition } | { kind: "aabb"; halfExtents: EntityPosition; offset?: EntityPosition } — ⚠ undocumented
940
+ - `ColliderShape` (type): type ColliderShape = | { kind: "sphere"; radius: number; offset?: EntityPosition } | { kind: "aabb"; halfExtents: EntityPosition; offset?: EntityPosition } | { kind: "mesh"; /** Prepared triangle mesh in model space — engine-derived from an opted-in catalog asset, never hand-authored. */ mesh: Prepa… — Collision geometry in entity-local space. `sphere` and `aabb` are analytic; `mesh` carries a prepared triangle mesh so opted-in concave models raycast their real surface while bounds and broadphase keep reading the conservative `halfExtents`.
884
941
  - `DEFAULT_ENTITY_BODY_HALF_EXTENTS` (const): const DEFAULT_ENTITY_BODY_HALF_EXTENTS: EntityPosition — Matches the shell's fallback actor capsule (~0.7m wide, feet at y=0 to head at ~1.8m).
885
942
  - `DEFAULT_ENTITY_BODY_OFFSET` (const): const DEFAULT_ENTITY_BODY_OFFSET: EntityPosition — Entity-local center of the default body hitbox (half its height above the feet).
886
943
  - `DEFAULT_ENTITY_HIT_RADIUS` (const): const DEFAULT_ENTITY_HIT_RADIUS: 0.5 — ⚠ undocumented
887
944
  - `DEFAULT_OBJECT_HALF_EXTENTS` (const): const DEFAULT_OBJECT_HALF_EXTENTS: EntityPosition — ⚠ undocumented
888
945
  - `EntityColliderSet` (interface): interface EntityColliderSet — ⚠ undocumented
946
+ - `MeasuredBounds` (interface): interface MeasuredBounds — Entity-local AABB of what the renderer actually mounted for a kind — the runtime counterpart to index-measured `dims`. Reported through `ctx.scene.entity.reportBounds` / `ctx.scene.object.reportBounds` (the shell does this automatically for custom `renderEntity`/`renderObject` content and models without index dims) so collider resolution can wrap the real rendered shape instead of a fixed-size guess.
947
+ - `ModelBodySource` (interface): interface ModelBodySource — The render-config subset collider fitting reads — structurally satisfied by a resolved `ModelConfig`, so the shell can hand its render config straight to the fitting math without a conversion step.
889
948
  - `ResolvedCollider` (interface): interface ResolvedCollider — ⚠ undocumented
890
949
 
950
+ ## @jgengine/core/scene/collisionMesh
951
+
952
+ - `CollisionMeshData` (interface): interface CollisionMeshData — Compact, serializable triangle collision mesh measured at asset reindex — the renderer-free source of mesh-accurate hitboxes. Positions are welded onto a 16-bit grid spanning `min`..`max` (model space) and stored base64-encoded, so an opted-in catalog asset ships its collision triangles inside the generated index without the runtime ever touching the rendered scene graph.
953
+ - `CollisionMeshHit` (interface): interface CollisionMeshHit — Nearest triangle impact from {@link raycastCollisionMesh}: world distance along the ray and the world-space geometric normal facing the ray.
954
+ - `CollisionMeshSource` (interface): interface CollisionMeshSource — Raw triangle soup for {@link encodeCollisionMesh}: model-space xyz triples plus triangle indices.
955
+ - `PreparedCollisionMesh` (interface): interface PreparedCollisionMesh — Decoded, BVH-indexed triangles ready for per-ray queries — build once per asset via {@link prepareCollisionMesh}. Treat the fields as opaque; they exist so the raycast hot path can run allocation-free over flat arrays.
956
+ - `encodeCollisionMesh` (function): function encodeCollisionMesh(source: CollisionMeshSource): CollisionMeshData | null — Quantize a triangle soup onto the 16-bit grid, weld coincident vertices, and drop triangles that collapse — the reindex-time compressor producing {@link CollisionMeshData}. Returns `null` when no finite, non-degenerate triangle survives.
957
+ - `prepareCollisionMesh` (function): function prepareCollisionMesh(data: CollisionMeshData): PreparedCollisionMesh | null — Decode a stored collision mesh and index it with a BVH. Memoized per data object, so the shell and a headless host preparing the same catalog entry share one build. Returns `null` (also memoized) when the payload is malformed.
958
+ - `raycastCollisionMesh` (function): function raycastCollisionMesh(mesh: PreparedCollisionMesh, origin: EntityPosition, direction: EntityPosition, maxDistance: number, position: EntityPosition, rotationY: number, scale: number, translate: EntityPosition): CollisionMeshHit | null — Nearest triangle hit for a world-space ray against a prepared mesh placed like its rendered model: model space scaled uniformly by `scale`, translated by entity-local `translate`, yaw-rotated by `rotationY`, and moved to `position` — the same composition {@link "scene/colliders".ModelBodySource} fitting applies to the AABB. Allocation-free until the returned hit. `distance` is world distance along `direction` (callers pass `direction` normalized); `normal` is the world-space geometric triangle normal facing the ray.
959
+
960
+ ## @jgengine/core/scene/companion
961
+
962
+ - `CompanionAdoptOptions` (interface): interface CompanionAdoptOptions — Options for {@link CompanionRoster.adopt}.
963
+ - `CompanionCommand` (type): type CompanionCommand = "follow" | "stay" | "passive" | "neutral" | "aggressive" — A tamed companion's standing order. Genre-agnostic aggression + posture preset: - `follow` — heel to the owner and assist whatever the owner is fighting. - `stay` — hold at `home` and assist the owner's target from there. - `passive` — heel to the owner and never engage (a pacifist escort). - `neutral` — heel to the owner and only fight back nearby threats (defensive). - `aggressive` — heel to the owner and proactively engage nearby threats and the owner's target.
964
+ - `CompanionConfig` (interface): interface CompanionConfig — Per-companion configuration shared by every companion the roster mints.
965
+ - `CompanionIntent` (interface): interface CompanionIntent — The companion's decision for one tick, shaped for `ai/mobBrain`: feed `candidates` into `MobBrainDeps.candidates()`, treat `leashTo` as the brain's `home`, and pass `leashDistance` as `leashDistance`. `kind` summarises the posture for HUD/animation.
966
+ - `CompanionIntentContext` (interface): interface CompanionIntentContext — Per-tick world context the game supplies so a command resolves into a concrete intent.
967
+ - `CompanionRecord` (interface): interface CompanionRecord — Serializable per-companion state: who owns it, its standing order, where it holds, its leash radius, and its levelled stat pool. Plain data — JSON round-trips without loss.
968
+ - `CompanionRoster` (interface): interface CompanionRoster — A set of tamed companions keyed by companion id, scoped to owners. Wraps allegiance/command state, per-companion levelled stats, and intent resolution behind create/command/level/ snapshot/hydrate — the counterpart of `scene/roster` for creatures that fight beside you.
969
+ - `CompanionSpendResult` (type): type CompanionSpendResult = | { status: "ok"; record: CompanionRecord; stat: StatValue } | { status: "rejected"; reason: string } — Outcome of {@link CompanionRoster.spend}: the updated record + stat, or a rejection reason.
970
+ - `CompanionStatUpgrade` (interface): interface CompanionStatUpgrade — Rule for turning one spent level-point into a stat gain. Absent from config ⇒ the stat can't be upgraded.
971
+ - `createCompanionRoster` (function): function createCompanionRoster(config: CompanionConfig = {}): CompanionRoster — Build a {@link CompanionRoster}. Composes `scene/roster` ownership (via `ownerId`/`sourceId`), `scene/entityStats` for the per-companion stat pool, and {@link resolveCompanionIntent} for `ai/mobBrain`-shaped behavior — turning a captured creature into a loyal, levelling ally.
972
+ - `resolveCompanionIntent` (function): function resolveCompanionIntent(record: CompanionRecord, context: CompanionIntentContext): CompanionIntent — Pure command → intent resolver. Maps a companion's standing order plus this tick's owner position, owner target, and nearby threats into the {@link CompanionIntent} a game feeds into `ai/mobBrain` (or executes directly). Deterministic and allocation-light — no import of the `@internal` brain factory; the two interoperate purely by shape.
973
+
891
974
  ## @jgengine/core/scene/entityStats
892
975
 
893
- - `EntityStatsApi` (interface): interface EntityStatsApi — ⚠ undocumented
976
+ - `EntityStatsApi` (interface): interface EntityStatsApi extends StatPoolAccess — Native entity-stat adapter over the portable {@link StatPoolAccess} contract.
894
977
  - `PoolDeltaResult` (type): type PoolDeltaResult = | { status: "ok"; map: StatValueMap; stat: StatValue; hitMin: boolean; hitMax: boolean } | { status: "rejected"; reason: string } — ⚠ undocumented
895
978
  - `StatCatalog` (type): type StatCatalog = Record<string, { max: number; min?: number; current?: number }> — ⚠ undocumented
896
- - `StatValue` (interface): interface StatValue — ⚠ undocumented
979
+ - `StatValue` (interface): interface StatValue extends StatPool — Native entity-stat name retained as a compatibility bridge to the portable pool model.
897
980
  - `StatValueMap` (type): type StatValueMap = Record<string, StatValue> — ⚠ undocumented
898
- - `StatValuePatch` (interface): interface StatValuePatch — ⚠ undocumented
981
+ - `StatValuePatch` (interface): interface StatValuePatch extends StatPoolPatch — Native entity-stat patch retained as a compatibility bridge.
899
982
 
900
983
  ## @jgengine/core/scene/entityStore
901
984
 
@@ -1011,6 +1094,7 @@
1011
1094
  - `ParamField` (type): type ParamField = | RangeParamField | NumberParamField | BoolParamField | SelectParamField | ColorParamField | TextParamField | SeedParamField | WeightedListParamField | ActionParamField — One row in a kind's parameter schema — the union the generic inspector knows how to render.
1012
1095
  - `ParamGroup` (interface): interface ParamGroup — A named, optionally-collapsed section the inspector groups fields under (by `field.group === id`).
1013
1096
  - `ParamIssue` (interface): interface ParamIssue — One validation problem found by {@link validateParams}: which field and why.
1097
+ - `ParamPreset` (interface): interface ParamPreset — A named slider/weight bundle for a kind — a saved set of field values the inspector (or the `apply_preset` verb) writes into an object's `meta` in one patch, ready to tweak afterwards. Presets are plain data on the schema, so kinds ship archetypes and games can override the registration with their own.
1014
1098
  - `ParamSchema` (interface): interface ParamSchema — A kind's full parameter surface: an ordered list of fields the inspector renders top-to-bottom.
1015
1099
  - `ParsedParams` (type): type ParsedParams = Record<string, number | boolean | string | WeightedParamEntry[]> — Parsed params after `parseParams`: every schema field present with a validated, defaulted value.
1016
1100
  - `RangeParamField` (interface): interface RangeParamField — A numeric slider row: bounded range with a live readout.
@@ -1024,6 +1108,7 @@
1024
1108
  - `TextParamField` (interface): interface TextParamField — A free string input.
1025
1109
  - `WeightedListParamField` (interface): interface WeightedListParamField — A repeatable list of weighted `{ item, weight }` rows (species palette, book set, …).
1026
1110
  - `WeightedParamEntry` (interface): interface WeightedParamEntry — One weighted entry in a `weightedList` param — an item id and its relative spawn weight.
1111
+ - `findSchemaPreset` (function): function findSchemaPreset(schema: ParamSchema, id: string): ParamPreset | undefined — Look up a schema preset by id, or undefined — the seam `apply_preset` and games resolve bundles through.
1027
1112
  - `parseParams` (function): function parseParams(schema: ParamSchema, meta: Record<string, unknown> | undefined): ParsedParams — Parse a raw `meta` bag against a schema into typed params — every field present, invalid/missing values replaced by the field default, numbers clamped to their range. The single parser every studio shares instead of hand-writing its own `metaNumber`/`metaBool` ladder.
1028
1113
  - `registerSceneKind` (function): function registerSceneKind<TResolved>(definition: SceneKindDefinition<TResolved>): void — Register a scene kind — the plug-in point for a new parametric studio. Idempotent per `kind` (last registration wins), so a game's registration overrides a default. Call at module load; the editor inspector, `+ Add` menu, and `AuthoredScene` renderer lookup all read this registry.
1029
1114
 
@@ -1321,6 +1406,11 @@
1321
1406
  - `AcquisitionRetention` (interface): interface AcquisitionRetention — Retention hysteresis that keeps an already-held target from flickering under churn.
1322
1407
  - `AddBodyOptions` (type): type AddBodyOptions = BoxBodyOptions | SphereBodyOptions — ⚠ undocumented
1323
1408
  - `Aim` (type): type Aim = | { origin: EntityPosition; direction: EntityPosition } | { yaw: number; pitch: number; spread?: number } — ⚠ undocumented
1409
+ - `AircraftDynamics` (interface): interface AircraftDynamics — Stateful six-degree-of-freedom aircraft simulation.
1410
+ - `AircraftKind` (type): type AircraftKind = "fixedWing" | "rotorcraft" | "vtol" — Supported aerodynamic/propulsion families.
1411
+ - `AircraftOptions` (interface): interface AircraftOptions — Spawn state and injectable world-field samplers for an aircraft instance.
1412
+ - `AircraftStep` (interface): interface AircraftStep — Pose and aerodynamic telemetry returned after one flight tick.
1413
+ - `AircraftTuning` (interface): interface AircraftTuning — Data-first physical tuning shared by all aircraft instances of one catalog type.
1324
1414
  - `AreaDistribution` (type): type AreaDistribution = "uniform" | "edge" — Fill policy for a rect/box: `"uniform"` = even coverage; `"edge"` = biased to a boundary band.
1325
1415
  - `AreaEffectEvent` (interface): interface AreaEffectEvent<P> — One membership edge emitted by `step`, `removeSource`, or `clear`.
1326
1416
  - `AreaEffectField` (interface): interface AreaEffectField<P> — Runtime handle tracking continuous area membership across ticks.
@@ -1353,24 +1443,57 @@
1353
1443
  - `BehaviorSnapshot` (type): type BehaviorSnapshot = | { readonly kind: "patrol"; readonly state: PathFollowState } | { readonly kind: "wander"; readonly origin: Waypoint; readonly target: Waypoint | null } — Serializable snapshot of one behavior instance — round-trips exactly through {@link BehaviorControl.serialize}/{@link BehaviorControl.restore}.
1354
1444
  - `BehaviorStatus` (type): type BehaviorStatus = "active" | "paused" | "disabled" — Whether a behavior instance advances and writes pose (`active`), is temporarily suspended retaining state (`paused`), or is held off until re-enabled (`disabled`).
1355
1445
  - `BiomeBand` (interface): interface BiomeBand — A z-ordered ground palette zone — the linear-boundary counterpart to the radial `materialRegions`. Adjacent bands cross-fade into each other across a `fade`-wide window centered on the midpoint z between their centers, so a multi-biome world (vale → marsh → peaks along z) blends its ground color instead of hard-switching. Bands may also carry per-zone `fog`, `sky`, and `weather`. Order the list by ascending `z`.
1446
+ - `BoardGround` (interface): interface BoardGround — A 2D surface you look at — grid games, solitaire, tabletop. Physics is often zero-gravity or omitted; the game owns the face it draws on the board.
1447
+ - `BoardGroundSize` (interface): interface BoardGroundSize — Size of a `board` ground: a 2D surface you look at, in cells or layout units.
1356
1448
  - `BookmarkRecallMode` (type): type BookmarkRecallMode = "replace" | "merge" — How a recalled bookmark folds into the active selection.
1357
1449
  - `BoundsSpec` (type): type BoundsSpec = | { readonly kind: "sphere"; readonly radius: number; readonly offset?: Vec3 } | { readonly kind: "aabb"; readonly half: Vec3; readonly offset?: Vec3 } | { readonly kind: "rect"; readonly halfWidth: number; readonly halfDepth: number; readonly halfHeight?: number; readonly offset?:… — How a renderable declares its extent. AABB, bounding sphere, and 2D rectangle cover the common cases; `point` is the degenerate zero-size default for objects that never override. `offset` shifts the volume from the object origin (e.g. a tall model whose pivot is at its feet).
1358
1450
  - `BoxFormationOptions` (interface): interface BoxFormationOptions — Options for {@link boxFormation}.
1359
1451
  - `BuildRole` (type): type BuildRole = "owner" | "editor" | "viewer" — ⚠ undocumented
1360
- - `BuildingEnvironmentDescriptor` (type): type BuildingEnvironmentDescriptor = { kind: "building" } & Required< Pick<BuildingEnvironmentConfig, "count" | "footprint" | "stories" | "storyHeight" | "spacing" | "style"> > & Pick<BuildingEnvironmentConfig, "seed" | "position" | "palette"> — ⚠ undocumented
1452
+ - `BuildingEnvironmentDescriptor` (type): type BuildingEnvironmentDescriptor = { kind: "building" } & Required< Pick<BuildingEnvironmentConfig, "count" | "footprint" | "stories" | "storyHeight" | "spacing" | "style"> > & Pick<BuildingEnvironmentConfig, "seed" | "position" | "palette" | "along"> — ⚠ undocumented
1361
1453
  - `BuildingIndex` (interface): interface BuildingIndex — ⚠ undocumented
1362
1454
  - `BuildingPaletteOverrides` (type): type BuildingPaletteOverrides = Partial<BuildingPalette> — ⚠ undocumented
1363
1455
  - `BuildingStyle` (type): type BuildingStyle = | "generic" | "capital" | "village" | "desert" | "industrial" | "coastal" | "neon" | "ruin" | "frontier" | "aerial" — ⚠ undocumented
1456
+ - `CITY_DEFAULTS` (const): const CITY_DEFAULTS: CityRules — City defaults: a zoned mixed metropolis — towers downtown, slabs mid-ring, houses at the edge.
1457
+ - `CITY_KIND` (const): const CITY_KIND: "city" — The editor volume kind marking a box as a procedural city district.
1458
+ - `CITY_LOT_CLASSES` (const): const CITY_LOT_CLASSES: readonly CityLotClass[] — All classes, for schema hints and validation.
1459
+ - `CITY_SCHEMA` (const): const CITY_SCHEMA: ParamSchema — The city parameter schema — drives the inspector sliders and `meta` parse via the studio seam.
1460
+ - `CITY_TREE_SPECIES` (const): const CITY_TREE_SPECIES: readonly CityTreeSpecies[] — All species, for schema hints and validation.
1461
+ - `CITY_ZONE_KIND` (const): const CITY_ZONE_KIND: "cityzone" — The editor volume kind that locally overrides a city's zone band/mix — a district in a district.
1462
+ - `CITY_ZONE_SCHEMA` (const): const CITY_ZONE_SCHEMA: ParamSchema — Zone-override schema for `cityzone` volumes: pin a band and optionally a bespoke class mix.
1364
1463
  - `CameraView` (type): type CameraView = PerspectiveView | OrthographicView — ⚠ undocumented
1365
1464
  - `CameraVisibilityContext` (interface): interface CameraVisibilityContext — A camera's contribution to visibility. The VisibilitySystem unions results across every active context: an object stays renderable/loaded if *any* relevant camera needs it. A camera can opt out of driving asset streaming (e.g. a minimap that only needs positions, not loaded meshes) via `influencesStreaming: false`.
1366
1465
  - `Cardinal` (type): type Cardinal = "N" | "NE" | "E" | "SE" | "S" | "SW" | "W" | "NW" — ⚠ undocumented
1367
1466
  - `Carryable` (class): class Carryable — A grabbed physics object following a moving hold point through a spring constraint (the pick — a raycast — is the caller's/shell's job; core owns the constraint). Supports shared multi-owner carry (the follow point is the average of owners' hold points), an encumbrance read, and drop/throw. Reuses `PhysicsWorld.springJoint` to a world anchor moved each frame.
1368
1467
  - `CarvableField` (class): class CarvableField implements TerrainField — A `TerrainField` you can write craters and mounds into at runtime — the height-field side of destructible terrain (Helldivers 2 explosion craters, engineer-deposited berms). Wraps a base field and layers smooth radial deformations on top, so `sampleHeight` (and therefore ground-snap, collision, and the shell's terrain mesh) all read the deformed surface. `carve` digs a bowl, `deposit` raises a mound.
1369
1468
  - `CircleFormationOptions` (interface): interface CircleFormationOptions — Options for {@link circleFormation}.
1469
+ - `CityBlock` (interface): interface CityBlock — One closed city block: a face of the road graph, inset to curb and land boundaries.
1470
+ - `CityBlockKind` (type): type CityBlockKind = "buildable" | "park" | "plaza" | "field" | "buffer" — How a block (a face of the road graph) is used.
1471
+ - `CityBridge` (interface): interface CityBridge — One bridge deck spanning water: bank-to-bank polyline plus the silhouette style.
1472
+ - `CityDriveway` (interface): interface CityDriveway — One driveway ribbon from a street to a lot.
1473
+ - `CityHedge` (interface): interface CityHedge — One hedge run: a thin box strip (estate perimeter).
1474
+ - `CityIntersection` (interface): interface CityIntersection — One crossing of two through streets: patch center/radius plus crosswalk arm directions.
1475
+ - `CityLight` (interface): interface CityLight — One street light: curb position plus the yaw its arm faces (over the road).
1476
+ - `CityLot` (interface): interface CityLot — One building lot: footprint, zone band, class, seeded floors, massing pieces, street anchor.
1477
+ - `CityLotClass` (type): type CityLotClass = | "tower" | "slab" | "shop" | "rowhouse" | "house" | "mansion" | "farmhouse" | "barn" | "silo" — A building class a zone mix can weight — drives lot size, floors, setback, and massing.
1478
+ - `CityLotPiece` (interface): interface CityLotPiece — One massing piece in LOT-LOCAL space: x along frontage width, z into the block, y up from grade.
1479
+ - `CityParcel` (interface): interface CityParcel — One polygonal parcel subdivided from a block's street frontage.
1480
+ - `CityParcelFrontageOut` (interface): interface CityParcelFrontageOut — One street-frontage edge of a parcel.
1481
+ - `CityPark` (interface): interface CityPark — One intentional open space: an unbuilt block, a block-interior courtyard, or a buffer sliver.
1482
+ - `CityParking` (interface): interface CityParking — One parking pad behind a commercial lot.
1483
+ - `CityPieceRole` (type): type CityPieceRole = "wall" | "roof" | "trim" | "accent" — Palette role a piece colors from (wall/roof/trim/accent map onto the district's style palette).
1484
+ - `CityPieceShape` (type): type CityPieceShape = "box" | "gable" | "cylinder" | "dome" — Primitive shapes massing pieces instance — the renderer keeps one InstancedMesh per shape.
1485
+ - `CityResolveContext` (interface): interface CityResolveContext extends SceneKindResolveContext — Extended resolve context: sibling `cityzone` volumes that override the band/mix locally.
1486
+ - `CityRules` (interface): interface CityRules — Fully-defaulted city params parsed from a volume's `meta`.
1487
+ - `CityStreet` (interface): interface CityStreet — One synthesized street: a world-space XZ polyline with width, hierarchy level, and surface.
1488
+ - `CityTree` (interface): interface CityTree — One placed tree: world XZ, species, and seeded scale/color jitter.
1489
+ - `CityTreeSpecies` (type): type CityTreeSpecies = "broadleaf" | "conifer" | "palm" | "cypress" — Tree species a district's tree mix can weight — the renderer keeps one canopy mesh per species.
1490
+ - `CityZoneBand` (type): type CityZoneBand = "core" | "mid" | "edge" — Zone band a lot falls in: dense core, middle ring, or the district edge.
1491
+ - `CityZoneProfile` (type): type CityZoneProfile = "core-out" | "inverted" | "uniform" — How the radial zone metric maps to bands.
1370
1492
  - `ClockSnapshot` (interface): interface ClockSnapshot — ⚠ undocumented
1371
1493
  - `CollapseEvent` (interface): interface CollapseEvent — ⚠ undocumented
1372
1494
  - `ColliderPurpose` (type): type ColliderPurpose = "physical" | "damage" — ⚠ undocumented
1373
1495
  - `CollisionEvent` (interface): interface CollisionEvent — A contact reported to `onCollision`. The object is reused each call — read/copy, never retain.
1496
+ - `CollisionObstacle` (interface): interface CollisionObstacle — A placed scene object the walking player collides against as a circle-vs-AABB obstacle.
1374
1497
  - `ConcealmentSensor` (interface): interface ConcealmentSensor — ⚠ undocumented
1375
1498
  - `ContextMenu` (interface): interface ContextMenu — ⚠ undocumented
1376
1499
  - `ContextVerb` (interface): interface ContextVerb — One right-click verb: a label plus the command it dispatches (walk-then-act supported by args).
@@ -1382,6 +1505,7 @@
1382
1505
  - `DEFAULT_FORWARD` (const): const DEFAULT_FORWARD: readonly [number, number, number] — The forward-axis convention: a generator or scene kind declares which way its "front" faces (a bookcase's open/book face, a building's entrance) once, as data, instead of leaving every placement to hand-tuned `rotationY` trial-and-error. `StudioStage`'s `faceCamera` (`@jgengine/shell/scene/ StudioStage`) reads the declared axis to auto-orient a product shot; a placement tool can read the same field to face a freshly dropped asset toward the camera/path by default. `DEFAULT_FORWARD` (+Z) is what a generator/scene-kind gets when it omits `forward` — build your front toward it.
1383
1506
  - `DEFAULT_GRIP_CURVE` (const): const DEFAULT_GRIP_CURVE: GripCurve — ⚠ undocumented
1384
1507
  - `DEFAULT_MARKER_KINDS` (const): const DEFAULT_MARKER_KINDS: Record<string, MarkerKindStyle> — ⚠ undocumented
1508
+ - `DEFAULT_MINIMAP_PALETTE` (const): const DEFAULT_MINIMAP_PALETTE: MinimapBakePalette — The built-in height→color ramp and water color a bake uses when no palette override is given.
1385
1509
  - `DEFAULT_REPUTATION_TIERS` (const): const DEFAULT_REPUTATION_TIERS: readonly ReputationTier[] — ⚠ undocumented
1386
1510
  - `DrapeOptions` (interface): interface DrapeOptions — Shaping for surface draping: subdivision spacing and a lift to keep the line off the ground.
1387
1511
  - `EditableTerrain` (interface): interface EditableTerrain extends TerrainField — ⚠ undocumented
@@ -1398,6 +1522,11 @@
1398
1522
  - `FactionDef` (interface): interface FactionDef — ⚠ undocumented
1399
1523
  - `FallbackPolicy` (type): type FallbackPolicy<P extends SamplePoint = SamplePoint> = | "none" | "last-candidate" | { readonly point: P } — What to return when the attempt budget is exhausted. `"none"` yields no point (honest failure); `"last-candidate"` returns the final rejected draw (post-projection); `{ point }` returns a caller fixed fallback (a hand-placed safe spot). Explicit, so a caller never mistakes a fallback for a hit.
1400
1524
  - `FireGrid` (interface): interface FireGrid — ⚠ undocumented
1525
+ - `FlatGround` (interface): interface FlatGround — A 3D walkable plane/slab. `Infinity` axes are unbounded; no separate "infinite" mode exists.
1526
+ - `FlatGroundSize` (interface): interface FlatGroundSize — Size of a `flat` ground: extents in world units. `Infinity` on an axis means unbounded — an endless plain needs no bounds number invented for it. `y` optionally bounds vertical play space.
1527
+ - `FlightControlInput` (interface): interface FlightControlInput — Normalized pilot inputs for one flight-simulation tick.
1528
+ - `FlightControlRates` (interface): interface FlightControlRates — Angular authority, response, damping, and self-leveling configuration.
1529
+ - `FlightVector` (type): type FlightVector = readonly [number, number, number] — Three-dimensional world-space vector used by the flight model.
1401
1530
  - `FogCells` (interface): interface FogCells — ⚠ undocumented
1402
1531
  - `FogField` (interface): interface FogField — Reveal-on-event fog of war over a fixed grid. Walking (`revealAlong`) and digging/acting (`reveal`) clear cells; once revealed a cell stays revealed. Pure and renderer-free — the shell/react map draws `cells()`.
1403
1532
  - `ForceVolume` (class): class ForceVolume — A trigger region that pushes bodies passing through it — boost pads (`impulse` + `once`), conveyors (`velocity`), fans/wind (`accelerate`). Call `apply` each tick; `once` mode fires only on entry by tracking membership between ticks.
@@ -1416,7 +1545,12 @@
1416
1545
  - `Glide` (class): class Glide — A reduced-gravity, forward-thrust glide over a physics body — wingsuit / glider / paraglider (Enshrouded, Grounded). Call `apply(dt, steerX, steerZ)` each frame *before* `world.step`: it feeds back most of the gravity the sim is about to apply (leaving `gravityScale` of it), pushes the body along the steer vector by `thrust`, and clamps descent to `maxFallSpeed`. Stop calling it to fall normally again — no attach/detach state to leak.
1417
1546
  - `Grapple` (class): class Grapple — A fired-anchor rope on the joint API — grapple (reel toward a hit point), zipline (rigid cable to a far anchor you then slide/reel along), swing (rigid rope + gravity = a pendulum). `fire` attaches a `distance`/`spring` joint from the traveller body to a fixed world point; `reel` shrinks its rest length so the constraint drags the body in; `moveAnchor` re-points it (zipline glide, grapple-to- moving-target). The pick — a raycast to find the anchor — is the caller's; core owns the constraint.
1418
1547
  - `GrassEnvironmentDescriptor` (type): type GrassEnvironmentDescriptor = { kind: "grass" } & Required< Pick<GrassEnvironmentConfig, "area" | "density" | "bladeHeight" | "bladeWidth" | "windStrength" | "colors"> > & Pick<GrassEnvironmentConfig, "seed"> — ⚠ undocumented
1548
+ - `GravityField` (interface): interface GravityField — Position-dependent gravity source used by movement and vehicle simulations.
1549
+ - `GravityVector` (type): type GravityVector = readonly [number, number, number] — Three-dimensional acceleration vector sampled from a gravity field.
1419
1550
  - `GripCurve` (interface): interface GripCurve — ⚠ undocumented
1551
+ - `GroundConfig` (type): type GroundConfig = FlatGround | RoundGround | VoxelGround | BoardGround — The substrate of a place, discriminated by `mode` — TS rejects a `radius` on `flat` and `x`/`z` on `round`.
1552
+ - `GroundGenerator` (interface): interface GroundGenerator — Serializable algorithm parameters for a procedural ground generator. Never a genre kit.
1553
+ - `GroundMode` (type): type GroundMode = "flat" | "round" | "voxel" | "board" — Canonical ground modes after normalization (`stage` → `board`).
1420
1554
  - `GroundPoint` (type): type GroundPoint = readonly [number, number] — A world-space point on the ground plane as an `[x, z]` pair.
1421
1555
  - `GuideRegion` (interface): interface GuideRegion — An axis-aligned XZ rectangle to generate terrain-readability guides within.
1422
1556
  - `HeatConfig` (interface): interface HeatConfig — Tuning for {@link createHeatState}/{@link advanceHeat} — levels, decay, and pursuit-spawn ring.
@@ -1437,6 +1571,10 @@
1437
1571
  - `Job` (interface): interface Job — ⚠ undocumented
1438
1572
  - `JobDef` (interface): interface JobDef — ⚠ undocumented
1439
1573
  - `JobReport` (interface): interface JobReport — ⚠ undocumented
1574
+ - `KinematicChassisTuning` (interface): interface KinematicChassisTuning — Mass-and-force chassis layer (#1051); when present it supersedes `engineAccel`/`brakeAccel` with force/mass dynamics. Drive/brake become forces divided by `massKg`, a per-tick tire friction budget (`tireGrip` * grip curve * surface * downforce * m * g) is split lateral-first then longitudinal so hard slides and launches saturate, and `comHeight`/`trackWidth` set weight-transfer washout and body lean. Coasting decelerates from physical road load, not a per-vehicle constant: rolling resistance `μ_rr · m · g` always, plus engine braking `ENGINE_BRAKE_FRACTION · engineForce` routed through the current gear (so it strengthens as the car downshifts) whenever the throttle is lifted and a `powertrain` is configured. All fields are required; omit the whole block for the legacy model.
1575
+ - `KinematicDynamicsTuning` (interface): interface KinematicDynamicsTuning — Aerodynamic and electronic-assist settings layered over tire grip.
1576
+ - `KinematicPowertrainTuning` (interface): interface KinematicPowertrainTuning — Data-first gearbox and torque-curve tuning for a kinematic ground vehicle.
1577
+ - `KinematicSteeringTuning` (interface): interface KinematicSteeringTuning — Bicycle-model steering settings; all angles are radians.
1440
1578
  - `KinematicVehicle` (interface): interface KinematicVehicle — The pure-kinematic arcade car every racing game hand-rolled (#282.1): steer-yaw scaled by speed, throttle/brake acceleration, and a grip-curve lateral-slip bleed — no `PhysicsWorld`, no wheels, just the drift-friendly integration the three shipped racers proved out. Games keep their flavor (drift meters, boost, off-track rules) via `surfaceFriction`/`dragAt` hooks and the returned slip.
1441
1579
  - `KinematicVehicleStep` (interface): interface KinematicVehicleStep — ⚠ undocumented
1442
1580
  - `KinematicVehicleTuning` (interface): interface KinematicVehicleTuning — ⚠ undocumented
@@ -1451,11 +1589,21 @@
1451
1589
  - `MOVEMENT_TUNING` (const): const MOVEMENT_TUNING: { readonly standEyeHeight: 1.7; readonly crouchEyeHeight: 1.15; readonly walkSpeedMultiplier: 1.75; readonly runSpeedMultiplier: 2.25; readonly crouchSpeedMultiplier: 0.45; readonly backpedalSpeedMultiplier: 0.65; readonly groundAcceleration: 26; readonly airAcceleration: 12; … — Kinematics + feel tuning for the first-person controller. Centralised here so movement feel lives in one place rather than scattered through the renderer.
1452
1590
  - `MagnitudeOf` (type): type MagnitudeOf<P> = (membership: AreaMembership<P>) => number — Read a comparable magnitude from a membership (e.g. buff strength, damage per tick).
1453
1591
  - `MapCellStates` (interface): interface MapCellStates — ⚠ undocumented
1454
- - `MapMarker` (interface): interface MapMarker<TMeta = unknown> — ⚠ undocumented
1592
+ - `MapMarker` (interface): interface MapMarker<TMeta = unknown> extends MarkerView<TMeta> — A marker owned by {@link MarkerSet}, including its lifecycle and query fields.
1455
1593
  - `MapRoute` (interface): interface MapRoute — ⚠ undocumented
1456
1594
  - `MapZone` (interface): interface MapZone — ⚠ undocumented
1595
+ - `MarkerCollection` (type): type MarkerCollection<TMarker extends MarkerView = MarkerView> = | readonly TMarker[] | MarkerSource<TMarker> | MarkerSet — Marker data accepted by portable consumers: static views, an external source, or a native set.
1457
1596
  - `MarkerKindStyle` (interface): interface MarkerKindStyle — Visual descriptor for a marker kind. Games supply their own palette; the engine ships `DEFAULT_MARKER_KINDS` as a content-agnostic starting set that the react minimap/compass read for colors and glyphs.
1458
1597
  - `MarkerSet` (interface): interface MarkerSet<TMeta = unknown> — ⚠ undocumented
1598
+ - `MarkerSource` (interface): interface MarkerSource<TMarker extends MarkerView = MarkerView> — Observable marker snapshots owned by an external project. `getSnapshot` must return the same array identity until the source changes and calls its subscribers, matching React's external-store contract.
1599
+ - `MarkerSourceOptions` (interface): interface MarkerSourceOptions<TEntity, TMarker extends MarkerView = MarkerView> — Configuration for projecting a caller-owned collection into display-only markers.
1600
+ - `MarkerView` (interface): interface MarkerView<TMeta = unknown> — Small, display-only marker shape consumed by map renderers. Existing games can project their own entities to this view without adopting marker lifecycle storage or duplicating them into a {@link MarkerSet}.
1601
+ - `MinimapBake` (interface): interface MinimapBake — A baked minimap image: RGBA pixels plus the world bounds they span.
1602
+ - `MinimapBakeBounds` (interface): interface MinimapBakeBounds — Deterministic minimap terrain bake (#1036): rasterize an authored world's terrain (plus optional biome zones and water) into a top-down RGBA image and a matching world-bounds rectangle, then encode it as a PNG data URI. The editor runs this as a bake action and stores the result on the scene document; runtime feeds it straight into the existing `Minimap` / `WorldMap` `background` + `mapBounds` props — no new runtime render path, and the same authored world always bakes the same image (safe for verify/CI). Pure: no canvas, no DOM, `core` still imports nothing external.
1603
+ - `MinimapBakeOptions` (interface): interface MinimapBakeOptions — Options for {@link bakeMinimapImage}.
1604
+ - `MinimapBakePalette` (interface): interface MinimapBakePalette — The height→color ramp and water color used by the bake.
1605
+ - `MinimapBakeSource` (interface): interface MinimapBakeSource — The authored world a bake reads — a height sampler, its bounds, and optional zones/water.
1606
+ - `MinimapBakeZone` (interface): interface MinimapBakeZone — One biome/region tint painted over the terrain shade where the ground falls inside its polygon.
1459
1607
  - `MinimapView` (interface): interface MinimapView — ⚠ undocumented
1460
1608
  - `ModelAssetRef` (interface): interface ModelAssetRef — ⚠ undocumented
1461
1609
  - `ModelDims` (interface): interface ModelDims — Measured horizontal footprint, footprint center, and lowest Y of a model in model space.
@@ -1494,11 +1642,13 @@
1494
1642
  - `OrderTargeting` (interface): interface OrderTargeting — Narrow targeting adapter for engagement verbs. `acquire` returns the id of a hostile within `radius` (nearest, or whatever policy the game injects), and `positionOf` locates a known target. Actual damage/effects stay game-side.
1495
1643
  - `OrderTickReport` (interface): interface OrderTickReport<TPayload = unknown> — What one `tick` did this frame, for tests and game reactions (play a bark on activation, flash on completion). Bounded per tick.
1496
1644
  - `OrderVec3` (type): type OrderVec3 = readonly [number, number, number] — Composable entity orders: a serializable command queue with lifecycle, preemption, and pluggable order kinds (#912). Player- or AI-issued intent ("move here", "attack that", "patrol this route") becomes reusable data instead of a hard-coded RTS verb kit. The queue owns issue -> activate -> tick -> complete/cancel lifecycle and deterministic preemption policy; each order KIND owns what "running" means, composed over narrow world adapters. Engine code never branches on `move`, `attack`, or any game verb -- kinds are looked up by string in a registry, so a game adds a verb by registering data.
1645
+ - `POLE_LINE_SCHEMA` (const): const POLE_LINE_SCHEMA: ParamSchema — The pole-line parameter schema — drives the inspector and `meta` parse via the studio seam.
1497
1646
  - `POSE_HITBOX` (const): const POSE_HITBOX: Record<MovementPose, PoseHitbox> — ⚠ undocumented
1498
1647
  - `PadEnvironmentDescriptor` (type): type PadEnvironmentDescriptor = { kind: "pad" } & Required< Pick<PadEnvironmentConfig, "center" | "size" | "height" | "color"> > & Pick<PadEnvironmentConfig, "rotationY" | "elevation"> — ⚠ undocumented
1499
1648
  - `PadSize` (type): type PadSize = readonly [number, number] | { radius: number } — ⚠ undocumented
1500
1649
  - `PaintStroke` (interface): interface PaintStroke — ⚠ undocumented
1501
1650
  - `ParamField` (type): type ParamField = | RangeParamField | NumberParamField | BoolParamField | SelectParamField | ColorParamField | TextParamField | SeedParamField | WeightedListParamField | ActionParamField — One row in a kind's parameter schema — the union the generic inspector knows how to render.
1651
+ - `ParamPreset` (interface): interface ParamPreset — A named slider/weight bundle for a kind — a saved set of field values the inspector (or the `apply_preset` verb) writes into an object's `meta` in one patch, ready to tweak afterwards. Presets are plain data on the schema, so kinds ship archetypes and games can override the registration with their own.
1502
1652
  - `ParamSchema` (interface): interface ParamSchema — A kind's full parameter surface: an ordered list of fields the inspector renders top-to-bottom.
1503
1653
  - `ParsedParams` (type): type ParsedParams = Record<string, number | boolean | string | WeightedParamEntry[]> — Parsed params after `parseParams`: every schema field present with a validated, defaulted value.
1504
1654
  - `PathFollowConfig` (interface): interface PathFollowConfig — ⚠ undocumented
@@ -1512,6 +1662,8 @@
1512
1662
  - `PhysicsStats` (interface): interface PhysicsStats — ⚠ undocumented
1513
1663
  - `PhysicsWorld` (class): class PhysicsWorld — ⚠ undocumented
1514
1664
  - `PlaceAssetResult` (interface): interface PlaceAssetResult — Shared place-asset verb: one resolved payload for editor `place_asset` and in-game build-mode commits. Convert with {@link toStructureInput} / {@link toEditorMarker}.
1665
+ - `PlaceConfig` (interface): interface PlaceConfig — Input to {@link world}: place identity, substrate, and the laws of this place.
1666
+ - `PlaceWorldFeature` (interface): interface PlaceWorldFeature — A declared place — the `world()` result carried on `GameDefinition.world`.
1515
1667
  - `PlacedStructure` (interface): interface PlacedStructure — ⚠ undocumented
1516
1668
  - `PlacementCommit` (interface): interface PlacementCommit — ⚠ undocumented
1517
1669
  - `PlacementController` (interface): interface PlacementController — ⚠ undocumented
@@ -1520,6 +1672,7 @@
1520
1672
  - `PlacementRules` (interface): interface PlacementRules — ⚠ undocumented
1521
1673
  - `PlatformCarry` (class): class PlatformCarry — Carries bodies standing on a moving platform by composing their transform with the platform's per-`step` delta — moving/rotating lifts and conveyor floors (Fall Guys, Gang Beasts). The platform is a body the game repositions each frame; riders are detected by overlap on its top face.
1522
1674
  - `Point3` (type): type Point3 = readonly [number, number, number] — Deterministic spatial sampling — draw one or many positions from a geometric region under explicit constraints, with an injected RNG, bounded attempts, and a structured pass/fail result.
1675
+ - `PointGravityOptions` (interface): interface PointGravityOptions — Center, strength, and falloff for radial gravity.
1523
1676
  - `PositionedPrompt` (interface): interface PositionedPrompt — ⚠ undocumented
1524
1677
  - `ProximityPrompt` (interface): interface ProximityPrompt — ⚠ undocumented
1525
1678
  - `QteStep` (interface): interface QteStep — ⚠ undocumented
@@ -1530,14 +1683,20 @@
1530
1683
  - `RecordingBufferOptions` (interface): interface RecordingBufferOptions — ⚠ undocumented
1531
1684
  - `RegionField` (interface): interface RegionField<T = unknown> extends TerrainField — ⚠ undocumented
1532
1685
  - `Renderable` (interface): interface Renderable — A scene object the visibility system considers. A normal game object already carries a position and a version counter, so it becomes cullable automatically — no separate "cullable" component. Everything else is optional override.
1686
+ - `ResolvedCity` (interface): interface ResolvedCity — A resolved city district: world-space network, zoned lots, parks, and furniture.
1533
1687
  - `ResolvedCollider` (interface): interface ResolvedCollider — ⚠ undocumented
1688
+ - `ResolvedGround` (type): type ResolvedGround = FlatGround | RoundGround | VoxelGround | ResolvedBoardGround — A place's ground after `world()` normalization.
1689
+ - `ResolvedPoleLine` (interface): interface ResolvedPoleLine — The renderable payload the resolver returns and the shell renderer consumes.
1534
1690
  - `ResolvedTerrainDetail` (type): type ResolvedTerrainDetail = Required<Omit<TerrainDetailConfig, "waterLevel" | "material">> & { waterLevel: number; material?: ResolvedTerrainDetailMaterial; } — A {@link TerrainDetailConfig} with every field resolved to a concrete value — the shape the shell's detail material consumes.
1535
1691
  - `ResolvedWeather` (interface): interface ResolvedWeather — ⚠ undocumented
1536
1692
  - `RevealHit` (interface): interface RevealHit — ⚠ undocumented
1537
1693
  - `RevealQuery` (interface): interface RevealQuery — ⚠ undocumented
1538
1694
  - `RoadEnvironmentDescriptor` (type): type RoadEnvironmentDescriptor = { kind: "road" } & Required< Pick<RoadEnvironmentConfig, "path" | "width" | "color" | "markings" | "markingColor" | "elevation"> > & { /** Resolved sidewalk band, or `false` when the road has none. */ sidewalk: { width: number; color: string } | false; } — Resolved road descriptor produced by {@link road} and rendered by the shell environment scene.
1695
+ - `RoadSurfaceOptions` (interface): interface RoadSurfaceOptions — Grip levels and blend width for {@link roadSurfaceSampler}; each field is optional and defaulted.
1539
1696
  - `RoofPlan` (interface): interface RoofPlan — ⚠ undocumented
1540
1697
  - `RosterEntry` (interface): interface RosterEntry — ⚠ undocumented
1698
+ - `RoundGround` (interface): interface RoundGround — A planet/sphere you play on the outside of. Sized by `radius` only.
1699
+ - `RoundGroundSize` (interface): interface RoundGroundSize — Size of a `round` ground: the planet/sphere radius in world units. Nothing else.
1541
1700
  - `SCATTER_PATH_KIND` (const): const SCATTER_PATH_KIND: "scatter" — The editor path kind that marks a closed polyline as a foliage/scatter region.
1542
1701
  - `SHAPE_BOX` (const): const SHAPE_BOX: 0 — ⚠ undocumented
1543
1702
  - `SHAPE_SPHERE` (const): const SHAPE_SPHERE: 1 — ⚠ undocumented
@@ -1582,7 +1741,7 @@
1582
1741
  - `SpawnEntry` (interface): interface SpawnEntry — ⚠ undocumented
1583
1742
  - `SpawnRequest` (interface): interface SpawnRequest — ⚠ undocumented
1584
1743
  - `StatCatalog` (type): type StatCatalog = Record<string, { max: number; min?: number; current?: number }> — ⚠ undocumented
1585
- - `StatValue` (interface): interface StatValue — ⚠ undocumented
1744
+ - `StatValue` (interface): interface StatValue extends StatPool — Native entity-stat name retained as a compatibility bridge to the portable pool model.
1586
1745
  - `Station` (interface): interface Station — ⚠ undocumented
1587
1746
  - `StratifiedOptions` (interface): interface StratifiedOptions — Inputs for {@link sampleStratified}: a grid over `area` with one jittered point per cell.
1588
1747
  - `StructureGraph` (class): class StructureGraph — A structural-integrity graph over a building — nodes are pieces (walls, beams, floors), edges are load-bearing connections, some nodes are anchored foundations. `damage`/`damageEdge` wear pieces and connections down; when a piece shatters or an edge severs, the graph recomputes which pieces still reach an anchor and hands back every newly-disconnected piece as one `CollapseEvent`. Feed that to `toDebris` to sink the fallen pieces into a `PhysicsWorld` as rigid bodies ("The Finals" smooth destruction, Rainbow Six walls). Coarse by design: it replicates the collapse event, not per fragment.
@@ -1591,6 +1750,7 @@
1591
1750
  - `SurfaceDelta` (interface): interface SurfaceDelta — A compact record of the surface-material cells a paint stroke touched: parallel `indices`/`before`/`after` arrays into the per-cell surface grid. One per stroke keeps paint undo history small.
1592
1751
  - `SurfaceGridLine` (interface): interface SurfaceGridLine — One draped grid line from {@link surfaceGridLines}: its axis, emphasis, and draped vertices.
1593
1752
  - `SurfaceGridOptions` (interface): interface SurfaceGridOptions — Shaping for {@link surfaceGridLines}: region, spacing, emphasis cadence, and draping.
1753
+ - `SurfaceLaws` (interface): interface SurfaceLaws — The place model: a world is the place you play in — substrate (ground) plus laws (physics, surface) — never a dressed diorama. Sky look, foliage scatter, props, and sculpt are content: they are authored in the editor (or by a content preset that writes into the scene document) and consumed through the authored-scene seams, not declared on the world.
1594
1754
  - `SurfaceStroke` (interface): interface SurfaceStroke — Accumulates a whole paint drag — many surface stamps — into one compact {@link SurfaceDelta}. Keeps each cell's first `before` and latest `after`, so undo replays the paint as a single step.
1595
1755
  - `SynthPatch` (interface): interface SynthPatch — A procedural sound cue: a set of voices triggered together, each with its own `delay`, summed into one one-shot. Pure serialisable data — the shell realises it on Web Audio, so the same catalog runs headless in tests with no `AudioContext`.
1596
1756
  - `TERRAIN_MATERIAL_PALETTES` (const): const TERRAIN_MATERIAL_PALETTES: Record<TerrainMaterial, TerrainPalette> — ⚠ undocumented
@@ -1629,6 +1789,8 @@
1629
1789
  - `VISIBILITY_OBSERVED` (const): const VISIBILITY_OBSERVED: 2 — Numeric code for a cell a group currently observes.
1630
1790
  - `VISIBILITY_REMEMBERED` (const): const VISIBILITY_REMEMBERED: 1 — Numeric code for a cell seen before but not currently in view (last-known).
1631
1791
  - `Vec3` (type): type Vec3 = EntityPosition — ⚠ undocumented
1792
+ - `VehicleImpact` (interface): interface VehicleImpact — A single blocked-move event a car can react to (#1051): crash damage, screen shake, a metal-crunch cue. Reported once, when a move is first vetoed, then consumed by {@link VehicleObstacleClamp.takeImpact}.
1793
+ - `VehicleObstacleClamp` (interface): interface VehicleObstacleClamp — A planar move clamp for a kinematic car: feed {@link clampMove} to a vehicle's `clampMove` hook so an attempted XZ displacement slides along world solids instead of driving through them, and read {@link takeImpact} once per tick for the crash it produced.
1632
1794
  - `VehicleSeats` (class): class VehicleSeats — Composes `scene/mount`'s control-transfer bookkeeping with the seat/camera/movement-mode transition every enter/exit-vehicle flow needs (#533.2): boarding resolves a free seat and reports the camera target, drive target, and rider movement-lock patch in one call; leaving computes a side-door placement next to the vehicle and reports the same triad in reverse. Pure — no entity/camera side effects — the caller applies `riderMovementPatch`/`placement`/`cameraTarget` via its own `ctx`.
1633
1795
  - `VisibilityCells` (interface): interface VisibilityCells — Dense per-cell readout for one group, shaped for minimap/overlay drawing.
1634
1796
  - `VisibilityConfig` (interface): interface VisibilityConfig — Per-game visibility configuration, surfaced on `PlayableGame.visibility`. Everything is optional: an existing game that sets nothing gets the conservative engine defaults automatically. This is the scene-level and per-kind override seam (requirement: per-object, per-layer, per-scene, and global controls).
@@ -1644,6 +1806,8 @@
1644
1806
  - `VolumetricCloudsConfig` (interface): interface VolumetricCloudsConfig — Volumetric cloud layer config for `sky()` — a raymarched cloud slab mounted from the environment `sky` seam. Pure config + defaulting here; the raymarch shader lives in the `shell` renderer (`environment/VolumetricClouds.tsx`), mounted alongside `SkyDome` whenever a sky descriptor carries this field. Off by default — omit `volumetricClouds` on `sky({...})` and no layer mounts.
1645
1807
  - `VolumetricCloudsRules` (interface): interface VolumetricCloudsRules — Fully-defaulted volumetric cloud params, resolved from a `VolumetricCloudsConfig`.
1646
1808
  - `VoxelFace` (type): type VoxelFace = "px" | "nx" | "py" | "ny" | "pz" | "nz" — ⚠ undocumented
1809
+ - `VoxelGround` (interface): interface VoxelGround — A procedural volume of blocks. `size` is the generator domain; `generator` is algorithm params only.
1810
+ - `VoxelGroundSize` (interface): interface VoxelGroundSize — Size of a `voxel` ground: the generator's domain per axis; axes may be `Infinity` for streaming volumes.
1647
1811
  - `VoxelMaterial` (interface): interface VoxelMaterial — ⚠ undocumented
1648
1812
  - `VoxelVolume` (class): class VoxelVolume — A runtime-editable dense voxel grid — the carve/deposit op behind destructible dig worlds (Deep Rock Galactic tunnels, Astroneer terrain). Cells hold a material id (0 = empty); `carve` clears a sphere of solid cells that a tool is strong enough to break and returns how many it removed (feed that to a loot roll), `deposit` fills a sphere with a material. World↔cell mapping is `origin`+`scale`.
1649
1813
  - `WATER_SCHEMA` (const): const WATER_SCHEMA: ParamSchema — The water parameter schema — drives the inspector and `meta` parse via the studio seam.
@@ -1658,7 +1822,7 @@
1658
1822
  - `WeightedParamEntry` (interface): interface WeightedParamEntry — One weighted entry in a `weightedList` param — an item id and its relative spawn weight.
1659
1823
  - `WeightedRegionEntry` (interface): interface WeightedRegionEntry<P extends SamplePoint = SamplePoint> — A weighted member of a {@link weightedRegion} composite.
1660
1824
  - `WindField` (interface): interface WindField — ⚠ undocumented
1661
- - `WorldFeature` (type): type WorldFeature = | ({ kind: "biomes" } & BiomesWorldConfig) | ({ kind: "voxel" } & VoxelWorldConfig) | ({ kind: "plots" } & PlotsWorldConfig) | ({ kind: "tilemap" } & TilemapWorldConfig) | EnvironmentWorldFeature | { kind: "flat" } — A declared world shape — biomes, voxel grid, plots, tilemap, environment, or flat — passed to `defineGame`.
1825
+ - `WorldFeature` (type): type WorldFeature = | PlaceWorldFeature | ({ kind: "biomes" } & BiomesWorldConfig) | ({ kind: "voxel" } & VoxelWorldConfig) | ({ kind: "plots" } & PlotsWorldConfig) | ({ kind: "tilemap" } & TilemapWorldConfig) | EnvironmentWorldFeature | { kind: "flat" } — A declared world shape passed to `defineGame`. The preferred model is the place feature from `world()` (`@jgengine/core/world/place`): substrate + laws, with all dressing authored in the editor. The remaining members — biomes, voxel grid, plots, tilemap, environment, flat — are the legacy code-declared shapes kept for existing games.
1662
1826
  - `WorldGridCell` (interface): interface WorldGridCell — ⚠ undocumented
1663
1827
  - `WorldGridConfig` (interface): interface WorldGridConfig — Shared by `biomes()`/`voxel()`/`plots()`/`tilemap()` so the shell can render their declared content as instanced boxes without a hand-written renderer.
1664
1828
  - `WorldXZ` (type): type WorldXZ = readonly [number, number] — ⚠ undocumented
@@ -1674,6 +1838,8 @@
1674
1838
  - `applyRotationPolicy` (function): function applyRotationPolicy(degrees: number, policy: PlacementRotationPolicy | undefined): number — Resolve a raw drag/scroll heading through a {@link PlacementRotationPolicy} into the heading a placement should actually commit: `locked` ignores the input for its fixed heading, `snap` quantizes, `free` (or an absent policy) normalizes. Deterministic — the single interpreter preview, editor placement, and runtime spawning share instead of each re-implementing the modes.
1675
1839
  - `applySurfaceDeltaToSnapshot` (function): function applySurfaceDeltaToSnapshot(snapshot: TerraformSnapshot, delta: SurfaceDelta): TerraformSnapshot — Returns a new snapshot with a surface delta's `after` ids applied (copy-on-write).
1676
1840
  - `assignFormationSlots` (function): function assignFormationSlots(members: readonly Vec2[], slots: readonly Vec2[], options: SlotAssignmentOptions = {}): number[] — Match `members` to `slots` by a deterministic greedy nearest assignment: every (member, slot) pair is ranked by squared travel distance (minus a stickiness bonus for a member's previous slot) and assigned in order while both ends are free. Returns `assignment[member] = slot`, or `-1` for members left unmatched when there are fewer slots than members. Ties break by member then slot index, so the result is stable across runs and independent of input ordering — the property replay and lockstep multiplayer rely on. Groups are bounded, so the `O(members·slots·log)` sort is fine; this is not a per-frame whole-world pass.
1841
+ - `bakeMinimapBackground` (function): function bakeMinimapBackground(source: MinimapBakeSource, options: MinimapBakeOptions = {}): { background: string; mapBounds: MinimapBakeBounds } — One-call convenience: rasterize a source and return `{ background, mapBounds }` for a minimap.
1842
+ - `bakeMinimapImage` (function): function bakeMinimapImage(source: MinimapBakeSource, options: MinimapBakeOptions = {}): MinimapBake — Rasterizes a top-down terrain image: height maps onto a low→high color ramp (normalized over the sampled height range), slope darkens the shade, water fills below `waterLevel`, and each zone polygon tints the ground it covers. Deterministic for a fixed source. The bounds are preserved so a player-centered minimap pans the image correctly.
1677
1843
  - `bearingToCardinal` (function): function bearingToCardinal(bearing: number): Cardinal — ⚠ undocumented
1678
1844
  - `beginSurfaceStroke` (function): function beginSurfaceStroke(terrain: Pick<EditableTerrain, "paintRecording">): SurfaceStroke — Opens a paint-stroke recorder over `terrain`; stamp paint edits into it, then read one net delta.
1679
1845
  - `beginTerraformStroke` (function): function beginTerraformStroke(terrain: Pick<EditableTerrain, "applyRecording">): TerraformStroke — Opens a stroke recorder over `terrain`; stamp edits into it, then read one net delta.
@@ -1684,7 +1850,7 @@
1684
1850
  - `boxRegion` (function): function boxRegion(min: Point3, max: Point3): SampleRegion<Point3> — An axis-aligned box `[min..max]` in 3D. Uniform density; draws x, y, z in order.
1685
1851
  - `buildContextMenu` (function): function buildContextMenu(input: BuildContextMenuInput): ContextMenu | null — Assemble a menu from a target's catalog verbs; null when the target lists none.
1686
1852
  - `buildRoadRibbon` (function): function buildRoadRibbon(path: readonly RoadPoint[], width: number, sampleHeight: (x: number, z: number) => number, options: RoadRibbonOptions = {}): RoadRibbon — Triangulate a road centerline into a ground-draped ribbon mesh: the polyline is subdivided, each vertex is offset half a `width` along the local perpendicular, and every vertex sits at `sampleHeight(x, z) + elevation`. Pure geometry — the shell (or any renderer) turns the result into a mesh, and tests can assert on it directly.
1687
- - `building` (function): function building(config: BuildingEnvironmentConfig = {}): BuildingEnvironmentDescriptor — Declares a cluster of procedurally-massed buildings for `environment()` — count, footprint, stories, style.
1853
+ - `building` (function): function building(config: BuildingEnvironmentConfig = {}): BuildingEnvironmentDescriptor — Declares a cluster of procedurally-massed buildings for `environment()` — count, footprint, stories, style. Pass `along` to line road frontage instead of gridding around `position`.
1688
1854
  - `buildingIndex` (function): function buildingIndex(buildings: readonly GeneratedBuilding[]): BuildingIndex — ⚠ undocumented
1689
1855
  - `cappedStacks` (function): function cappedStacks<P>(limit: number, magnitudeOf?: MagnitudeOf<P>): AreaStackPolicy<P> — Keep at most `limit` memberships per `stackKey` (the highest-magnitude ones when `magnitudeOf` is given, else the first-seen). Models capped stacks — e.g. a poison that stacks up to 5 times.
1690
1856
  - `carrySpeedMultiplier` (function): function carrySpeedMultiplier(mass: number, carryCapacity: number, owners: number): number — Movement multiplier (1 = unhindered, →0 = crushed) for a body of `mass` carried by `owners`. Pure — the HUD/movement kit reads it to slow a laden hauler (Lethal Company) and to gate items that need 2+ people (R.E.P.O.).
@@ -1695,6 +1861,7 @@
1695
1861
  - `clampToMinimapEdge` (function): function clampToMinimapEdge(point: MinimapPoint, size: number): { x: number; y: number } — Clamp a projected point to the minimap edge, preserving direction (edge markers).
1696
1862
  - `clearanceZonesFrom` (function): function clearanceZonesFrom(doc: SceneDocumentLike, options: ClearanceOptions = {}): AvoidZone[] — Point-pad clearance **discs** from a document's markers/volumes — the terrain-flatten set (spawns, plots, POIs get a level pad). A marker/volume contributes a disc when it carries `meta.clearance` or its kind is in `kinds`. Paths are *not* included (they render draped, never flattened — see {@link clearanceMasksFrom} for their foliage corridor). Pass `ids`/`kinds` to scope it.
1697
1863
  - `collectAuthoredTriggers` (function): function collectAuthoredTriggers(document: SceneDocumentLike): AuthoredTrigger[] — Collect every authored trigger on a document's markers and volumes. Pure — no runtime state. Action params use the live {@link registerTriggerAction} registry when present.
1864
+ - `combineGravity` (function): function combineGravity(fields: readonly GravityField[]): GravityField — Adds several gravity sources into one field.
1698
1865
  - `command` (function): function command(name: string, input?: unknown): PromptCommand — ⚠ undocumented
1699
1866
  - `compassBearing` (function): function compassBearing(from: WorldXZ, to: WorldXZ): number — Compass bearing (radians, 0 = map north = −Z, increasing clockwise toward +X = east) from one world XZ point to another. Feeds both the minimap direction and the compass strip.
1700
1867
  - `composeRealm` (function): function composeRealm(base: RealmBase, cards: readonly RealmCard[]): ComposedRealm — Assemble a played realm instance at runtime from a deck of modifier cards — the Nightingale "realm card" model. A major card is the biome base; minor cards layer weather, day length, and spawn edits. The result recomposes both the environment (into a sampleable field via `environmentField()`) and the spawn table, and it depends on the weather hooks in this group (#92) to turn its `weather` into gameplay modifiers. Cards apply in array order; sort your deck (majors first) before composing.
@@ -1703,6 +1870,7 @@
1703
1870
  - `contextVerb` (function): function contextVerb(label: string, command: string, args?: Record<string, unknown>): ContextVerb — Builds a {@link ContextVerb} for a right-click menu entry.
1704
1871
  - `contextVerbInput` (function): function contextVerbInput(menu: ContextMenu, verb: ContextVerb): Record<string, unknown> — Command input a chosen verb dispatches: the verb's own args, plus the target id and the world point, so a single handler can walk the actor to the target then perform it.
1705
1872
  - `controlGroupKey` (function): function controlGroupKey(digit: number, options: ControlGroupOptions = {}): string — The stable bookmark key for a control-group `digit` under `options.keyPrefix` — the key a caller passes to `SelectionBookmarks.bind`/`recall` to store a group without going through {@link resolveControlGroupIntent}.
1873
+ - `createAircraftDynamics` (function): function createAircraftDynamics(tuning: AircraftTuning, options: AircraftOptions = {}): AircraftDynamics — Six-degree-of-freedom arcade flight model for fixed-wing, helicopter, and VTOL aircraft.
1706
1874
  - `createAreaEffectField` (function): function createAreaEffectField<P = unknown>(state?: AreaFieldState<P>): AreaEffectField<P> — Build a continuous area-effect field. Drive it with `setSource` (once per live source per tick, so shapes follow their emitters) and `step` (to reconcile membership and drain enter/refresh/leave edges). Optionally restore prior membership by passing a `serialize()` snapshot; re-`setSource` live shapes before the first `step` after restore, since shapes are transient.
1707
1875
  - `createAssetCatalog` (function): function createAssetCatalog<TMeta extends ModelAssetRef = ModelAssetRef>(): AssetCatalog<TMeta> — ⚠ undocumented
1708
1876
  - `createAuthoredTriggerRuntime` (function): function createAuthoredTriggerRuntime(options: { document: SceneDocumentLike; handlers?: TriggerHandlers; /** Invoked for every dispatch after the matching handler (if any). */ onDispatch?: (event: TriggerDispatchEvent) => void; /** Override the collected trigger list (tests / hot-reload). Default: … — Build a runtime that watches a document's authored triggers against moving actors and dispatches to per-action handlers (and optional catch-all). Pure membership math; the game supplies actors each tick from its own player/entity poses.
@@ -1726,6 +1894,7 @@
1726
1894
  - `createLeaderTrail` (function): function createLeaderTrail(config: LeaderTrailConfig): LeaderTrail — A trailing follower formation that chases a leader along its past path — snake/convoy trails.
1727
1895
  - `createLodScheduler` (function): function createLodScheduler(config: LodSchedulerConfig): LodScheduler — ⚠ undocumented
1728
1896
  - `createMarkerSet` (function): function createMarkerSet<TMeta = unknown>(now: () => number = Date.now): MarkerSet<TMeta> — ⚠ undocumented
1897
+ - `createMarkerSource` (function): function createMarkerSource<TEntity, TMarker extends MarkerView = MarkerView>(options: MarkerSourceOptions<TEntity, TMarker>): MarkerSource<TMarker> — Adapt a caller-owned array/store to an observable marker source. Projection is cached between source changes, so React reads do not copy the collection per frame. The caller retains ownership of entities, updates, persistence, and subscription scheduling.
1729
1898
  - `createMountController` (function): function createMountController(): MountController — ⚠ undocumented
1730
1899
  - `createNavGrid` (function): function createNavGrid(config: NavGridConfig): NavGrid — ⚠ undocumented
1731
1900
  - `createOrderQueue` (function): function createOrderQueue<TCtx, TPayload = unknown>(registry: OrderRegistry<TCtx>, options: OrderQueueOptions<TPayload> = {}): OrderQueue<TCtx, TPayload> — Create a per-entity order queue over a shared kind registry. The queue owns the deterministic lifecycle and preemption policy; the kinds own behavior. Nothing here is random or unbounded: id generation is injected, activation is bounded by the pending count, and a single `tick` advances at most the active order plus one activation.
@@ -1747,12 +1916,13 @@
1747
1916
  - `createTerrainSnapshot` (function): function createTerrainSnapshot(config: EditableTerrainConfig): TerraformSnapshot — A fresh, unedited terrain snapshot sized to `bounds`/`cellSize` — the seed for a new sculpt document.
1748
1917
  - `createThreatTable` (function): function createThreatTable(config: ThreatTableConfig = {}): ThreatTable — ⚠ undocumented
1749
1918
  - `createVehicleBody` (function): function createVehicleBody(world: PhysicsWorld, config: VehicleBodyConfig): VehicleBody — ⚠ undocumented
1919
+ - `createVehicleObstacleClamp` (function): function createVehicleObstacleClamp(options: { /** Solids near the car this tick (already filtered to the relevant, solid set). */ obstacles: () => readonly CollisionObstacle[]; /** Vehicle body radius (units). Default {@link DEFAULT_VEHICLE_RADIUS}. */ radius?: number; /** Current tick dt (seconds)… — Build a slide-along move clamp for a kinematic car (#1051). `obstacles` is sampled fresh each tick — the caller hands back the already-filtered set of solids near the car — and `dt` supplies the current tick length so a blocked move's lost displacement converts to a closing speed. `radius` inflates each obstacle footprint by the car's body radius (default {@link DEFAULT_VEHICLE_RADIUS}).
1750
1920
  - `createVehicleSeats` (function): function createVehicleSeats(controller?: MountController): VehicleSeats — Builds a {@link VehicleSeats}, optionally over an existing `MountController` to share its occupancy.
1751
1921
  - `createVisibilityField` (function): function createVisibilityField(config: VisibilityFieldConfig): VisibilityField — Build a per-group gameplay visibility field. First adopters: an RTS/stealth team whose scout observes terrain (which stays remembered after it leaves) while enemy units re-hide once no scout observes their cell, and any authoritative host that must filter hidden entities out of a client's replica.
1752
1922
  - `createVisibilitySystem` (function): function createVisibilitySystem(options: VisibilitySystemOptions): VisibilitySystem — ⚠ undocumented
1753
1923
  - `createVoxelField` (function): function createVoxelField<T extends string = string>(config?: VoxelFieldConfig): VoxelField<T> — ⚠ undocumented
1754
1924
  - `customRegion` (function): function customRegion<P extends SamplePoint>(spec: { dimensions: 2 | 3; sample: (rng: () => number) => P; contains: (point: P) => boolean; isEmpty?: boolean; }): SampleRegion<P> — Wrap a caller-defined sampler and bounds test as a {@link SampleRegion} — the escape hatch for regions the built-ins do not cover (a navmesh cell, a heightfield mask, a spline tube).
1755
- - `dashSegments` (function): function dashSegments(path: readonly RoadPoint[], dashLength = 3, gapLength = 3): readonly (readonly RoadPoint[])[] — Split a centerline into dash sub-polylines for lane markings: `dashLength` of painted line, `gapLength` of asphalt, repeated along the path's arc length. Feed each returned sub-path back through {@link buildRoadRibbon} with a thin width to mesh the dashes.
1925
+ - `dashSegments` (function): function dashSegments(path: readonly RoadPoint[], dashLength = 3, gapLength = 3, exclude: readonly DashExclusion[] = []): readonly (readonly RoadPoint[])[] — Split a centerline into dash sub-polylines for lane markings: `dashLength` of painted line, `gapLength` of asphalt, repeated along the path's arc length. Feed each returned sub-path back through {@link buildRoadRibbon} with a thin width to mesh the dashes. Pass `exclude` circles (junction patches) to interrupt the center line through intersections — any dash whose midpoint lands inside an exclusion is dropped.
1756
1926
  - `defineAttackMoveOrder` (function): function defineAttackMoveOrder<TCtx extends OrderMover & OrderTargeting>(config: EngagementKindConfig = {}): OrderKind<TCtx, AttackMoveOrderPayload> — Attack-move: advance toward a destination but break off to engage any hostile acquired within `aggroRadius`, pursuing it to `attackRange` and writing the engagement intent into `order.state` for the game to act on. Completes on reaching the destination with nothing to engage.
1757
1927
  - `defineHoldOrder` (function): function defineHoldOrder<TCtx extends OrderMover>(config: OrderKindConfig = {}): OrderKind<TCtx, EmptyOrderPayload> — Hold position: stand ground indefinitely (never completes on its own) until preempted or canceled — the "guard here" verb.
1758
1928
  - `defineMoveOrder` (function): function defineMoveOrder<TCtx extends OrderMover>(config: OrderKindConfig & { arriveRadius?: number } = {}): OrderKind<TCtx, MoveOrderPayload> — The plain "go here" verb: step toward a point each tick, complete on arrival, fail if the entity despawns. The completion predicate is arrival within `arriveRadius`.
@@ -1763,17 +1933,20 @@
1763
1933
  - `distance` (function): function distance(a: Vec3, b: Vec3): number — ⚠ undocumented
1764
1934
  - `distance3` (function): function distance3(a: { x: number; y: number; z: number }, b: { x: number; y: number; z: number }): number — ⚠ undocumented
1765
1935
  - `distanceToPolygonEdge` (function): function distanceToPolygonEdge(point: Vec2, polygon: readonly Vec2[]): number — Shortest distance from a point to a polygon's boundary.
1936
+ - `distanceToRoadEdge` (function): function distanceToRoadEdge(roads: readonly RoadEnvironmentDescriptor[], x: number, z: number): number — Signed planar distance from `(x, z)` to the nearest road *surface edge* across every segment of every road (#1051): negative inside the asphalt (magnitude = how far in from the closest edge, so `-width/2` on the centerline), `~0` right at the curb, and positive off the road (the gap to the nearest edge). Point-to-segment distance minus the road's half width, minimised over all segments — the "am I on the road, and by how much" seam driving grip, tyre audio, and off-road penalties.
1766
1937
  - `drapePolyline` (function): function drapePolyline(sampleHeight: HeightSampler, points: readonly GroundPoint[], options: DrapeOptions = {}): number[] — Drapes an XZ polyline onto the surface: subdivides each span to at most `spacing` and lifts every vertex to `sampleHeight + offset`, returning flat `[x, y, z, ...]` world triples. The reusable seam behind surface-following placement guides and grid lines — a straight guide bends to follow terrain.
1767
1938
  - `editableTerrainFromSnapshot` (function): function editableTerrainFromSnapshot(snapshot: TerraformSnapshot, base?: TerrainField): EditableTerrain — Rebuilds a live {@link EditableTerrain} from a snapshot, layered over `base` ground.
1768
1939
  - `effectiveRelation` (function): function effectiveRelation(input: EffectiveRelationInput): FactionRelation — ⚠ undocumented
1940
+ - `encodeBakePng` (function): function encodeBakePng(bake: MinimapBake): Uint8Array — Encodes an RGBA bake to raw PNG bytes (pure; stored DEFLATE, valid for any decoder).
1769
1941
  - `entityMetaOf` (function): function entityMetaOf<T>(entity: SceneEntity<unknown>, isMeta: (value: unknown) => value is T): T | null — Narrow `entity.meta` with a type guard — prefer this over `entity.meta as T` so failed shapes return `null` instead of lying to the type checker.
1770
- - `environment` (function): function environment(config: EnvironmentWorldConfig = {}): EnvironmentWorldFeature — Composes an `environment()` world feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
1942
+ - `environment` (function): function environment(config: EnvironmentWorldConfig = {}): EnvironmentWorldFeature — Composes an `environment()` feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
1771
1943
  - `evaluateQteSequence` (function): function evaluateQteSequence(steps: readonly QteStep[], inputs: readonly QteInputEvent[]): QteOutcome — Evaluate a quick-time-event input sequence against timed hit windows.
1772
1944
  - `evaluateSkillCheck` (function): function evaluateSkillCheck(config: SkillCheckConfig, elapsedSeconds: number): SkillCheckResult — ⚠ undocumented
1773
1945
  - `extractContours` (function): function extractContours(sampleHeight: HeightSampler, options: ContourOptions): ContourLine[] — Traces surface-following contour lines from a height field via marching squares: samples a bounded grid over the region, then for every multiple of `interval` strictly inside the sampled height range emits the iso-line as XZ segments (saddle cells disambiguated by the cell-center average). Because a contour is exact constant elevation, drawing each segment at `y = level` makes it hug the terrain — the readable, scale-bearing overlay a flat ground grid cannot give. Pure math, renderer-agnostic.
1774
1946
  - `extremumStack` (function): function extremumStack<P>(magnitudeOf: MagnitudeOf<P>, weakest = false): AreaStackPolicy<P> — Reduce to the single strongest membership overall (`weakest = false` picks the weakest); ties broken by `sourceId`. Use when only the best or worst overlapping source should apply.
1775
1947
  - `facingYaw` (function): function facingYaw(from: Vec2, to: Vec2): number — Engine yaw (`rotationY`, radians) that faces from `from` toward `to` on the XZ plane, matching the `forward = (sin yaw, cos yaw)` convention. Feed the result as the `facing` of {@link placeFormation} to orient a formation along its travel direction. Returns `0` when the points coincide.
1776
1948
  - `findPath` (function): function findPath(grid: NavGrid, from: NavPoint, to: NavPoint, options: FindPathOptions = {}): NavPoint[] | null — A* over the walkable grid. Returns a polyline of world-space `[x, z]` waypoints from `from` to `to`, or `null` when no route exists. Blocked start/goal snap to the nearest walkable cell so a click on an obstacle still routes to its edge.
1949
+ - `findSchemaPreset` (function): function findSchemaPreset(schema: ParamSchema, id: string): ParamPreset | undefined — Look up a schema preset by id, or undefined — the seam `apply_preset` and games resolve bundles through.
1777
1950
  - `firstImpact` (function): function firstImpact(hits: readonly SceneRaycastHit[]): SceneRaycastHit | null — First impact: nearest hit that blocks, or nearest hit if none block.
1778
1951
  - `flat` (function): function flat(): WorldFeature — Declares an empty flat world — the minimal `WorldFeature` for games with no terrain of their own.
1779
1952
  - `footprintObstacles` (function): function footprintObstacles(grid: FootprintGrid): PlacementObstacle[] — Bridges live reservations into `world/placement`'s `PlacementRules.obstacles` so `validatePlacement`/`createPlacementController` see the grid's committed footprints unchanged.
@@ -1791,6 +1964,7 @@
1791
1964
  - `independentStacks` (function): function independentStacks<P>(): AreaStackPolicy<P> — Every overlapping membership applies independently (no deduplication) — the default for hazards, fields, and lights where two sources genuinely stack.
1792
1965
  - `interestPhase` (function): function interestPhase(seed: string | number): number — A deterministic `[0,1)` cadence phase derived from a stable id, for staggering sibling gates so a batch of agents spawned together does not fire their first active tick on the same frame. Pass the result as the `phase` argument to {@link createInterestGateState}.
1793
1966
  - `isMarquee` (function): function isMarquee(rect: ScreenRect, thresholdPx = 4): boolean — True when the drag is large enough to be a marquee rather than a click.
1967
+ - `isPlaceWorld` (function): function isPlaceWorld(worldFeature: { kind: string } | undefined): worldFeature is PlaceWorldFeature — Type guard for the place-model world feature.
1794
1968
  - `isRegionField` (function): function isRegionField(field: TerrainField): field is RegionField — ⚠ undocumented
1795
1969
  - `isScatterPath` (function): function isScatterPath(path: ScenePathLike): boolean — True when an editor path is a foliage/scatter region.
1796
1970
  - `keybind` (function): function keybind(actionId: string, label?: string): KeybindPromptDisplay — ⚠ undocumented
@@ -1800,8 +1974,9 @@
1800
1974
  - `listTriggerActions` (function): function listTriggerActions(target?: TriggerSourceKind): TriggerActionDefinition[] — Every registered action, optionally filtered by target collection.
1801
1975
  - `mapLayerColor` (function): function mapLayerColor(tone: MapLayerTone | undefined): string — ⚠ undocumented
1802
1976
  - `markerCatalogId` (function): function markerCatalogId(marker: AuthoredObjectMarkerLike): string | null — Catalog id for a marker: first-class `catalogId` field, else `meta.catalogId` migration alias. Returns null when the marker is not an authored catalog prop (spawn, mob, generator, …).
1803
- - `markerKindStyle` (function): function markerKindStyle(kind: string, styles: Record<string, MarkerKindStyle> = DEFAULT_MARKER_KINDS): MarkerKindStyle — ⚠ undocumented
1977
+ - `markerKindStyle` (function): function markerKindStyle(kind: string | undefined, styles: Record<string, MarkerKindStyle> = DEFAULT_MARKER_KINDS): MarkerKindStyle — ⚠ undocumented
1804
1978
  - `migrateTerrainSnapshot` (function): function migrateTerrainSnapshot(snapshot: TerraformSnapshot): TerraformSnapshot — Upgrades a pre-2.0 snapshot in place-safe (copy-on-write) form: derives a {@link TerrainMaterialLayer} stack from the distinct painted surfaces (first-seen order, default params) when none exists. Leaves the lazy `weights` buffer absent — a single-layer terrain stays compact until blended. Idempotent: a snapshot that already carries `layers` is returned unchanged.
1979
+ - `minimapBakeToPngDataUri` (function): function minimapBakeToPngDataUri(bake: MinimapBake): string — Encodes a bake as a `data:image/png;base64,...` URI — the exact string the `Minimap` / `WorldMap` `background` prop takes. Deterministic for a fixed bake.
1805
1980
  - `mtof` (function): function mtof(midi: number): number — Standard equal-temperament MIDI-to-frequency (A4 = 440 Hz at MIDI 69).
1806
1981
  - `normalizeDegrees` (function): function normalizeDegrees(degrees: number): number — Wrap `degrees` into `[0, 360)` — the canonical heading range every policy and conversion here works in. Non-finite input collapses to `0` so bad metadata never leaks a `NaN` heading downstream.
1807
1982
  - `notesInWindow` (function): function notesInWindow(theme: MusicTheme, anchorSec: number, fromSec: number, toSec: number): ScheduledNote[] — Pure lookahead scheduler: every note occurrence of `theme` whose onset falls in the half-open window `(fromSec, toSec]`, given the theme's loop-zero at `anchorSec`. Handles any number of loop wraps, so a director calls it once per tick with a non-overlapping window and never double-schedules a note.
@@ -1829,6 +2004,7 @@
1829
2004
  - `placeFormation` (function): function placeFormation(destination: Vec2, facing: number, count: number, generator: FormationSlotGenerator): Vec2[] — Transform a generator's local slot offsets into world XZ positions around a `destination`, rotated by `facing` (engine yaw). Slot `i` in the returned array is `generator(count)[i]` mapped through the group frame, so it stays aligned with {@link assignFormationSlots}' slot indices. Pure and allocation- light: one array of `count` points, no per-call closures retained.
1830
2005
  - `player` (function): function player(): PlayerBehavior — ⚠ undocumented
1831
2006
  - `plots` (function): function plots(config: PlotsWorldConfig = {}): WorldFeature — Declares a subdivided-plots world — farming, base-building, and other parcel-based layouts.
2007
+ - `pointGravity` (function): function pointGravity(options: PointGravityOptions): GravityField — Radial gravity toward one center, with optional inverse-square falloff for planetary worlds.
1832
2008
  - `pointInPolygon` (function): function pointInPolygon(point: Vec2, polygon: readonly Vec2[]): boolean — Ray-casting point-in-polygon test on the XZ plane.
1833
2009
  - `pointInVolume` (function): function pointInVolume(volume: SceneVolumeLike, point: { x: number; y: number; z: number }): boolean — True when `point` is inside an editor volume (sphere / cylinder / box). Cylinder height defaults to diameter when omitted; sphere ignores y for the common ground-plane case only when the volume radius covers the full vertical span — here y is tested for sphere and box too.
1834
2010
  - `pointSetRegion` (function): function pointSetRegion(points: readonly Vec2[], options: { weights?: readonly number[] } = {}): SampleRegion<Vec2> — A fixed set of candidate points sampled by (optionally weighted) selection — the "spawn point table" region. `contains` is exact membership. Empty when the set is empty.
@@ -1852,7 +2028,8 @@
1852
2028
  - `relativeBearing` (function): function relativeBearing(bearing: number, reference: number): number — Signed offset of `bearing` from `reference`, wrapped into (−π, π].
1853
2029
  - `resolveActivePrompt` (function): function resolveActivePrompt<T extends PositionedPrompt>(playerPosition: PromptPoint, prompts: readonly T[]): T | null — Nearest prompt strictly within its radius wins; a higher-priority prompt in range beats any lower-priority one regardless of distance; equal priority and distance keep the earliest prompt in the list.
1854
2030
  - `resolveAnchorOffset` (function): function resolveAnchorOffset(space?: Pick<AssetSpace, "anchor" | "footprint">): Vec2 — The pivot's offset from the footprint center, in engine meters, implied by {@link AssetSpace.anchor} and {@link AssetSpace.footprint}. `center` yields `[0, 0]`; `corner` yields the min corner; a normalized `{ x, z }` scales by the footprint. Subtract it to seat a footprint centered on a point.
1855
- - `resolveAuthoredObjects` (function): function resolveAuthoredObjects(document: AuthoredObjectsDocumentLike): AuthoredObject[] — Every marker carrying a catalog id, as placeable props — pure, no terrain sample. Parallel to {@link resolveScatter}: games and headless tests read the same list `<AuthoredObjects>` places.
2031
+ - `resolveAuthoredObjects` (function): function resolveAuthoredObjects(document: AuthoredObjectsDocumentLike, options: ResolveAuthoredObjectsOptions = {}): AuthoredObject[] — Every marker carrying a catalog id, as placeable props — pure, no terrain sample. Parallel to {@link resolveScatter}: games and headless tests read the same list `<AuthoredObjects>` places. Entity-spawn kinds (`mob`/`boss`) are skipped by default — they carry a `catalogId` for their entity definition, but are spawned via `authoredEntitySpawns`, not placed as static meshes.
2032
+ - `resolveCityObject` (function): function resolveCityObject(object: SceneKindObject, context?: CityResolveContext): ResolvedCity | null — Synthesize the deterministic city plan for one `city` volume: streets → bridges → parks → zoned frontage lots with massing pieces → furniture, all in the volume's local frame and then rotated/translated into world space. Same volume (id, footprint, meta) over the same terrain always resolves to the identical plan. When `context` provides a ground sampler, lots respect the `maxSlope` cliff rule — hillside and canyon districts keep their steep faces open. When `context.zoneOverrides` carries sibling `cityzone` volumes, lots inside them adopt the override band/mix. Returns null without a usable footprint.
1856
2033
  - `resolveControlGroupIntent` (function): function resolveControlGroupIntent(input: ControlGroupInput, options: ControlGroupOptions = {}): ControlGroupIntent — Resolve a control-group key press into a {@link ControlGroupIntent}: Ctrl+digit binds, a bare digit recalls, and a second recall of the same group within `doubleTapMs` focuses. Pure — the caller applies the intent against the store and its own focus hook, and records the returned recall for the next call.
1857
2034
  - `resolveEmitterGain` (function): function resolveEmitterGain(distance: number, sound: Pick<SoundDef, "gain" | "positional" | "falloff">, busGain: number): number — ⚠ undocumented
1858
2035
  - `resolveFacingRotationY` (function): function resolveFacingRotationY(headingDegrees: number, space?: Pick<AssetSpace, "forwardDegrees">): number — The Three.js Y-rotation that makes a model whose front is authored at `forwardDegrees` visually point `headingDegrees` (engine north = `0`). This is the catalog-owned replacement for per-game corrective yaw: a model authored facing south (`forwardDegrees: 180`) placed toward north resolves to `Math.PI`.
@@ -1860,13 +2037,16 @@
1860
2037
  - `resolveLocalAvoidance` (function): function resolveLocalAvoidance(agents: AvoidanceAgent[], options: LocalAvoidanceOptions = {}): number — Resolve overlaps in `agents` in place and return how many overlapping pairs remained on the final pass (`0` = fully separated). Uses a bounded uniform hash grid sized to the largest agent, so only nearby agents are ever compared. Deterministic: corrections are accumulated then applied per pass, independent of agent order. Pass `weights` to pin or differentially push agents.
1861
2038
  - `resolvePlaceAsset` (function): function resolvePlaceAsset(input: ResolvePlaceAssetInput): PlaceAssetResult — Resolve a place-asset intent into a shared payload (editor + games, one verb).
1862
2039
  - `resolvePlayerMovementTuning` (function): function resolvePlayerMovementTuning(opts: { collision?: VoxelCollisionConfig; movement?: PlayerMovementConfig; physics?: PhysicsConfig; world?: WorldFeature; }): PlayerMovementTuning — Gather a game's collision/movement/physics/world config into a {@link PlayerMovementTuning} — call once per world; both the shell and a host pass the result to {@link stepPlayerMovement}.
2040
+ - `resolvePoleLine` (function): function resolvePoleLine(object: SceneKindObject, params: ParsedParams, context?: SceneKindResolveContext): ResolvedPoleLine — Resolve poles + cables from a document object's points and parsed params. Poles come from the generic `placeAlongPath` sampler; between each consecutive pair, `wireCount` parallel cables are strung with lateral offset and quadratic-Bézier `sag` (deeper on longer spans). Pure data.
1863
2041
  - `resolveScatter` (function): function resolveScatter(doc: SceneDocumentLike, terrain?: ScatterTerrain, options: ResolveScatterOptions = {}): ScatterInstance[] — Every scatter region's placements across a document, grounded on `terrain` when provided. Regions honor clearance masks: their own manual `avoid` discs, plus (when the region's `autoAvoid` is on and `options.autoAvoid !== false`) the document-wide discs + path corridors from {@link clearanceMasksFrom} — so foliage auto-clears spawns, plots, and paths without hand-carving the polygon.
1864
2042
  - `resolveScatterRegion` (function): function resolveScatterRegion(region: ScatterRegion, terrain?: ScatterTerrain, avoid?: AvoidMasks): ScatterInstance[] — Deterministic placements for one scatter region: scatter its polygon footprint at `density` items/m² (respecting `minSpacing`), clip to the polygon, thin near the edge, drop placements outside the slope/height mask, and derive item/scale/yaw from the region id + seed — so the same saved region always grows the same field. Grounds each instance on `terrain` when provided.
1865
2043
  - `resolveStructureBuildings` (function): function resolveStructureBuildings(descriptor: BuildingEnvironmentDescriptor): GeneratedBuilding[] — ⚠ undocumented
1866
2044
  - `resolveWeather` (function): function resolveWeather<TTable extends WeatherModifierTable>(state: WeatherState, table: TTable): ResolvedWeather — ⚠ undocumented
2045
+ - `resolveWorldPhysics` (function): function resolveWorldPhysics(worldFeature: { kind: string; physics?: PhysicsConfig } | undefined, base: PhysicsConfig | undefined): PhysicsConfig | undefined — Resolves the physics laws in effect for the active world: a place world's own `physics` wins field-by-field over the game-level default. Non-place worlds (and games with no world) keep the game-level config unchanged.
1867
2046
  - `revertDeltaFromSnapshot` (function): function revertDeltaFromSnapshot(snapshot: TerraformSnapshot, delta: TerraformDelta): TerraformSnapshot — Returns a new snapshot with a delta's `before` offsets restored (copy-on-write undo).
1868
2047
  - `revertSurfaceDeltaFromSnapshot` (function): function revertSurfaceDeltaFromSnapshot(snapshot: TerraformSnapshot, delta: SurfaceDelta): TerraformSnapshot — Returns a new snapshot with a surface delta's `before` ids restored (copy-on-write undo).
1869
2048
  - `road` (function): function road(config: RoadEnvironmentConfig): RoadEnvironmentDescriptor — Declare a road ribbon for an `environment()` world; the shell drapes and renders it over the terrain.
2049
+ - `roadSurfaceSampler` (function): function roadSurfaceSampler(roads: readonly RoadEnvironmentDescriptor[], options: RoadSurfaceOptions = {}): (x: number, z: number) => number — A `surfaceFriction`-compatible sampler (the `(x, z) => grip` hook a kinematic car reads each tick) that turns road geometry into grip (#1051): full `onRoad` grip on the asphalt, a monotonic linear ramp down across a `shoulder`-wide band at the curb, and flat `offRoad` grip beyond it — so a car that clips onto the grass loses bite progressively instead of snapping. Closes over {@link distanceToRoadEdge}, so the returned sampler is itself allocation-free per call.
1870
2050
  - `rotatedFootprint` (function): function rotatedFootprint(footprint: Footprint, headingDegrees: number): Footprint — The axis-aligned footprint extent after rotating a rectangular {@link Footprint} by `headingDegrees` — footprint-aware placement: a 90-degree turn swaps width/depth, and arbitrary headings grow the bounding box so overlap and snap checks see the space the rotated asset truly occupies.
1871
2051
  - `rotationYToHeading` (function): function rotationYToHeading(rotationY: number): number — Inverse of {@link headingToRotationY}: recover the `[0, 360)` compass heading from a Three.js Y-rotation. Lets a gizmo or inspector present radians as the degrees authors edit.
1872
2052
  - `sagCurve` (function): function sagCurve(a: Vec3, b: Vec3, sag: number, segments: number): Vec3[] — Quadratic-Bézier sag between two anchors: the control point is pulled straight down so the mid-span lowest point droops by exactly `sag` meters below the chord. Cheap and stable; the go-to for cables where exact catenary physics don't matter. Returns `segments + 1` points.
@@ -1881,6 +2061,7 @@
1881
2061
  - `scatterRegionEstimate` (function): function scatterRegionEstimate(path: ScenePathLike): { area: number; count: number } — Estimated placement count for a scatter path — density × polygon area, for a live UI readout.
1882
2062
  - `scatterRegionFromPath` (function): function scatterRegionFromPath(path: ScenePathLike): ScatterRegion | null — Builds a resolvable {@link ScatterRegion} from a scatter path (XZ polygon + rules), or null.
1883
2063
  - `screenRect` (function): function screenRect(ax: number, ay: number, bx: number, by: number): ScreenRect — Normalize two drag corners (in any order) into a rectangle.
2064
+ - `seedForPlace` (function): function seedForPlace(worldId: string, runSeed = ""): string — The engine-side seed derivation for a place: a stable string from the world `id` plus the save/run seed. Generators and scatter receive this — never a `seed` field in the world definition — so a save replays its world deterministically and a fresh run can vary by `runSeed` alone.
1884
2065
  - `selectAutoTarget` (function): function selectAutoTarget(policy: AutoTargetPolicy, fromId: string, deps: AutoTargetDeps): string | null — ⚠ undocumented
1885
2066
  - `selectWithinRect` (function): function selectWithinRect(candidates: readonly ScreenPoint[], rect: ScreenRect): string[] — Ids of the projected candidates whose screen point falls inside the marquee.
1886
2067
  - `shellRegion` (function): function shellRegion(center: Point3, innerRadius: number, outerRadius: number, options: { distribution?: VolumeDistribution } = {}): SampleRegion<Point3> — A spherical shell between `innerRadius` and `outerRadius`. `"volume"` fills the shell with even density; `"radial"` spreads uniformly in radius. Direction first, then radius.
@@ -1917,6 +2098,7 @@
1917
2098
  - `toEditorMarker` (function): function toEditorMarker(result: PlaceAssetResult): { id: string; kind: string; position: PlaceAssetVec3; rotationY: number; label: string; color: string; meta: Record<string, unknown>; } — Scene-document form: feed editor `addMarker` / `place_asset` path.
1918
2099
  - `toEngineUnits` (function): function toEngineUnits(sourceValue: number, space?: Pick<AssetSpace, "unitScale">): number — Convert a source-space length to engine meters through the asset's {@link AssetSpace.unitScale} — the data-owned replacement for per-game scale constants (a native ~4-unit kit tile down to a 1-unit grid).
1919
2100
  - `toStructureInput` (function): function toStructureInput(result: PlaceAssetResult): AddStructureInput — Game-state form: feed {@link createPlacedStructureStore}.add.
2101
+ - `uniformGravity` (function): function uniformGravity(vector: GravityVector = [0, -9.81, 0]): GravityField — Constant vector gravity for ordinary worlds, space stations, and sideways-gravity levels.
1920
2102
  - `uniqueByStackKey` (function): function uniqueByStackKey<P>(magnitudeOf?: MagnitudeOf<P>): AreaStackPolicy<P> — Keep at most one membership per `stackKey`. With `magnitudeOf` the strongest per key wins (ties broken by `sourceId` for determinism); without it the first-seen per key wins. Use for unique-by-key buffs where reapplying the same aura should not stack.
1921
2103
  - `unprojectFromMinimap` (function): function unprojectFromMinimap(point: { x: number; y: number }, view: MinimapView): WorldXZ — Invert `projectToMinimap` (#285.6): minimap pixel → world XZ, rotate-aware — click-to-pin, tap-to-ping, drag-to-set-waypoint map interactions.
1922
2104
  - `validateAssetSpace` (function): function validateAssetSpace(raw: unknown): AssetSpaceIssue[] — Report contradictory or malformed asset-space metadata so catalog generation can reject it before it reaches a tool: non-finite headings, non-positive scales/sizes, inverted bounds, unknown anchors, and ill-formed rotation policies (a `snap` with a non-positive increment, an unknown `mode`). An empty array means valid. Validation lives here so tools consume resolved metadata instead of reinterpreting.
@@ -1930,19 +2112,40 @@
1930
2112
  - `weightedRegion` (function): function weightedRegion<P extends SamplePoint>(entries: readonly WeightedRegionEntry<P>[]): SampleRegion<P> — A composite that first picks one member by weight, then delegates to its sampler — the "weighted subregions" distribution policy. `contains` is true when any member contains the point.
1931
2113
  - `windField` (function): function windField(config: WindFieldConfig = {}): WindField — ⚠ undocumented
1932
2114
  - `withPathProfiles` (function): function withPathProfiles(base: (x: number, z: number) => number, profiles: readonly TerrainPathProfile[]): (x: number, z: number) => number — Wraps a height sampler so each authored `TerrainPathProfile` reshapes it. Profiles apply in list order (later profiles compose over earlier ones, so an intersection's last profile wins its core); each reads the running height as its surrounding ground and the original `base` for `sample` centerline heights. The returned sampler is pure and deterministic. Degenerate profiles (fewer than two points, non-positive width or length) are skipped; with no usable profile the original `base` is returned unchanged.
2115
+ - `world` (function): function world(config: PlaceConfig): PlaceWorldFeature — Declares the place a game is played in: substrate (`ground`) + laws (`physics`, `ground.surface`). The thin default start — `flat` with `Infinity` axes and default physics, `board` for 2D — is a complete world; dressing it (sky, foliage, props, sculpt) is editor-authored scene content. Multiple worlds per game are first-class: declare one `world()` per place, each with its own id, ground, and physics. Games that are not a spatial place (pure UI/rules) omit `world` entirely.
1933
2116
  - `worldSockets` (function): function worldSockets(def: ConnectorPieceDef, piece: PlacedPiece): WorldSocket[] — ⚠ undocumented
1934
2117
 
2118
+ ## @jgengine/core/world/authoredEntities
2119
+
2120
+ - `AuthoredEntityDocumentLike` (interface): interface AuthoredEntityDocumentLike — The minimal document shape {@link authoredEntitySpawns} walks; any `EditorDocument` satisfies it.
2121
+ - `AuthoredEntityMarkerLike` (type): type AuthoredEntityMarkerLike = AuthoredObjectMarkerLike — The minimal marker shape entity spawns read; any `EditorMarker` satisfies it.
2122
+ - `AuthoredEntitySpawn` (interface): interface AuthoredEntitySpawn — One resolved entity to spawn from the authored scene — its marker id, catalog id, and pose.
2123
+ - `ENTITY_MARKER_KINDS` (const): const ENTITY_MARKER_KINDS: readonly string[] — Marker kinds that are spawnable entities (materialized by `authoredEntitySpawns`), not static catalog props. {@link resolveAuthoredObjects} skips them by default so a placed `mob`/`boss` is spawned once as an entity and never also placed as a static mesh.
2124
+ - `authoredEntitySpawns` (function): function authoredEntitySpawns(document: AuthoredEntityDocumentLike, kinds: readonly string[] = ENTITY_MARKER_KINDS): AuthoredEntitySpawn[] — Every authored entity marker (`mob`/`boss` by default) that carries a `catalogId`, as a spawn plan the runtime feeds to `ctx.scene.entity.spawn(catalogId, { id, position })`. Reads the same document the editor authors, so placing a mob and setting its catalog id in the editor is all it takes to spawn it — no coordinates or spawn tables copied into game code. Markers without a catalog id are skipped (they are placement-only, e.g. a boss arena marker a game handles specially).
2125
+
1935
2126
  ## @jgengine/core/world/authoredObjects
1936
2127
 
1937
2128
  - `AuthoredObject` (interface): interface AuthoredObject — One authored catalog prop resolved from an editor marker — grounded at `x`/`z` with yaw, ready for `ctx.scene.object.place` or {@link placeAuthoredObjects}.
1938
2129
  - `AuthoredObjectMarkerLike` (interface): interface AuthoredObjectMarkerLike extends SceneMarkerLike — Minimal marker shape {@link resolveAuthoredObjects} reads; any `EditorMarker` satisfies it.
1939
2130
  - `AuthoredObjectPlaceTarget` (interface): interface AuthoredObjectPlaceTarget — Structural place target — any `ObjectStore` satisfies it.
1940
2131
  - `AuthoredObjectsDocumentLike` (interface): interface AuthoredObjectsDocumentLike — Minimal document shape {@link resolveAuthoredObjects} walks; any `EditorDocument` satisfies it.
2132
+ - `ENTITY_MARKER_KINDS` (const): const ENTITY_MARKER_KINDS: readonly string[] — Marker kinds that are spawnable entities (materialized by `authoredEntitySpawns`), not static catalog props. {@link resolveAuthoredObjects} skips them by default so a placed `mob`/`boss` is spawned once as an entity and never also placed as a static mesh.
1941
2133
  - `PlaceAuthoredObjectsOptions` (interface): interface PlaceAuthoredObjectsOptions — Options for {@link placeAuthoredObjects}.
2134
+ - `ResolveAuthoredObjectsOptions` (interface): interface ResolveAuthoredObjectsOptions — Options for {@link resolveAuthoredObjects}.
1942
2135
  - `markerCatalogId` (function): function markerCatalogId(marker: AuthoredObjectMarkerLike): string | null — Catalog id for a marker: first-class `catalogId` field, else `meta.catalogId` migration alias. Returns null when the marker is not an authored catalog prop (spawn, mob, generator, …).
1943
2136
  - `placeAuthoredObjects` (function): function placeAuthoredObjects(store: AuthoredObjectPlaceTarget, objects: readonly AuthoredObject[], sampleHeight: (x: number, z: number) => number, options: PlaceAuthoredObjectsOptions = {}): string[] — Places resolved authored objects into an object store, grounding each on `sampleHeight(x,z)` plus per-object and options vertical offsets. Returns the instance ids that were placed (or kept).
1944
2137
  - `placeAuthoredObjectsFromDocument` (function): function placeAuthoredObjectsFromDocument(store: AuthoredObjectPlaceTarget, document: AuthoredObjectsDocumentLike, sampleHeight: (x: number, z: number) => number, options: PlaceAuthoredObjectsOptions = {}): string[] — Convenience: resolve a document then place every authored catalog prop.
1945
- - `resolveAuthoredObjects` (function): function resolveAuthoredObjects(document: AuthoredObjectsDocumentLike): AuthoredObject[] — Every marker carrying a catalog id, as placeable props — pure, no terrain sample. Parallel to {@link resolveScatter}: games and headless tests read the same list `<AuthoredObjects>` places.
2138
+ - `resolveAuthoredObjects` (function): function resolveAuthoredObjects(document: AuthoredObjectsDocumentLike, options: ResolveAuthoredObjectsOptions = {}): AuthoredObject[] — Every marker carrying a catalog id, as placeable props — pure, no terrain sample. Parallel to {@link resolveScatter}: games and headless tests read the same list `<AuthoredObjects>` places. Entity-spawn kinds (`mob`/`boss`) are skipped by default — they carry a `catalogId` for their entity definition, but are spawned via `authoredEntitySpawns`, not placed as static meshes.
2139
+
2140
+ ## @jgengine/core/world/authoredSpawn
2141
+
2142
+ - `AuthoredSpawnDocumentLike` (interface): interface AuthoredSpawnDocumentLike — Minimal document shape spawn queries walk; any `EditorDocument` satisfies it.
2143
+ - `AuthoredSpawnMarkerLike` (interface): interface AuthoredSpawnMarkerLike extends SceneMarkerLike — Minimal marker shape spawn queries read; any `EditorMarker` satisfies it.
2144
+ - `AuthoredSpawnOptions` (interface): interface AuthoredSpawnOptions — Options for {@link authoredSpawnPosition}: pick a specific marker id or a non-default kind.
2145
+ - `PLAYER_SPAWN_KIND` (const): const PLAYER_SPAWN_KIND: "player_spawn" — Marker kind {@link authoredSpawnPosition} resolves by default.
2146
+ - `authoredSpawnPosition` (function): function authoredSpawnPosition(document: AuthoredSpawnDocumentLike, options: AuthoredSpawnOptions = {}): [number, number, number] | null — Position of the authored spawn marker as a spawn-ready `[x, y, z]` tuple, or null when the document has none. Reads the first `player_spawn` marker by default, so dragging the marker in the editor moves where players spawn — no coordinates copied into game code.
2147
+ - `authoredSpawnRotation` (function): function authoredSpawnRotation(document: AuthoredSpawnDocumentLike, options: AuthoredSpawnOptions = {}): number — Facing (yaw radians) of the authored spawn marker, or 0 when the document has none — pair with {@link authoredSpawnPosition} to spawn players where and how the editor placed them.
2148
+ - `markersOfKind` (function): function markersOfKind<TMarker extends AuthoredSpawnMarkerLike>(document: { markers: readonly TMarker[] }, kind: string): TMarker[] — Every marker of `kind`, in document order — the generic query behind gameplay that references authored markers by kind instead of copying coordinates into code.
1946
2149
 
1947
2150
  ## @jgengine/core/world/buildPermissions
1948
2151
 
@@ -1957,6 +2160,26 @@
1957
2160
  - `createContributionPool` (function): function createContributionPool(goal: ContributionGoal): ContributionPool — ⚠ undocumented
1958
2161
  - `createPlotPermissions` (function): function createPlotPermissions(config: PlotPermissionConfig): PlotPermissions — ⚠ undocumented
1959
2162
 
2163
+ ## @jgengine/core/world/buildSockets
2164
+
2165
+ - `BuildCell` (interface): interface BuildCell — One integer grid cell — structurally the `GridCell` of `world/footprintGrid` (no import needed).
2166
+ - `BuildFootprint` (interface): interface BuildFootprint — A rectangular footprint (world units) a piece occupies on the build grid — the occupancy bridge.
2167
+ - `BuildPieceDef` (interface): interface BuildPieceDef — A registered piece type: its named sockets and, optionally, the footprint it claims when placed.
2168
+ - `BuildSocketCatalog` (interface): interface BuildSocketCatalog — Handle returned by {@link createBuildSocketCatalog}.
2169
+ - `BuildSocketCatalogConfig` (interface): interface BuildSocketCatalogConfig — Serializable catalog config; also the shape returned by {@link BuildSocketCatalog.toJSON}.
2170
+ - `ConnectionRule` (interface): interface ConnectionRule — Declares that two socket kinds may snap together; `mutual` (default `true`) also allows `b`→`a`.
2171
+ - `ModelSocketLike` (interface): interface ModelSocketLike — A `{ name, offset }` attach point — structurally the `ModelSocket` of `scene/modelSockets`.
2172
+ - `PieceTransform` (interface): interface PieceTransform — World transform of a placed piece: position plus a yaw about +Y.
2173
+ - `PlacedPiece` (interface): interface PlacedPiece — An already-placed piece the resolver snaps candidates against.
2174
+ - `PlacedSocket` (interface): interface PlacedSocket — A piece's socket resolved into world space.
2175
+ - `ResolveSnapsOptions` (interface): interface ResolveSnapsOptions — Options for {@link BuildSocketCatalog.resolveSnaps}.
2176
+ - `SnapCandidate` (interface): interface SnapCandidate — A resolved snap: which sockets mate and the world transform that lands the candidate onto the target.
2177
+ - `SocketDef` (interface): interface SocketDef — One named socket on a piece: where it sits and which horizontal direction it faces (yaw about Y).
2178
+ - `SocketVec3` (type): type SocketVec3 = readonly [number, number, number] — Data-driven modular build-piece snap system: a catalog of piece types, each declaring named sockets (local position + outward facing + a generic "kind"), plus a connection-rule table saying which socket kinds may mate. Given a placed piece and a candidate type it resolves every valid snap — the world transform that lands the candidate's socket exactly on the placed piece's socket, facing back into it. Genre-agnostic: foundation/wall/ceiling/pillar/edge snapping falls out of the catalog data, with no game-specific piece names baked in. Pure and serializable; composes with `world/footprintGrid` occupancy (via an injected `isFree` predicate — never imported) and with `scene/modelSockets` named attach points (via {@link pieceSocketsFromModel}).
2179
+ - `createBuildSocketCatalog` (function): function createBuildSocketCatalog(config: BuildSocketCatalogConfig): BuildSocketCatalog — Build a modular snap catalog from piece definitions and a connection-rule table. Resolves the set of valid snap transforms when hovering a candidate piece near a placed one: for every compatible socket pair it computes the world transform that seats the candidate's socket onto the placed socket, oriented to face back into it. Deterministic ordering (nearest a cursor when given, else declaration order) and an optional occupancy predicate keep it drop-in for a build-mode controller.
2180
+ - `footprintCells` (function): function footprintCells(position: SocketVec3, footprint: BuildFootprint, yaw = 0, cellSize = 1): BuildCell[] — The grid cells a piece `footprint` centered on `position` (world units) covers, honoring `yaw` (snapped to the nearest quarter turn). Mirrors `world/footprintGrid`'s `cellsFor` so a game can feed the result straight into `grid.isFree`/`grid.reserve` after committing a resolved snap — without this module importing the grid.
2181
+ - `pieceSocketsFromModel` (function): function pieceSocketsFromModel(sockets: readonly ModelSocketLike[], kindOf: (name: string) => string, yawOf?: (name: string) => number): SocketDef[] — Turn a model's named attach points (from `scene/modelSockets`' `readNamedSockets`) into {@link SocketDef}s, classifying each into a connection `kind` via `kindOf` and, optionally, an outward `yaw` via `yawOf`. Lets an artist author snap sockets as empties in a GLB instead of by hand in the catalog. Pure and structural — no three.js or scene import.
2182
+
1960
2183
  ## @jgengine/core/world/buildingGenerator
1961
2184
 
1962
2185
  - `BUILDING_GENERATOR_ID` (const): const BUILDING_GENERATOR_ID: "building" — The generator id a catalog entry / placed marker references.
@@ -1968,6 +2191,14 @@
1968
2191
  - `BuildingIndex` (interface): interface BuildingIndex — ⚠ undocumented
1969
2192
  - `buildingIndex` (function): function buildingIndex(buildings: readonly GeneratedBuilding[]): BuildingIndex — ⚠ undocumented
1970
2193
 
2194
+ ## @jgengine/core/world/buildingLots
2195
+
2196
+ - `BuildingLotOptions` (interface): interface BuildingLotOptions — Options for {@link deriveBuildingLots}.
2197
+ - `LotArea` (interface): interface LotArea — Rectangular clip region lots must fall within (world center + half-extents).
2198
+ - `PlacedBuildingLot` (interface): interface PlacedBuildingLot — One placed building lot: where a building stands and how it is turned to face its road.
2199
+ - `RoadFrontage` (interface): interface RoadFrontage — One road the frontage placer lines with buildings: a centerline polyline and its full width.
2200
+ - `deriveBuildingLots` (function): function deriveBuildingLots(options: BuildingLotOptions): PlacedBuildingLot[] — Derive street-aligned building lots from road frontage. Lots are stepped along each road at `footprint.w + spacing`, offset to each side by `width / 2 + setback + footprint.d / 2`, and turned to face the road. Cross-road overlaps are rejected by a bounded nearest-neighbour test, so two roads meeting at a corner don't stack buildings. Deterministic: identical inputs (including seed) always yield the identical list.
2201
+
1971
2202
  ## @jgengine/core/world/buildings
1972
2203
 
1973
2204
  - `BUILDING_STYLE_PALETTES` (const): const BUILDING_STYLE_PALETTES: Record<BuildingStyle, BuildingPalette> — ⚠ undocumented
@@ -2019,6 +2250,99 @@
2019
2250
  - `CellStateGridConfig` (interface): interface CellStateGridConfig<TState extends string> — ⚠ undocumented
2020
2251
  - `createCellStateGrid` (function): function createCellStateGrid<TState extends string>(config: CellStateGridConfig<TState>): CellStateGrid<TState> — ⚠ undocumented
2021
2252
 
2253
+ ## @jgengine/core/world/cityBlocks
2254
+
2255
+ - `BlockRings` (interface): interface BlockRings — A block's derived rings plus the sidewalk band (outer = curb line, inner = land line).
2256
+ - `CityBlockKind` (type): type CityBlockKind = "buildable" | "park" | "plaza" | "field" | "buffer" — How a block (a face of the road graph) is used.
2257
+ - `CityBlockLocal` (interface): interface CityBlockLocal — One closed block: a face of the road network, inset to its curb and land boundaries.
2258
+ - `CityParcelFrontage` (interface): interface CityParcelFrontage — One street-frontage reference of a parcel.
2259
+ - `CityParcelKind` (type): type CityParcelKind = "built" | "vacant" | "yard" — How a parcel is used after occupancy/fitting rolls.
2260
+ - `CityParcelLocal` (interface): interface CityParcelLocal — One polygonal parcel subdivided out of a block's street frontage.
2261
+ - `FabricParams` (interface): interface FabricParams — Everything block extraction needs from the district rules.
2262
+ - `FabricStreet` (interface): interface FabricStreet — Minimal street shape the fabric needs (matches cityKind's LocalStreet).
2263
+ - `GraphFace` (interface): interface GraphFace — One extracted face: closed centerline polygon + the street index along each polygon edge.
2264
+ - `ParcelCut` (interface): interface ParcelCut — Inputs for one parcel strip cut from a block ring.
2265
+ - `RingWalker` (class): class RingWalker — Arc-length station lookup along a closed ring.
2266
+ - `buildablePolygon` (function): function buildablePolygon(parcel: readonly Vec2[], frontA: Vec2, frontB: Vec2, frontSetback: number, sideGap: number, rearMargin: number, depth: number): Vec2[] — Buildable polygon for a parcel: the parcel clipped by the front setback (a half-plane pushed in from the frontage chord), side gaps along both cut lines, and a rear margin. Works on any parcel polygon — no vertex correspondence needed.
2267
+ - `carveCorridors` (function): function carveCorridors(poly: Vec2[], keep: Vec2, corridors: readonly { pts: readonly Vec2[]; width: number }[], margin: number): Vec2[] — Carve dead-end road corridors (cul-de-sac lanes pruned from the face graph) out of a polygon: for every corridor segment crossing it, keep the polygon piece on the side where `keep` lies.
2268
+ - `conformPolygonToRing` (function): function conformPolygonToRing(poly: readonly Vec2[], ring: readonly Vec2[]): Vec2[] — Conform a polygon to a containing ring: sample every edge (a straight edge can bulge across a concave notch even when its endpoints hug the boundary), then pull each escaping point to its nearest boundary point. Callers re-run this after any operation that adds mid-edge vertices.
2269
+ - `cutParcel` (function): function cutParcel(walker: RingWalker, blockRing: readonly Vec2[], cut: ParcelCut): Vec2[] | null — Cut one polygonal parcel out of a block land ring: the frontage arc between two stations, extruded inward along the station normals, clipped back to the block. Returns null when the strip collapses (over-tight corner, sliver arc).
2270
+ - `extractBlocks` (function): function extractBlocks(streets: readonly FabricStreet[], hx: number, hz: number, params: FabricParams): { blocks: BlockRings[]; deadEnds: { pts: Vec2[]; width: number }[] } — Extract closed blocks from the street network: planar faces of the graph, each inset to its curb ring (pavement edge) and land ring (behind the sidewalk band). Faces that collapse under the inset come back with an empty `land` and are the caller's slivers/buffers.
2271
+ - `isSliverBlock` (function): function isSliverBlock(land: readonly Vec2[], minArea: number, minWidth: number): boolean — Deterministic sliver verdict shared by classification and tests.
2272
+ - `pointsInPolygon` (function): function pointsInPolygon(ring: readonly Vec2[], count: number, rng: () => number, margin = 1.5): Vec2[] — Sample deterministic points inside a polygon by seeded rejection over its bounds.
2273
+ - `sidewalkWidthFor` (function): function sidewalkWidthFor(level: FabricStreet["level"], base: number): number — Sidewalk band width by street hierarchy (base = the district's street-level width).
2274
+
2275
+ ## @jgengine/core/world/cityContent
2276
+
2277
+ - `CITY_LOT_CLASSES` (const): const CITY_LOT_CLASSES: readonly CityLotClass[] — All classes, for schema hints and validation.
2278
+ - `CITY_TREE_SPECIES` (const): const CITY_TREE_SPECIES: readonly CityTreeSpecies[] — All species, for schema hints and validation.
2279
+ - `CityLotClass` (type): type CityLotClass = | "tower" | "slab" | "shop" | "rowhouse" | "house" | "mansion" | "farmhouse" | "barn" | "silo" — A building class a zone mix can weight — drives lot size, floors, setback, and massing.
2280
+ - `CityLotPiece` (interface): interface CityLotPiece — One massing piece in LOT-LOCAL space: x along frontage width, z into the block, y up from grade.
2281
+ - `CityPieceRole` (type): type CityPieceRole = "wall" | "roof" | "trim" | "accent" — Palette role a piece colors from (wall/roof/trim/accent map onto the district's style palette).
2282
+ - `CityPieceShape` (type): type CityPieceShape = "box" | "gable" | "cylinder" | "dome" — Primitive shapes massing pieces instance — the renderer keeps one InstancedMesh per shape.
2283
+ - `CityTreeSpecies` (type): type CityTreeSpecies = "broadleaf" | "conifer" | "palm" | "cypress" — Tree species a district's tree mix can weight — the renderer keeps one canopy mesh per species.
2284
+ - `CityZoneBand` (type): type CityZoneBand = "core" | "mid" | "edge" — Zone band a lot falls in: dense core, middle ring, or the district edge.
2285
+ - `CityZoneProfile` (type): type CityZoneProfile = "core-out" | "inverted" | "uniform" — How the radial zone metric maps to bands.
2286
+
2287
+ ## @jgengine/core/world/cityGenerator
2288
+
2289
+ - `CityGeneratorOptions` (interface): interface CityGeneratorOptions — Options for {@link generateCity}: a seed, street-dial overrides, and lot pass-through options.
2290
+ - `GeneratedCity` (interface): interface GeneratedCity — A generated city: the street network and the building lots lining its frontage.
2291
+ - `generateCity` (function): function generateCity(options: CityGeneratorOptions, hx: number, hz: number): GeneratedCity — Grow a street network inside the `hx`/`hz` half-extents and line its frontage with building lots. Deterministic: identical options ⇒ identical city.
2292
+
2293
+ ## @jgengine/core/world/cityGeometry
2294
+
2295
+ - `Vec2` (type): type Vec2 = readonly [number, number] — Deterministic 2D polygon math for the `city` studio's block/parcel pipeline: signed areas, point-in-polygon, half-plane clipping, per-edge inward insets (the curb → sidewalk → land and parcel → buildable transforms), simple-loop recovery after aggressive insets, and rotated-rect fitting inside arbitrary polygons. Pure functions over `[x, z]` tuples — no allocation-heavy classes, no rendering, no randomness — so every consumer from the resolver to the tests shares one geometric truth.
2296
+ - `clipHalfPlane` (function): function clipHalfPlane(ring: readonly Vec2[], normal: Vec2, limit: number): Vec2[] — Clip a polygon to the half-plane `dot(p, normal) <= limit` (Sutherland–Hodgman step). Returns the surviving ring, possibly empty. The subject may be concave; the output of a single half-plane clip of a simple ring is always a valid (possibly pinched) ring.
2297
+ - `dedupeRing` (function): function dedupeRing(ring: readonly Vec2[], epsilon = 1e-6): Vec2[] — Remove consecutive (near-)duplicate vertices; returns [] when fewer than 3 survive.
2298
+ - `distanceToRing` (function): function distanceToRing(ring: readonly Vec2[], x: number, z: number): number — Distance from a point to the nearest boundary segment of a ring.
2299
+ - `ensureCcw` (function): function ensureCcw(ring: readonly Vec2[]): Vec2[] — Ensure counter-clockwise winding (positive signed area) without mutating the input.
2300
+ - `extractSimpleLoop` (function): function extractSimpleLoop(ring: readonly Vec2[], maxPasses = 6): Vec2[] — Recover the dominant simple loop from a lightly self-intersecting ring: whenever two edges cross, the smaller of the two loops the crossing pinches off is dropped. Bounded passes; rings that stay tangled after that return []. This is the cleanup net under aggressive insets — a concave block inset past a neck pinches into a bow-tie, and the bigger lobe is the block.
2301
+ - `fitRectInPolygon` (function): function fitRectInPolygon(ring: readonly Vec2[], cx: number, cz: number, maxW: number, maxD: number, rotationY: number, minScale = 0.55): { w: number; d: number; cx: number; cz: number } | null — Fit the largest rect (up to `maxW`×`maxD`, oriented to `rotationY`, centered near `[cx, cz]`) inside a polygon by bounded bisection on a single scale factor. Deterministic; returns null when even `minScale` of the request does not fit after nudging the center inward.
2302
+ - `insetRing` (function): function insetRing(ring: readonly Vec2[], edgeDistances: readonly number[]): Vec2[] — Inset a CCW ring inward with a PER-EDGE distance (edge i runs vertex i → i+1). True corners take the intersection of the two adjacent offset lines (so a street corner lands exactly where the two curb lines meet, even with different street widths); near-collinear vertices — polyline samples along a curve — fall back to the averaged-normal offset, which is exact in the limit. Returns [] when the inset collapses (sliver) or stays tangled after loop recovery.
2303
+ - `insetRingUniform` (function): function insetRingUniform(ring: readonly Vec2[], distance: number): Vec2[] — Uniform-distance convenience over {@link insetRing}.
2304
+ - `pointInPolygon` (function): function pointInPolygon(ring: readonly Vec2[], x: number, z: number): boolean — Even-odd point-in-polygon test.
2305
+ - `polygonArea` (function): function polygonArea(ring: readonly Vec2[]): number — Absolute polygon area.
2306
+ - `polygonCentroid` (function): function polygonCentroid(ring: readonly Vec2[]): Vec2 — Area centroid of a simple polygon (falls back to the vertex mean for degenerate rings).
2307
+ - `polygonMeanWidth` (function): function polygonMeanWidth(ring: readonly Vec2[]): number — Mean "width" proxy for sliver detection: the diameter of the largest inscribed strip is approximated by 2·area / perimeter (exact for long rectangles, conservative elsewhere).
2308
+ - `polygonPerimeter` (function): function polygonPerimeter(ring: readonly Vec2[]): number — Ring perimeter length.
2309
+ - `polygonSignedArea` (function): function polygonSignedArea(ring: readonly Vec2[]): number — Signed area of a polygon ring (positive = counter-clockwise in XZ).
2310
+ - `polygonsOverlap` (function): function polygonsOverlap(a: readonly Vec2[], b: readonly Vec2[], shrink = 0.05): boolean — Conservative polygon-overlap test: any vertex of one strictly inside the other, or any edges crossing.
2311
+ - `rayDistanceToRing` (function): function rayDistanceToRing(ring: readonly Vec2[], origin: Vec2, dir: Vec2, minT = 0.6): number — Distance from `origin` along `dir` to the first ring-boundary crossing (ignoring hits closer than `minT`, e.g. the edge the origin sits on). Infinity when the ray never leaves — degenerate.
2312
+ - `rectCorners` (function): function rectCorners(cx: number, cz: number, hw: number, hd: number, rotationY: number): Vec2[] — All four corners of a rotated rect (center, half-extents, yaw in engine rotationY convention).
2313
+ - `rectInsidePolygon` (function): function rectInsidePolygon(ring: readonly Vec2[], cx: number, cz: number, hw: number, hd: number, rotationY: number): boolean — True when the whole rotated rect (corners + edge midpoints) sits inside the ring.
2314
+ - `ringBounds` (function): function ringBounds(ring: readonly Vec2[]): { minX: number; minZ: number; maxX: number; maxZ: number } — Axis-aligned bounding box of a ring.
2315
+ - `ringSelfIntersects` (function): function ringSelfIntersects(ring: readonly Vec2[]): boolean — True when any two non-adjacent edges of the ring properly cross. O(n²), fine for block-scale n.
2316
+ - `splitByLine` (function): function splitByLine(ring: readonly Vec2[], normal: Vec2, limit: number): { below: Vec2[]; above: Vec2[] } — Split a polygon by the line `dot(p, normal) = limit` into the `<=` and `>=` sides.
2317
+ - `triangulatePolygon` (function): function triangulatePolygon(ring: readonly Vec2[]): { positions: Vec2[]; indices: number[] } — Ear-clip a simple polygon into triangles. Returns the cleaned/CCW-oriented vertex ring plus flat index triples into it (so a draping consumer can sample a height per returned vertex). O(n²) — fine for block/park rings. A polygon that stays un-clippable (self-touching after dedupe) yields whatever ears were found before the guard trips; degenerate input returns no triangles.
2318
+ - `triangulateRingBand` (function): function triangulateRingBand(outer: readonly Vec2[], inner: readonly Vec2[]): { positions: Vec2[]; indices: number[] } — Triangulate the band between two nested rings (an outer ring with an inner hole, e.g. a curb ring around a land ring — the sidewalk). Pairs the loops by cumulative arc-length fraction, aligning the inner start to the outer's first vertex, so it is robust to differing vertex counts and to a rotational offset between the rings. Returns the merged vertex list (outer, then the rotated inner) and index triples into it. Zero-area triangles — where the two rings coincide (a street edge with no sidewalk) — are dropped so `computeVertexNormals` never sees a degenerate face.
2319
+
2320
+ ## @jgengine/core/world/cityKind
2321
+
2322
+ - `CITY_DEFAULTS` (const): const CITY_DEFAULTS: CityRules — City defaults: a zoned mixed metropolis — towers downtown, slabs mid-ring, houses at the edge.
2323
+ - `CITY_KIND` (const): const CITY_KIND: "city" — The editor volume kind marking a box as a procedural city district.
2324
+ - `CITY_SCHEMA` (const): const CITY_SCHEMA: ParamSchema — The city parameter schema — drives the inspector sliders and `meta` parse via the studio seam.
2325
+ - `CITY_ZONE_KIND` (const): const CITY_ZONE_KIND: "cityzone" — The editor volume kind that locally overrides a city's zone band/mix — a district in a district.
2326
+ - `CITY_ZONE_SCHEMA` (const): const CITY_ZONE_SCHEMA: ParamSchema — Zone-override schema for `cityzone` volumes: pin a band and optionally a bespoke class mix.
2327
+ - `CityBlock` (interface): interface CityBlock — One closed city block: a face of the road graph, inset to curb and land boundaries.
2328
+ - `CityBridge` (interface): interface CityBridge — One bridge deck spanning water: bank-to-bank polyline plus the silhouette style.
2329
+ - `CityDriveway` (interface): interface CityDriveway — One driveway ribbon from a street to a lot.
2330
+ - `CityHedge` (interface): interface CityHedge — One hedge run: a thin box strip (estate perimeter).
2331
+ - `CityIntersection` (interface): interface CityIntersection — One crossing of two through streets: patch center/radius plus crosswalk arm directions.
2332
+ - `CityLight` (interface): interface CityLight — One street light: curb position plus the yaw its arm faces (over the road).
2333
+ - `CityLot` (interface): interface CityLot — One building lot: footprint, zone band, class, seeded floors, massing pieces, street anchor.
2334
+ - `CityParcel` (interface): interface CityParcel — One polygonal parcel subdivided from a block's street frontage.
2335
+ - `CityParcelFrontageOut` (interface): interface CityParcelFrontageOut — One street-frontage edge of a parcel.
2336
+ - `CityPark` (interface): interface CityPark — One intentional open space: an unbuilt block, a block-interior courtyard, or a buffer sliver.
2337
+ - `CityParking` (interface): interface CityParking — One parking pad behind a commercial lot.
2338
+ - `CityResolveContext` (interface): interface CityResolveContext extends SceneKindResolveContext — Extended resolve context: sibling `cityzone` volumes that override the band/mix locally.
2339
+ - `CityRules` (interface): interface CityRules — Fully-defaulted city params parsed from a volume's `meta`.
2340
+ - `CityStreet` (interface): interface CityStreet — One synthesized street: a world-space XZ polyline with width, hierarchy level, and surface.
2341
+ - `CityTree` (interface): interface CityTree — One placed tree: world XZ, species, and seeded scale/color jitter.
2342
+ - `CityTunnel` (interface): interface CityTunnel — One tunnel bore piercing a ridge: portal-to-portal polyline held at bank height.
2343
+ - `ResolvedCity` (interface): interface ResolvedCity — A resolved city district: world-space network, zoned lots, parks, and furniture.
2344
+ - `resolveCityObject` (function): function resolveCityObject(object: SceneKindObject, context?: CityResolveContext): ResolvedCity | null — Synthesize the deterministic city plan for one `city` volume: streets → bridges → parks → zoned frontage lots with massing pieces → furniture, all in the volume's local frame and then rotated/translated into world space. Same volume (id, footprint, meta) over the same terrain always resolves to the identical plan. When `context` provides a ground sampler, lots respect the `maxSlope` cliff rule — hillside and canyon districts keep their steep faces open. When `context.zoneOverrides` carries sibling `cityzone` volumes, lots inside them adopt the override band/mix. Returns null without a usable footprint.
2345
+
2022
2346
  ## @jgengine/core/world/connectors
2023
2347
 
2024
2348
  - `ConnectorPieceDef` (interface): interface ConnectorPieceDef — ⚠ undocumented
@@ -2068,7 +2392,9 @@
2068
2392
  - `BiomeSky` (interface): interface BiomeSky — Per-band sky/light override cross-faded along z by `createBiomeSkySampler`; unset fields fall through to the base sky.
2069
2393
  - `BiomesWorldConfig` (interface): interface BiomesWorldConfig extends WorldGridConfig — ⚠ undocumented
2070
2394
  - `BuildingEnvironmentConfig` (interface): interface BuildingEnvironmentConfig — ⚠ undocumented
2071
- - `BuildingEnvironmentDescriptor` (type): type BuildingEnvironmentDescriptor = { kind: "building" } & Required< Pick<BuildingEnvironmentConfig, "count" | "footprint" | "stories" | "storyHeight" | "spacing" | "style"> > & Pick<BuildingEnvironmentConfig, "seed" | "position" | "palette"> — ⚠ undocumented
2395
+ - `BuildingEnvironmentDescriptor` (type): type BuildingEnvironmentDescriptor = { kind: "building" } & Required< Pick<BuildingEnvironmentConfig, "count" | "footprint" | "stories" | "storyHeight" | "spacing" | "style"> > & Pick<BuildingEnvironmentConfig, "seed" | "position" | "palette" | "along"> — ⚠ undocumented
2396
+ - `BuildingFrontageConfig` (interface): interface BuildingFrontageConfig — Street-aware placement for `building()`: instead of a grid scattered around `position`, lots are stepped along each road's frontage, offset by a consistent setback (a curb + sidewalk strip), and turned so every building FRONT faces its road. `footprint` (`w` = frontage width, `d` = depth) and `spacing` (along-road gap) are shared with the grid mode. Deterministic and bounded by `maxLots`.
2397
+ - `BuildingFrontageRoad` (interface): interface BuildingFrontageRoad — One road a `building({ along })` frontage lines with buildings: centerline + full width.
2072
2398
  - `EnvironmentArea` (interface): interface EnvironmentArea extends WorldBounds — ⚠ undocumented
2073
2399
  - `EnvironmentDescriptorList` (type): type EnvironmentDescriptorList<T> = T | readonly T[] — ⚠ undocumented
2074
2400
  - `EnvironmentVec2` (type): type EnvironmentVec2 = readonly [number, number] — ⚠ undocumented
@@ -2112,12 +2438,12 @@
2112
2438
  - `WaterEnvironmentDescriptor` (type): type WaterEnvironmentDescriptor = OceanEnvironmentDescriptor — ⚠ undocumented
2113
2439
  - `WeatherEnvironmentDescriptor` (type): type WeatherEnvironmentDescriptor = RainEnvironmentDescriptor | SnowEnvironmentDescriptor — ⚠ undocumented
2114
2440
  - `WorldBounds` (interface): interface WorldBounds — ⚠ undocumented
2115
- - `WorldFeature` (type): type WorldFeature = | ({ kind: "biomes" } & BiomesWorldConfig) | ({ kind: "voxel" } & VoxelWorldConfig) | ({ kind: "plots" } & PlotsWorldConfig) | ({ kind: "tilemap" } & TilemapWorldConfig) | EnvironmentWorldFeature | { kind: "flat" } — A declared world shape — biomes, voxel grid, plots, tilemap, environment, or flat — passed to `defineGame`.
2441
+ - `WorldFeature` (type): type WorldFeature = | PlaceWorldFeature | ({ kind: "biomes" } & BiomesWorldConfig) | ({ kind: "voxel" } & VoxelWorldConfig) | ({ kind: "plots" } & PlotsWorldConfig) | ({ kind: "tilemap" } & TilemapWorldConfig) | EnvironmentWorldFeature | { kind: "flat" } — A declared world shape passed to `defineGame`. The preferred model is the place feature from `world()` (`@jgengine/core/world/place`): substrate + laws, with all dressing authored in the editor. The remaining members — biomes, voxel grid, plots, tilemap, environment, flat — are the legacy code-declared shapes kept for existing games.
2116
2442
  - `WorldGridCell` (interface): interface WorldGridCell — ⚠ undocumented
2117
2443
  - `WorldGridConfig` (interface): interface WorldGridConfig — Shared by `biomes()`/`voxel()`/`plots()`/`tilemap()` so the shell can render their declared content as instanced boxes without a hand-written renderer.
2118
2444
  - `biomes` (function): function biomes(config: BiomesWorldConfig): WorldFeature — Declares a biome-painted world — the whole-world alternative to a single `environment()` terrain.
2119
- - `building` (function): function building(config: BuildingEnvironmentConfig = {}): BuildingEnvironmentDescriptor — Declares a cluster of procedurally-massed buildings for `environment()` — count, footprint, stories, style.
2120
- - `environment` (function): function environment(config: EnvironmentWorldConfig = {}): EnvironmentWorldFeature — Composes an `environment()` world feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
2445
+ - `building` (function): function building(config: BuildingEnvironmentConfig = {}): BuildingEnvironmentDescriptor — Declares a cluster of procedurally-massed buildings for `environment()` — count, footprint, stories, style. Pass `along` to line road frontage instead of gridding around `position`.
2446
+ - `environment` (function): function environment(config: EnvironmentWorldConfig = {}): EnvironmentWorldFeature — Composes an `environment()` feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
2121
2447
  - `flat` (function): function flat(): WorldFeature — Declares an empty flat world — the minimal `WorldFeature` for games with no terrain of their own.
2122
2448
  - `grass` (function): function grass(config: GrassEnvironmentConfig = {}): GrassEnvironmentDescriptor — Declares a grass vegetation patch for `environment()` — area, blade sizing, density, and colors.
2123
2449
  - `island` (function): function island(config: TerrainIslandConfig): TerrainIslandDescriptor — ⚠ undocumented
@@ -2211,14 +2537,19 @@
2211
2537
  ## @jgengine/core/world/markers
2212
2538
 
2213
2539
  - `DEFAULT_MARKER_KINDS` (const): const DEFAULT_MARKER_KINDS: Record<string, MarkerKindStyle> — ⚠ undocumented
2214
- - `MapMarker` (interface): interface MapMarker<TMeta = unknown> — ⚠ undocumented
2540
+ - `MapMarker` (interface): interface MapMarker<TMeta = unknown> extends MarkerView<TMeta> — A marker owned by {@link MarkerSet}, including its lifecycle and query fields.
2541
+ - `MarkerCollection` (type): type MarkerCollection<TMarker extends MarkerView = MarkerView> = | readonly TMarker[] | MarkerSource<TMarker> | MarkerSet — Marker data accepted by portable consumers: static views, an external source, or a native set.
2215
2542
  - `MarkerInput` (interface): interface MarkerInput<TMeta = unknown> — ⚠ undocumented
2216
2543
  - `MarkerKindStyle` (interface): interface MarkerKindStyle — Visual descriptor for a marker kind. Games supply their own palette; the engine ships `DEFAULT_MARKER_KINDS` as a content-agnostic starting set that the react minimap/compass read for colors and glyphs.
2217
2544
  - `MarkerPosition` (type): type MarkerPosition = readonly [number, number, number] — ⚠ undocumented
2218
2545
  - `MarkerQuery` (interface): interface MarkerQuery — ⚠ undocumented
2219
2546
  - `MarkerSet` (interface): interface MarkerSet<TMeta = unknown> — ⚠ undocumented
2547
+ - `MarkerSource` (interface): interface MarkerSource<TMarker extends MarkerView = MarkerView> — Observable marker snapshots owned by an external project. `getSnapshot` must return the same array identity until the source changes and calls its subscribers, matching React's external-store contract.
2548
+ - `MarkerSourceOptions` (interface): interface MarkerSourceOptions<TEntity, TMarker extends MarkerView = MarkerView> — Configuration for projecting a caller-owned collection into display-only markers.
2549
+ - `MarkerView` (interface): interface MarkerView<TMeta = unknown> — Small, display-only marker shape consumed by map renderers. Existing games can project their own entities to this view without adopting marker lifecycle storage or duplicating them into a {@link MarkerSet}.
2220
2550
  - `createMarkerSet` (function): function createMarkerSet<TMeta = unknown>(now: () => number = Date.now): MarkerSet<TMeta> — ⚠ undocumented
2221
- - `markerKindStyle` (function): function markerKindStyle(kind: string, styles: Record<string, MarkerKindStyle> = DEFAULT_MARKER_KINDS): MarkerKindStyle — ⚠ undocumented
2551
+ - `createMarkerSource` (function): function createMarkerSource<TEntity, TMarker extends MarkerView = MarkerView>(options: MarkerSourceOptions<TEntity, TMarker>): MarkerSource<TMarker> — Adapt a caller-owned array/store to an observable marker source. Projection is cached between source changes, so React reads do not copy the collection per frame. The caller retains ownership of entities, updates, persistence, and subscription scheduling.
2552
+ - `markerKindStyle` (function): function markerKindStyle(kind: string | undefined, styles: Record<string, MarkerKindStyle> = DEFAULT_MARKER_KINDS): MarkerKindStyle — ⚠ undocumented
2222
2553
 
2223
2554
  ## @jgengine/core/world/massing
2224
2555
 
@@ -2249,6 +2580,25 @@
2249
2580
  - `relativeBearing` (function): function relativeBearing(bearing: number, reference: number): number — Signed offset of `bearing` from `reference`, wrapped into (−π, π].
2250
2581
  - `unprojectFromMinimap` (function): function unprojectFromMinimap(point: { x: number; y: number }, view: MinimapView): WorldXZ — Invert `projectToMinimap` (#285.6): minimap pixel → world XZ, rotate-aware — click-to-pin, tap-to-ping, drag-to-set-waypoint map interactions.
2251
2582
 
2583
+ ## @jgengine/core/world/minimapBake
2584
+
2585
+ - `DEFAULT_MINIMAP_PALETTE` (const): const DEFAULT_MINIMAP_PALETTE: MinimapBakePalette — The built-in height→color ramp and water color a bake uses when no palette override is given.
2586
+ - `MinimapBake` (interface): interface MinimapBake — A baked minimap image: RGBA pixels plus the world bounds they span.
2587
+ - `MinimapBakeBounds` (interface): interface MinimapBakeBounds — Deterministic minimap terrain bake (#1036): rasterize an authored world's terrain (plus optional biome zones and water) into a top-down RGBA image and a matching world-bounds rectangle, then encode it as a PNG data URI. The editor runs this as a bake action and stores the result on the scene document; runtime feeds it straight into the existing `Minimap` / `WorldMap` `background` + `mapBounds` props — no new runtime render path, and the same authored world always bakes the same image (safe for verify/CI). Pure: no canvas, no DOM, `core` still imports nothing external.
2588
+ - `MinimapBakeOptions` (interface): interface MinimapBakeOptions — Options for {@link bakeMinimapImage}.
2589
+ - `MinimapBakePalette` (interface): interface MinimapBakePalette — The height→color ramp and water color used by the bake.
2590
+ - `MinimapBakeSource` (interface): interface MinimapBakeSource — The authored world a bake reads — a height sampler, its bounds, and optional zones/water.
2591
+ - `MinimapBakeZone` (interface): interface MinimapBakeZone — One biome/region tint painted over the terrain shade where the ground falls inside its polygon.
2592
+ - `bakeMinimapBackground` (function): function bakeMinimapBackground(source: MinimapBakeSource, options: MinimapBakeOptions = {}): { background: string; mapBounds: MinimapBakeBounds } — One-call convenience: rasterize a source and return `{ background, mapBounds }` for a minimap.
2593
+ - `bakeMinimapImage` (function): function bakeMinimapImage(source: MinimapBakeSource, options: MinimapBakeOptions = {}): MinimapBake — Rasterizes a top-down terrain image: height maps onto a low→high color ramp (normalized over the sampled height range), slope darkens the shade, water fills below `waterLevel`, and each zone polygon tints the ground it covers. Deterministic for a fixed source. The bounds are preserved so a player-centered minimap pans the image correctly.
2594
+ - `encodeBakePng` (function): function encodeBakePng(bake: MinimapBake): Uint8Array — Encodes an RGBA bake to raw PNG bytes (pure; stored DEFLATE, valid for any decoder).
2595
+ - `minimapBakeToPngDataUri` (function): function minimapBakeToPngDataUri(bake: MinimapBake): string — Encodes a bake as a `data:image/png;base64,...` URI — the exact string the `Minimap` / `WorldMap` `background` prop takes. Deterministic for a fixed bake.
2596
+
2597
+ ## @jgengine/core/world/minimapTrack
2598
+
2599
+ - `TrackAxis` (interface): interface TrackAxis — A world-space segment defining a linear "track" minimap — points are projected onto the `from`→`to` axis.
2600
+ - `trackFraction` (function): function trackFraction(point: WorldXZ | readonly [number, number, number], axis: TrackAxis): number — Project a world point onto the `from`→`to` segment of `axis` and return the clamped 0..1 fraction of how far along the track it lies (0 at `from`, 1 at `to`). The linear analogue of `projectToMinimap` — feeds a horizontal corridor/route progress rail. Accepts XZ (`[x, z]`) or XYZ (`[x, y, z]`) points (index 0 = x, index 2 when length 3 else index 1 = z). A zero-length axis returns 0.
2601
+
2252
2602
  ## @jgengine/core/world/pathInstances
2253
2603
 
2254
2604
  - `PathInstance` (interface): interface PathInstance — One placed transform along a path: grounded position, facing yaw, and its ordinal + arc distance.
@@ -2262,6 +2612,29 @@
2262
2612
  - `TerrainPathProfile` (interface): interface TerrainPathProfile — A serializable path-driven terrain modifier. The `points` centerline reshapes the heightfield across a corridor of `width`, feathering back to the surrounding ground across `shoulder`. `height` sets the centerline target (sample / fixed / grade); `depth` carves a channel below it (deepest at the centerline, easing to zero at the core edge — rivers and trenches); `retaining` raises walls where the cut/fill exceeds a threshold; `maxCut`/`maxFill` cap how far the ground may move from its base height. All fields are plain data (numbers, string enums, point arrays) so a profile round-trips through the scene document and evaluates identically at author time and runtime.
2263
2613
  - `withPathProfiles` (function): function withPathProfiles(base: (x: number, z: number) => number, profiles: readonly TerrainPathProfile[]): (x: number, z: number) => number — Wraps a height sampler so each authored `TerrainPathProfile` reshapes it. Profiles apply in list order (later profiles compose over earlier ones, so an intersection's last profile wins its core); each reads the running height as its surrounding ground and the original `base` for `sample` centerline heights. The returned sampler is pure and deterministic. Degenerate profiles (fewer than two points, non-positive width or length) are skipped; with no usable profile the original `base` is returned unchanged.
2264
2614
 
2615
+ ## @jgengine/core/world/place
2616
+
2617
+ - `BoardGround` (interface): interface BoardGround — A 2D surface you look at — grid games, solitaire, tabletop. Physics is often zero-gravity or omitted; the game owns the face it draws on the board.
2618
+ - `BoardGroundSize` (interface): interface BoardGroundSize — Size of a `board` ground: a 2D surface you look at, in cells or layout units.
2619
+ - `FlatGround` (interface): interface FlatGround — A 3D walkable plane/slab. `Infinity` axes are unbounded; no separate "infinite" mode exists.
2620
+ - `FlatGroundSize` (interface): interface FlatGroundSize — Size of a `flat` ground: extents in world units. `Infinity` on an axis means unbounded — an endless plain needs no bounds number invented for it. `y` optionally bounds vertical play space.
2621
+ - `GroundConfig` (type): type GroundConfig = FlatGround | RoundGround | VoxelGround | BoardGround — The substrate of a place, discriminated by `mode` — TS rejects a `radius` on `flat` and `x`/`z` on `round`.
2622
+ - `GroundGenerator` (interface): interface GroundGenerator — Serializable algorithm parameters for a procedural ground generator. Never a genre kit.
2623
+ - `GroundMode` (type): type GroundMode = "flat" | "round" | "voxel" | "board" — Canonical ground modes after normalization (`stage` → `board`).
2624
+ - `PlaceConfig` (interface): interface PlaceConfig — Input to {@link world}: place identity, substrate, and the laws of this place.
2625
+ - `PlaceWorldFeature` (interface): interface PlaceWorldFeature — A declared place — the `world()` result carried on `GameDefinition.world`.
2626
+ - `ResolvedBoardGround` (type): type ResolvedBoardGround = Omit<BoardGround, "mode"> & { mode: "board" } — {@link BoardGround} with the `stage` alias resolved away.
2627
+ - `ResolvedGround` (type): type ResolvedGround = FlatGround | RoundGround | VoxelGround | ResolvedBoardGround — A place's ground after `world()` normalization.
2628
+ - `RoundGround` (interface): interface RoundGround — A planet/sphere you play on the outside of. Sized by `radius` only.
2629
+ - `RoundGroundSize` (interface): interface RoundGroundSize — Size of a `round` ground: the planet/sphere radius in world units. Nothing else.
2630
+ - `SurfaceLaws` (interface): interface SurfaceLaws — The place model: a world is the place you play in — substrate (ground) plus laws (physics, surface) — never a dressed diorama. Sky look, foliage scatter, props, and sculpt are content: they are authored in the editor (or by a content preset that writes into the scene document) and consumed through the authored-scene seams, not declared on the world.
2631
+ - `VoxelGround` (interface): interface VoxelGround — A procedural volume of blocks. `size` is the generator domain; `generator` is algorithm params only.
2632
+ - `VoxelGroundSize` (interface): interface VoxelGroundSize — Size of a `voxel` ground: the generator's domain per axis; axes may be `Infinity` for streaming volumes.
2633
+ - `isPlaceWorld` (function): function isPlaceWorld(worldFeature: { kind: string } | undefined): worldFeature is PlaceWorldFeature — Type guard for the place-model world feature.
2634
+ - `resolveWorldPhysics` (function): function resolveWorldPhysics(worldFeature: { kind: string; physics?: PhysicsConfig } | undefined, base: PhysicsConfig | undefined): PhysicsConfig | undefined — Resolves the physics laws in effect for the active world: a place world's own `physics` wins field-by-field over the game-level default. Non-place worlds (and games with no world) keep the game-level config unchanged.
2635
+ - `seedForPlace` (function): function seedForPlace(worldId: string, runSeed = ""): string — The engine-side seed derivation for a place: a stable string from the world `id` plus the save/run seed. Generators and scatter receive this — never a `seed` field in the world definition — so a save replays its world deterministically and a fresh run can vary by `runSeed` alone.
2636
+ - `world` (function): function world(config: PlaceConfig): PlaceWorldFeature — Declares the place a game is played in: substrate (`ground`) + laws (`physics`, `ground.surface`). The thin default start — `flat` with `Infinity` axes and default physics, `board` for 2D — is a complete world; dressing it (sky, foliage, props, sculpt) is editor-authored scene content. Multiple worlds per game are first-class: declare one `world()` per place, each with its own id, ground, and physics. Games that are not a spatial place (pure UI/rules) omit `world` entirely.
2637
+
2265
2638
  ## @jgengine/core/world/placeAsset
2266
2639
 
2267
2640
  - `PlaceAssetFromCommitOptions` (interface): interface PlaceAssetFromCommitOptions — Optional catalog/label overrides for {@link placeAssetFromCommit}.
@@ -2305,6 +2678,15 @@
2305
2678
  - `createPlacementController` (function): function createPlacementController(config: PlacementControllerConfig): PlacementController — Headless placement ghost: hover → valid/invalid preview, rotate, grid/free/surface snap, commit. Pair with `@jgengine/shell/structures` `PlacementGhost` and {@link placeAssetFromCommit}.
2306
2679
  - `quarterTurnsToRotationY` (function): function quarterTurnsToRotationY(quarterTurns: number): number — Maps 0–3 quarter turns onto radians for ghost/commit rotation.
2307
2680
 
2681
+ ## @jgengine/core/world/poleLineKind
2682
+
2683
+ - `Cable` (interface): interface Cable — One resolved cable span: a point string to loft into a tube, plus its radius.
2684
+ - `POLE_LINE_KIND` (const): const POLE_LINE_KIND: "pole_line" — The editor path kind marking a polyline as a pole/cable run.
2685
+ - `POLE_LINE_SCHEMA` (const): const POLE_LINE_SCHEMA: ParamSchema — The pole-line parameter schema — drives the inspector and `meta` parse via the studio seam.
2686
+ - `Pole` (interface): interface Pole — One placed pole: grounded base position plus facing yaw along the run.
2687
+ - `ResolvedPoleLine` (interface): interface ResolvedPoleLine — The renderable payload the resolver returns and the shell renderer consumes.
2688
+ - `resolvePoleLine` (function): function resolvePoleLine(object: SceneKindObject, params: ParsedParams, context?: SceneKindResolveContext): ResolvedPoleLine — Resolve poles + cables from a document object's points and parsed params. Poles come from the generic `placeAlongPath` sampler; between each consecutive pair, `wireCount` parallel cables are strung with lateral offset and quadratic-Bézier `sag` (deeper on longer spans). Pure data.
2689
+
2308
2690
  ## @jgengine/core/world/polyline
2309
2691
 
2310
2692
  - `Polyline` (interface): interface Polyline — A polyline prepared for repeated distance/fraction sampling, with cumulative arc-length precomputed.
@@ -2332,14 +2714,30 @@
2332
2714
  - `createRegionField` (function): function createRegionField<T = unknown>(config: RegionFieldConfig<T>): RegionField<T> — ⚠ undocumented
2333
2715
  - `isRegionField` (function): function isRegionField(field: TerrainField): field is RegionField — ⚠ undocumented
2334
2716
 
2717
+ ## @jgengine/core/world/resourceNode
2718
+
2719
+ - `HarvestOptions` (interface): interface HarvestOptions — Options for a single harvest.
2720
+ - `HarvestResult` (interface): interface HarvestResult — Outcome of one harvest attempt.
2721
+ - `Quantity` (type): type Quantity = number | readonly [number, number] — A quantity that is either fixed or a uniformly sampled `[min, max]` range resolved by the field rng.
2722
+ - `ResourceGrant` (interface): interface ResourceGrant — One resource kind granted by a harvest and its resolved amount.
2723
+ - `ResourceNodeDef` (interface): interface ResourceNodeDef — A harvestable node definition: a finite budget, the resources it yields, and how it respawns.
2724
+ - `ResourceNodeField` (interface): interface ResourceNodeField — A set of harvestable nodes: harvest with tool profiles, tick respawn timers, snapshot/hydrate for save-load.
2725
+ - `ResourceNodeFieldConfig` (interface): interface ResourceNodeFieldConfig — Construction options for {@link createResourceNodeField}: node definitions and an optional RNG/suppression hook.
2726
+ - `ResourceNodeState` (interface): interface ResourceNodeState — Serializable per-node runtime state — round-trips through save/load and multiplayer sync.
2727
+ - `ResourceYield` (interface): interface ResourceYield — One resource kind a node can yield and its base per-harvest amount (before tool bias and harvester multiplier).
2728
+ - `ToolProfile` (interface): interface ToolProfile — How a tool extracts from a node — its per-hit power and per-resource yield bias. Two profiles over the same multi-resource node return different resources and amounts: the generic pick-vs-hatchet mechanic.
2729
+ - `createResourceNodeField` (function): function createResourceNodeField(config: ResourceNodeFieldConfig): ResourceNodeField — A field of depletable, respawning harvest nodes with tool-dependent yields — the generic rock / tree / bush / vein / corpse. Each node holds a finite budget across one or more resource kinds. A harvest applies a {@link ToolProfile} whose per-resource biases decide *which* resources and *how much* the same node returns (pick favors ore, hatchet favors wood), scaled by a creature/harvester multiplier and optional deterministic rng variance; the budget drops by the tool's power. When a node empties it starts a respawn timer that `tick(dt)` counts down and refills — unless respawn is suppressed by the per-node flag or the injected predicate (a structure claimed the spot). All state is plain and serializable for save-load and multiplayer sync via {@link snapshot}/{@link hydrate}.
2730
+
2335
2731
  ## @jgengine/core/world/roads
2336
2732
 
2733
+ - `DashExclusion` (interface): interface DashExclusion — A circular exclusion zone: dashes whose midpoint falls inside are dropped (e.g. junction patches).
2337
2734
  - `RoadPoint` (type): type RoadPoint = readonly [number, number] — A road centerline vertex in world XZ.
2338
2735
  - `RoadRibbon` (interface): interface RoadRibbon — Renderer-ready triangle ribbon: flat position triples plus triangle indices.
2339
2736
  - `RoadRibbonOptions` (interface): interface RoadRibbonOptions — Options for {@link buildRoadRibbon}.
2340
2737
  - `RoadSample` (interface): interface RoadSample — Result of {@link nearestOnPath}: closest point on the centerline plus distance and tangent.
2738
+ - `buildJunctionPatch` (function): function buildJunctionPatch(center: RoadPoint, radius: number, sampleHeight: (x: number, z: number) => number, options: { elevation?: number; segments?: number } = {}): RoadRibbon — Build a flat, ground-draped disc patch centered on `center` — the welded junction surface that covers crossing road ribbons so they read as one intersection instead of stacking/z-fighting. A triangle fan of `segments` sides (default 16), every vertex draped at `sampleHeight + elevation`. Pure geometry; the shell meshes the result with the asphalt material.
2341
2739
  - `buildRoadRibbon` (function): function buildRoadRibbon(path: readonly RoadPoint[], width: number, sampleHeight: (x: number, z: number) => number, options: RoadRibbonOptions = {}): RoadRibbon — Triangulate a road centerline into a ground-draped ribbon mesh: the polyline is subdivided, each vertex is offset half a `width` along the local perpendicular, and every vertex sits at `sampleHeight(x, z) + elevation`. Pure geometry — the shell (or any renderer) turns the result into a mesh, and tests can assert on it directly.
2342
- - `dashSegments` (function): function dashSegments(path: readonly RoadPoint[], dashLength = 3, gapLength = 3): readonly (readonly RoadPoint[])[] — Split a centerline into dash sub-polylines for lane markings: `dashLength` of painted line, `gapLength` of asphalt, repeated along the path's arc length. Feed each returned sub-path back through {@link buildRoadRibbon} with a thin width to mesh the dashes.
2740
+ - `dashSegments` (function): function dashSegments(path: readonly RoadPoint[], dashLength = 3, gapLength = 3, exclude: readonly DashExclusion[] = []): readonly (readonly RoadPoint[])[] — Split a centerline into dash sub-polylines for lane markings: `dashLength` of painted line, `gapLength` of asphalt, repeated along the path's arc length. Feed each returned sub-path back through {@link buildRoadRibbon} with a thin width to mesh the dashes. Pass `exclude` circles (junction patches) to interrupt the center line through intersections — any dash whose midpoint lands inside an exclusion is dropped.
2343
2741
  - `isOnRoad` (function): function isOnRoad(path: readonly RoadPoint[], width: number, x: number, z: number): boolean — True when the query point lies within half the road `width` of the centerline.
2344
2742
  - `nearestOnPath` (function): function nearestOnPath(path: readonly RoadPoint[], x: number, z: number): RoadSample | null — Closest-point query against a road centerline — the seam traffic AI, spawn placement, and "am I on the road" checks share. Returns null for a degenerate path.
2345
2743
  - `pathLength` (function): function pathLength(path: readonly RoadPoint[]): number — Total arc length of a centerline in world units.
@@ -2440,17 +2838,47 @@
2440
2838
  - `sphereRegion` (function): function sphereRegion(center: Point3, radius: number, options: { distribution?: VolumeDistribution } = {}): SampleRegion<Point3> — A filled ball. `"volume"` is volume-uniform (∛-corrected radius); `"radial"` is radius-uniform. Direction is drawn first (two draws), then radius.
2441
2839
  - `weightedRegion` (function): function weightedRegion<P extends SamplePoint>(entries: readonly WeightedRegionEntry<P>[]): SampleRegion<P> — A composite that first picks one member by weight, then delegates to its sampler — the "weighted subregions" distribution policy. `contains` is true when any member contains the point.
2442
2840
 
2841
+ ## @jgengine/core/world/streetGenerator
2842
+
2843
+ - `Street` (interface): interface Street — One chained through-street: a maximal run of edges through degree-2 nodes, for rendering + furniture.
2844
+ - `StreetDeadEnd` (interface): interface StreetDeadEnd — One dangling street end kept as a cul-de-sac: node position plus the heading pointing off the road.
2845
+ - `StreetEdge` (interface): interface StreetEdge — One atomic node-to-node edge — the fabric graph consumes these (welds at shared node coords).
2846
+ - `StreetFeature` (interface): interface StreetFeature — A resolved path feature in world-of-the-volume space: a bridge deck or tunnel bore centerline.
2847
+ - `StreetFeatureKind` (type): type StreetFeatureKind = "bridge" | "tunnel" — A path feature spanning part of an edge/street: a bridge deck over a gap or a tunnel bore under a ridge.
2848
+ - `StreetFeatureSpan` (interface): interface StreetFeatureSpan — A feature span carried by a street: a `[from, to]` index window into the street's `points`.
2849
+ - `StreetJunction` (interface): interface StreetJunction — One crossing of three or more streets: patch center/radius plus outgoing arm directions.
2850
+ - `StreetLevel` (type): type StreetLevel = "boulevard" | "avenue" | "street" | "lane" — Road hierarchy, widest to narrowest — shared by the city fabric and the renderer.
2851
+ - `StreetNetwork` (interface): interface StreetNetwork — The fully-resolved network in volume-local coords.
2852
+ - `StreetNetworkContext` (interface): interface StreetNetworkContext — Ground sampler + feature toggles enabling bridges/tunnels; omit for a flat, feature-free network.
2853
+ - `StreetNetworkMode` (type): type StreetNetworkMode = "net" | "circuit" — The generator's chosen topology family: an open street `net`, or a closed `circuit` loop.
2854
+ - `StreetNetworkRules` (interface): interface StreetNetworkRules — Fully-defaulted slider set the generator reads.
2855
+ - `StreetNode` (interface): interface StreetNode — One graph node: a junction, a dead end, or a mid-street bend, with its connection count.
2856
+ - `StreetVec2` (type): type StreetVec2 = readonly [number, number] — A path vertex in the volume-local XZ frame.
2857
+ - `generateStreets` (function): function generateStreets(rules: StreetNetworkRules, hx: number, hz: number, context: StreetNetworkContext = {}): StreetNetwork — Resolve a full path network from its rules inside a volume of half-extents `hx`×`hz`. Deterministic per `(rules.seed, hx, hz, context)`. Pass a {@link StreetNetworkContext} with a ground sampler to turn water gaps into bridges and ridges into tunnels. Coordinates are volume-local; the caller maps to world space.
2858
+
2443
2859
  ## @jgengine/core/world/streets
2444
2860
 
2445
2861
  - `FurnitureSpot` (interface): interface FurnitureSpot — A placement anchor on the curb line: position, outward-facing heading, and which side it sits on.
2446
2862
  - `FurnitureSpotOptions` (interface): interface FurnitureSpotOptions — Options for {@link furnitureSpots}.
2863
+ - `JunctionMarkingOptions` (interface): interface JunctionMarkingOptions — Options for {@link junctionMarkings}.
2864
+ - `JunctionMarkings` (interface): interface JunctionMarkings — Thin marking polylines for a junction: stop-line bars and crosswalk bars, ready for {@link buildRoadRibbon}.
2447
2865
  - `ParkingSpot` (interface): interface ParkingSpot — A curbside parking anchor: position at the road edge and a heading parallel to the street.
2448
2866
  - `ParkingSpotOptions` (interface): interface ParkingSpotOptions — Options for {@link parkingSpots}.
2867
+ - `RoadApproach` (interface): interface RoadApproach — A single arm of a junction: the road width plus the outward direction the road leaves the center.
2868
+ - `RoadJunction` (interface): interface RoadJunction — A welded road intersection: a patch center/radius plus the arms that feed it.
2869
+ - `RoadJunctionOptions` (interface): interface RoadJunctionOptions — Options for {@link findRoadJunctions}.
2870
+ - `RoadSurfaceOptions` (interface): interface RoadSurfaceOptions — Grip levels and blend width for {@link roadSurfaceSampler}; each field is optional and defaulted.
2449
2871
  - `StreetLane` (interface): interface StreetLane — A directed lane derived from a road: an offset centerline plus its direction of travel.
2872
+ - `curbPaths` (function): function curbPaths(road: RoadEnvironmentDescriptor, inset = 0): readonly [readonly RoadPoint[], readonly RoadPoint[]] — The two curb lines of a road — offset polylines running along the outer edge of the asphalt on each side. Mesh these with a thin darker ribbon to give the road a curb/edge strip instead of a hard asphalt-to-terrain seam. `inset` (default 0) nudges the line inward off the raw edge so the strip straddles the border.
2873
+ - `distanceToRoadEdge` (function): function distanceToRoadEdge(roads: readonly RoadEnvironmentDescriptor[], x: number, z: number): number — Signed planar distance from `(x, z)` to the nearest road *surface edge* across every segment of every road (#1051): negative inside the asphalt (magnitude = how far in from the closest edge, so `-width/2` on the centerline), `~0` right at the curb, and positive off the road (the gap to the nearest edge). Point-to-segment distance minus the road's half width, minimised over all segments — the "am I on the road, and by how much" seam driving grip, tyre audio, and off-road penalties.
2874
+ - `findRoadJunctions` (function): function findRoadJunctions(roads: readonly RoadEnvironmentDescriptor[], options: RoadJunctionOptions = {}): readonly RoadJunction[] — Detect welded intersections across a set of roads: wherever two road centerlines cross (or a road terminates on another) within the same elevation band, emit a {@link RoadJunction} whose patch covers the crossing ribbons. Nearby crossings merge into one junction. Deterministic and bounded — O(roads² · segments²) with a `maxJunctions` cap — so a scene builds its intersections once.
2450
2875
  - `furnitureSpots` (function): function furnitureSpots(road: RoadEnvironmentDescriptor, options: FurnitureSpotOptions = {}): readonly FurnitureSpot[] — Evenly spaced street-furniture anchors along a road's curb lines — streetlights, palms, signs, hydrants, benches. Each spot sits just outside the asphalt (plus `outset`), faces away from the street, and alternates sides by default so lights stagger like a real avenue. This is the answer to "where do I put it": furniture is an asset of the street, never a hand-typed coordinate.
2876
+ - `junctionExclusions` (function): function junctionExclusions(junctions: readonly RoadJunction[], pad = 0.5): readonly DashExclusion[] — Circular marking-exclusion zones for the junctions, sized to hide the center line under each patch.
2877
+ - `junctionMarkings` (function): function junctionMarkings(junction: RoadJunction, options: JunctionMarkingOptions = {}): JunctionMarkings — Data-driven junction entry markings: a stop-line bar across each approach and a band of crosswalk bars just outside the welded patch. Each returned polyline is a thin centerline meant to be meshed with {@link buildRoadRibbon} at a small width. Fully skippable per-feature via the options.
2451
2878
  - `laneCenters` (function): function laneCenters(road: RoadEnvironmentDescriptor): readonly [StreetLane, StreetLane] — Two right-hand-traffic lane centerlines for a road — each offset a quarter of the drivable width from the center and ordered in its direction of travel. Feed a lane's `path` straight into `nav/pathFollow` for traffic AI, or use its endpoints as directed car spawn points.
2452
2879
  - `offsetPath` (function): function offsetPath(path: readonly RoadPoint[], offset: number): readonly RoadPoint[] — Offset a centerline sideways by a signed distance along its local perpendicular — the building block for lanes, curb lines, and sidewalk paths. Positive offsets fall on the left of the direction of travel, negative on the right.
2453
2880
  - `parkingSpots` (function): function parkingSpots(road: RoadEnvironmentDescriptor, options: ParkingSpotOptions = {}): readonly ParkingSpot[] — Curbside parking anchors along a road: hugging the edge of the asphalt, headed parallel to the street in that side's direction of travel. Spawn parked vehicles here instead of eyeballing coordinates in the middle of the carriageway.
2881
+ - `roadSurfaceSampler` (function): function roadSurfaceSampler(roads: readonly RoadEnvironmentDescriptor[], options: RoadSurfaceOptions = {}): (x: number, z: number) => number — A `surfaceFriction`-compatible sampler (the `(x, z) => grip` hook a kinematic car reads each tick) that turns road geometry into grip (#1051): full `onRoad` grip on the asphalt, a monotonic linear ramp down across a `shoulder`-wide band at the curb, and flat `offRoad` grip beyond it — so a car that clips onto the grass loses bite progressively instead of snapping. Closes over {@link distanceToRoadEdge}, so the returned sampler is itself allocation-free per call.
2454
2882
  - `sidewalkPaths` (function): function sidewalkPaths(road: RoadEnvironmentDescriptor): readonly (readonly RoadPoint[])[] — The two sidewalk walking paths of a road — offset polylines running down the middle of each sidewalk band. Pedestrians spawn and route along these instead of the asphalt.
2455
2883
  - `sidewalkPoint` (function): function sidewalkPoint(road: RoadEnvironmentDescriptor, side: "left" | "right", fraction: number): RoadPoint | null — A deterministic point on one of a road's sidewalks at a normalized position — `side` picks the band, `fraction` (0..1) picks how far along. The canonical pedestrian spawn helper.
2456
2884
  - `sidewalkWidthOf` (function): function sidewalkWidthOf(road: RoadEnvironmentDescriptor): number — Resolved sidewalk band widths for a road; zero when the road declares no sidewalk.
@@ -2513,6 +2941,9 @@
2513
2941
  - `FractalNoiseConfig` (interface): interface FractalNoiseConfig — Octave settings for {@link fractalNoise}: frequency, layering, and optional ridged shaping.
2514
2942
  - `GroundSnapEntityStore` (interface): interface GroundSnapEntityStore — ⚠ undocumented
2515
2943
  - `GroundSnapTarget` (interface): interface GroundSnapTarget — ⚠ undocumented
2944
+ - `HeightFieldRayBounds` (interface): interface HeightFieldRayBounds — XZ region a {@link raycastHeightField} march is clipped to.
2945
+ - `HeightFieldRayHit` (interface): interface HeightFieldRayHit — Where a {@link raycastHeightField} march crossed the surface.
2946
+ - `HeightFieldRaycastOptions` (interface): interface HeightFieldRaycastOptions — Tuning for {@link raycastHeightField}: march resolution and refinement depth.
2516
2947
  - `HeightMapFieldConfig` (interface): interface HeightMapFieldConfig — ⚠ undocumented
2517
2948
  - `ISLAND_VOID_HEIGHT` (const): const ISLAND_VOID_HEIGHT: -256 — Ground height between islands when no base terrain exists — deep enough to read as a fall into the void, finite so physics stays sane.
2518
2949
  - `NoiseFieldConfig` (interface): interface NoiseFieldConfig — Configuration for {@link noiseField}: seed, amplitude, and fractal noise shaping.
@@ -2525,6 +2956,7 @@
2525
2956
  - `TerrainPalette` (interface): interface TerrainPalette — ⚠ undocumented
2526
2957
  - `TerrainSlopeSample` (interface): interface TerrainSlopeSample — ⚠ undocumented
2527
2958
  - `applyPathProfiles` (function): function applyPathProfiles(field: TerrainField, profiles: readonly TerrainPathProfile[]): TerrainField — Composes authored path profiles onto a field — the shared seam that turns a scene road/river/ramp path into flattened, graded, carved, or retained ground. Applies after `flatten` masks in `resolveTerrainField` so a corridor grades over already-leveled pads; call it directly to layer profiles onto any field a game builds by hand. Returns the field unchanged when no profile is given.
2959
+ - `raycastHeightField` (function): function raycastHeightField(sampleHeight: (x: number, z: number) => number, origin: readonly [number, number, number], direction: readonly [number, number, number], options: HeightFieldRaycastOptions): HeightFieldRayHit | null — Intersects a ray with a `sampleHeight` field by fixed-step raymarching plus bisection — the O(steps) editor/gameplay picking seam that replaces brute-force triangle raycasts against a tessellated ground mesh (tens of thousands of triangle tests per pick on a sculpt-sized grid). The ray is clipped to `bounds` on XZ first, marched at `step`, and the first above→below crossing is bisected. An origin already under the surface hits immediately at entry. Returns null when the clipped ray never crosses the surface.
2528
2960
 
2529
2961
  ## @jgengine/core/world/terrainGuides
2530
2962