@jgengine/core 0.14.0 → 0.15.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 (214) hide show
  1. package/CHANGELOG.md +500 -1
  2. package/dist/ai/difficulty.d.ts +154 -0
  3. package/dist/ai/difficulty.js +194 -0
  4. package/dist/ai/driver.d.ts +107 -0
  5. package/dist/ai/driver.js +175 -0
  6. package/dist/ai/flock.js +13 -23
  7. package/dist/ai/laneSelect.js +2 -1
  8. package/dist/ai/mobBrain.js +2 -1
  9. package/dist/ai/waveRunner.d.ts +81 -0
  10. package/dist/ai/waveRunner.js +104 -0
  11. package/dist/audio/musicState.d.ts +47 -0
  12. package/dist/audio/musicState.js +38 -0
  13. package/dist/audio/stepCadence.d.ts +47 -0
  14. package/dist/audio/stepCadence.js +29 -0
  15. package/dist/audio/synth.d.ts +12 -0
  16. package/dist/authoring.d.ts +6 -4
  17. package/dist/authoring.js +6 -4
  18. package/dist/combat/castRunner.d.ts +13 -1
  19. package/dist/combat/castRunner.js +5 -1
  20. package/dist/combat/comboMeter.d.ts +140 -0
  21. package/dist/combat/comboMeter.js +215 -0
  22. package/dist/combat/comboPoints.d.ts +11 -0
  23. package/dist/combat/comboPoints.js +11 -2
  24. package/dist/combat/damageResolution.d.ts +1 -1
  25. package/dist/combat/defensiveWindow.d.ts +5 -0
  26. package/dist/combat/effects.d.ts +24 -0
  27. package/dist/combat/effects.js +6 -1
  28. package/dist/combat/projectiles.d.ts +6 -0
  29. package/dist/combat/projectiles.js +2 -2
  30. package/dist/combat/regenShield.d.ts +40 -2
  31. package/dist/combat/regenShield.js +66 -18
  32. package/dist/combat/resourcePool.d.ts +19 -0
  33. package/dist/combat/resourcePool.js +20 -2
  34. package/dist/combat/shotOrigin.d.ts +5 -0
  35. package/dist/combat/statusApplication.d.ts +1 -1
  36. package/dist/combat/statusApplication.js +2 -1
  37. package/dist/combat/statusEffectView.d.ts +56 -0
  38. package/dist/combat/statusEffectView.js +52 -0
  39. package/dist/combat.d.ts +4 -2
  40. package/dist/combat.js +2 -0
  41. package/dist/devtools/fallbackSeams.d.ts +3 -2
  42. package/dist/devtools/fallbackSeams.js +1 -1
  43. package/dist/devtools/textureErrors.d.ts +40 -0
  44. package/dist/devtools/textureErrors.js +68 -0
  45. package/dist/economy/shopStock.d.ts +110 -0
  46. package/dist/economy/shopStock.js +157 -0
  47. package/dist/economy/wallet.d.ts +6 -0
  48. package/dist/economy/wallet.js +1 -0
  49. package/dist/game/achievements.d.ts +80 -0
  50. package/dist/game/achievements.js +124 -0
  51. package/dist/game/cameraConfig.d.ts +7 -0
  52. package/dist/game/codex.d.ts +60 -0
  53. package/dist/game/codex.js +89 -0
  54. package/dist/game/credits.d.ts +36 -0
  55. package/dist/game/credits.js +0 -0
  56. package/dist/game/defineGame.d.ts +28 -3
  57. package/dist/game/defineGame.js +5 -0
  58. package/dist/game/dialogueGraph.d.ts +116 -0
  59. package/dist/game/dialogueGraph.js +103 -0
  60. package/dist/game/eventTicker.d.ts +95 -0
  61. package/dist/game/eventTicker.js +91 -0
  62. package/dist/game/events.d.ts +24 -5
  63. package/dist/game/events.js +18 -0
  64. package/dist/game/gamePhase.d.ts +1 -1
  65. package/dist/game/gamePhase.js +1 -1
  66. package/dist/game/leaderboardRank.d.ts +71 -0
  67. package/dist/game/leaderboardRank.js +76 -0
  68. package/dist/game/lootTable.d.ts +10 -1
  69. package/dist/game/lootTable.js +4 -2
  70. package/dist/game/notifications.d.ts +57 -0
  71. package/dist/game/notifications.js +107 -0
  72. package/dist/game/playableGame.d.ts +39 -2
  73. package/dist/game/quest.d.ts +26 -0
  74. package/dist/game/quest.js +31 -0
  75. package/dist/game/runDraft.js +2 -1
  76. package/dist/game/saveSlots.d.ts +102 -0
  77. package/dist/game/saveSlots.js +136 -0
  78. package/dist/game/talentTreeView.d.ts +106 -0
  79. package/dist/game/talentTreeView.js +114 -0
  80. package/dist/game/worldItem.js +2 -1
  81. package/dist/gameplay.d.ts +15 -4
  82. package/dist/gameplay.js +13 -2
  83. package/dist/i18n/i18n.d.ts +51 -0
  84. package/dist/i18n/i18n.js +82 -0
  85. package/dist/input/axisInput.d.ts +1 -1
  86. package/dist/input/axisInput.js +18 -2
  87. package/dist/input/rebindSession.d.ts +141 -0
  88. package/dist/input/rebindSession.js +235 -0
  89. package/dist/input/touchControlsMode.d.ts +16 -0
  90. package/dist/input/touchControlsMode.js +23 -0
  91. package/dist/input/touchScheme.d.ts +30 -1
  92. package/dist/input/touchScheme.js +31 -1
  93. package/dist/interaction/promptRegistry.d.ts +78 -0
  94. package/dist/interaction/promptRegistry.js +130 -0
  95. package/dist/inventory/storageTier.js +3 -2
  96. package/dist/meta/changelog.d.ts +1 -1
  97. package/dist/meta/changelog.js +145 -1
  98. package/dist/movement/movementModel.d.ts +26 -3
  99. package/dist/movement/movementModel.js +121 -15
  100. package/dist/movement/playerMovement.js +161 -25
  101. package/dist/physics/drivableVehicle.js +3 -1
  102. package/dist/physics/kinematicVehicle.d.ts +56 -1
  103. package/dist/physics/kinematicVehicle.js +99 -10
  104. package/dist/physics/vehicleObstacles.js +19 -0
  105. package/dist/random/resolveRng.d.ts +14 -0
  106. package/dist/random/resolveRng.js +31 -0
  107. package/dist/render/postProcessing.d.ts +12 -1
  108. package/dist/runtime/cameraDirector.d.ts +2 -2
  109. package/dist/runtime/context/combat.js +8 -0
  110. package/dist/runtime/gameContext.js +6 -1
  111. package/dist/runtime/gameContextTypes.d.ts +18 -0
  112. package/dist/runtime/inputSnapshot.d.ts +10 -1
  113. package/dist/runtime/inputSnapshot.js +13 -1
  114. package/dist/runtime/runtimeSave.d.ts +3 -3
  115. package/dist/runtime/runtimeSave.js +11 -2
  116. package/dist/scene/assetDiagnostics.js +2 -2
  117. package/dist/scene/autoTarget.js +2 -1
  118. package/dist/scene/captureCheck.js +3 -2
  119. package/dist/scene/entityStore.d.ts +4 -1
  120. package/dist/scene/entityStore.js +3 -0
  121. package/dist/scene/objectStore.d.ts +10 -0
  122. package/dist/scene/objectStore.js +29 -6
  123. package/dist/scene/sceneKinds.d.ts +18 -0
  124. package/dist/scene/sceneKinds.js +19 -0
  125. package/dist/scene/sequenceDirector.d.ts +110 -0
  126. package/dist/scene/sequenceDirector.js +146 -0
  127. package/dist/session/roles.js +3 -2
  128. package/dist/settings/settingsModel.d.ts +1 -0
  129. package/dist/settings/settingsModel.js +1 -0
  130. package/dist/stats/rollCheck.js +4 -2
  131. package/dist/time/dayNightCycle.d.ts +114 -0
  132. package/dist/time/dayNightCycle.js +208 -0
  133. package/dist/time/timerSet.d.ts +132 -0
  134. package/dist/time/timerSet.js +243 -0
  135. package/dist/ui/accessibility.d.ts +51 -0
  136. package/dist/ui/accessibility.js +83 -0
  137. package/dist/ui/coachMarks.d.ts +99 -0
  138. package/dist/ui/coachMarks.js +126 -0
  139. package/dist/ui/floatingText.d.ts +114 -0
  140. package/dist/ui/floatingText.js +203 -0
  141. package/dist/ui/modalStack.d.ts +143 -0
  142. package/dist/ui/modalStack.js +160 -0
  143. package/dist/ui/objectiveBanner.d.ts +123 -0
  144. package/dist/ui/objectiveBanner.js +162 -0
  145. package/dist/ui/photoMode.d.ts +32 -0
  146. package/dist/ui/photoMode.js +51 -0
  147. package/dist/ui/radialMenu.d.ts +47 -0
  148. package/dist/ui/radialMenu.js +74 -0
  149. package/dist/ui/screenMarkers.d.ts +128 -0
  150. package/dist/ui/screenMarkers.js +118 -0
  151. package/dist/ui.d.ts +8 -0
  152. package/dist/ui.js +8 -0
  153. package/dist/vfx/cameraShake.d.ts +97 -0
  154. package/dist/vfx/cameraShake.js +136 -0
  155. package/dist/vfx/damageDirection.d.ts +102 -0
  156. package/dist/vfx/damageDirection.js +188 -0
  157. package/dist/vfx/particles.d.ts +103 -0
  158. package/dist/vfx/particles.js +256 -0
  159. package/dist/vfx/screenEffects.d.ts +149 -0
  160. package/dist/vfx/screenEffects.js +191 -0
  161. package/dist/world/authoredObjects.d.ts +18 -0
  162. package/dist/world/authoredObjects.js +21 -0
  163. package/dist/world/authoredSpawn.js +19 -0
  164. package/dist/world/buildingLots.d.ts +54 -11
  165. package/dist/world/buildingLots.js +116 -30
  166. package/dist/world/cityBlocks.d.ts +45 -0
  167. package/dist/world/cityBlocks.js +159 -0
  168. package/dist/world/cityContent.d.ts +46 -2
  169. package/dist/world/cityContent.js +160 -2
  170. package/dist/world/cityGenerator.d.ts +261 -23
  171. package/dist/world/cityGenerator.js +643 -33
  172. package/dist/world/cityGeometry.d.ts +20 -0
  173. package/dist/world/cityGeometry.js +91 -0
  174. package/dist/world/cityKind.js +1 -44
  175. package/dist/world/fastTravel.d.ts +64 -0
  176. package/dist/world/fastTravel.js +108 -0
  177. package/dist/world/features.d.ts +16 -0
  178. package/dist/world/features.js +2 -0
  179. package/dist/world/grounded.d.ts +11 -0
  180. package/dist/world/grounded.js +12 -0
  181. package/dist/world/mapAnnotations.d.ts +75 -0
  182. package/dist/world/mapAnnotations.js +139 -0
  183. package/dist/world/markers.js +1 -0
  184. package/dist/world/resourceNode.d.ts +1 -1
  185. package/dist/world/resourceNode.js +2 -1
  186. package/dist/world/roads.d.ts +294 -5
  187. package/dist/world/roads.js +1262 -21
  188. package/dist/world/sharedAnnotations.d.ts +84 -0
  189. package/dist/world/sharedAnnotations.js +76 -0
  190. package/dist/world/spawnOverride.d.ts +37 -0
  191. package/dist/world/spawnOverride.js +50 -0
  192. package/dist/world/streetGenerator.d.ts +60 -11
  193. package/dist/world/streetGenerator.js +1786 -129
  194. package/dist/world/terrain.d.ts +1 -0
  195. package/dist/world/terrain.js +2 -0
  196. package/dist/world/waypoints.d.ts +63 -0
  197. package/dist/world/waypoints.js +137 -0
  198. package/dist/world.d.ts +17 -2
  199. package/dist/world.js +17 -2
  200. package/package.json +1 -1
  201. package/skills/ce-handoff/SKILL.md +149 -0
  202. package/skills/game-design/SKILL.md +2 -0
  203. package/skills/jgengine/SKILL.md +3 -1
  204. package/skills/jgengine/api.md +17 -7
  205. package/skills/jgengine/capabilities.md +12 -0
  206. package/skills/jgengine/recipes/minimal-game.md +7 -4
  207. package/skills/jgengine-combat/api.md +40 -4
  208. package/skills/jgengine-combat/capabilities.md +12 -0
  209. package/skills/jgengine-combat/reference.md +2 -0
  210. package/skills/jgengine-gameplay/api.md +212 -11
  211. package/skills/jgengine-gameplay/capabilities.md +66 -1
  212. package/skills/jgengine-world/api.md +397 -11
  213. package/skills/jgengine-world/capabilities.md +123 -2
  214. package/skills/jgengine-world/reference.md +15 -1
@@ -15,9 +15,39 @@ export interface RoadRibbon {
15
15
  * @internal — the corner-smoothing behind `<AuthoredPaths>`; games get it for free through the render.
16
16
  */
17
17
  export declare function roundPathCorners(points: readonly RoadPoint[], radius: number, cornerSegments?: number): RoadPoint[];
18
+ /**
19
+ * The single owning table of ground-decal Y offsets, in world units above the sampled terrain.
20
+ *
21
+ * Contract — the vertical stacking order is `terrain < road < junction < marking < glow`, and every
22
+ * ground overlay must draw from THIS table rather than picking a local magic epsilon (the old
23
+ * scatter of `0.08` ribbons, `+0.02` discs, `0.05` markings, `0.055–0.1` playground fudge factors
24
+ * is exactly the z-fighting this removes).
25
+ *
26
+ * - `road` and `junction` deliberately share one layer: {@link buildJunctionSurface} welds its
27
+ * boundary vertices onto the exact corner vertices where the trimmed ribbon ends
28
+ * ({@link trimPathAtJunctions}), so the two surfaces meet at a shared seam and never stack — they
29
+ * must sit at the same height or the seam would tear. Do NOT bump `junction` above `road`.
30
+ * - `marking` is the ONLY permitted coplanar overlay (lane paint sits on top of asphalt at the same
31
+ * XZ). Its Y separation alone is not enough to beat depth precision on sloped ground: consumers
32
+ * rendering markings MUST ALSO set a negative `polygonOffset` and/or a higher `renderOrder` on the
33
+ * marking material (renderer-side — this table only owns the Y term).
34
+ * - `glow` sits above markings for emissive decals (crosswalk glow, selection halos).
35
+ *
36
+ * Values are chosen with real separation so a small terrain slope can't invert the order.
37
+ */
38
+ export declare const GROUND_DECAL_LAYERS: {
39
+ /** Road ribbons. */
40
+ readonly road: 0.06;
41
+ /** Junction surfaces — SAME layer as `road` because they are seam-welded, never stacked. */
42
+ readonly junction: 0.06;
43
+ /** Lane markings / crosswalks — the only coplanar overlay; also set polygonOffset/renderOrder. */
44
+ readonly marking: 0.11;
45
+ /** Emissive decals above markings (glow, halos). */
46
+ readonly glow: 0.14;
47
+ };
18
48
  /** Options for {@link buildRoadRibbon}. */
19
49
  export interface RoadRibbonOptions {
20
- /** Lift above the sampled ground so the ribbon never z-fights the terrain. Default 0.08. */
50
+ /** Lift above the sampled ground so the ribbon never z-fights the terrain. Default {@link GROUND_DECAL_LAYERS}.road. */
21
51
  elevation?: number;
22
52
  /** Longest centerline step before the polyline is subdivided to drape over relief. Default 4. */
23
53
  maxSegmentLength?: number;
@@ -35,10 +65,14 @@ export interface DashExclusion {
35
65
  radius: number;
36
66
  }
37
67
  /**
38
- * Build a flat, ground-draped disc patch centered on `center` — the welded junction surface that
39
- * covers crossing road ribbons so they read as one intersection instead of stacking/z-fighting.
40
- * A triangle fan of `segments` sides (default 16), every vertex draped at `sampleHeight + elevation`.
41
- * Pure geometry; the shell meshes the result with the asphalt material.
68
+ * Build a flat, ground-draped disc patch centered on `center` — a triangle fan of `segments` sides
69
+ * (default 16), every vertex draped at `sampleHeight + elevation`.
70
+ *
71
+ * @deprecated This floats a disc slightly above the crossing ribbons, which still overlaps and
72
+ * z-fights them. Prefer {@link buildJunctionSurface} (with {@link trimPathAtJunctions}, or the
73
+ * all-in-one {@link buildTrimmedIntersections}): it trims the ribbons back to the junction boundary
74
+ * and welds one seam-shared surface, with no overlap and no floating disc. Kept so existing callers
75
+ * don't break this round.
42
76
  */
43
77
  export declare function buildJunctionPatch(center: RoadPoint, radius: number, sampleHeight: (x: number, z: number) => number, options?: {
44
78
  elevation?: number;
@@ -70,3 +104,258 @@ export declare function nearestOnPath(path: readonly RoadPoint[], x: number, z:
70
104
  export declare function isOnRoad(path: readonly RoadPoint[], width: number, x: number, z: number): boolean;
71
105
  /** Total arc length of a centerline in world units. */
72
106
  export declare function pathLength(path: readonly RoadPoint[]): number;
107
+ /**
108
+ * The minimal junction shape this geometry needs — a node position plus its outgoing arms. Matches
109
+ * the structural subset of `StreetJunction` (streetGenerator) so a network's `junctions` can be fed
110
+ * straight in. Arm `angle` follows the generator convention `atan2(dx, dz)`, i.e. the outward unit
111
+ * direction of an arm is `[sin(angle), cos(angle)]`.
112
+ */
113
+ export interface RoadJunctionInput {
114
+ x: number;
115
+ z: number;
116
+ arms: readonly {
117
+ angle: number;
118
+ width: number;
119
+ }[];
120
+ }
121
+ /** Tunables shared by {@link trimPathAtJunctions}, {@link buildJunctionSurface}, and {@link buildTrimmedIntersections}. */
122
+ export interface JunctionGeometryOptions {
123
+ /**
124
+ * Requested curb-return radius at exterior corners between adjacent approaches. Default 2.
125
+ * Clamped per corner by the two adjacent road widths, the corner chord, and available mouth gap —
126
+ * never inflates the paved conflict area the way an apron pull-back would.
127
+ */
128
+ curbReturnRadius?: number;
129
+ /**
130
+ * Extra clearance beyond the projected crossing half-width so ribbons stop just outside the
131
+ * carriageway union. Default 0.25. Does **not** include the curb-return radius (returns live only
132
+ * on the exterior corner arcs).
133
+ */
134
+ apronMargin?: number;
135
+ /** Samples per curb-return fillet arc between two adjacent approach corners. Default 4. */
136
+ filletSegments?: number;
137
+ /** Lift above sampled ground. Defaults to {@link GROUND_DECAL_LAYERS}.junction (== road: seam-shared). */
138
+ elevation?: number;
139
+ /** Longest step before draping subdivision, matching {@link buildRoadRibbon}. Default 4. */
140
+ maxSegmentLength?: number;
141
+ /** World-space tolerance for matching a path vertex onto a junction node. Default 1e-6. */
142
+ nodeEpsilon?: number;
143
+ }
144
+ /** One trim of a ribbon end back to a junction boundary — the seam the welded surface attaches to. */
145
+ export interface RoadCut {
146
+ /** Index (into the `junctions` array passed to the trimmer) of the junction this cut welds to. */
147
+ junctionIndex: number;
148
+ /** Whether the cut is at the start or the end of the returned sub-path. */
149
+ at: "start" | "end";
150
+ /** Trimmed centerline endpoint — the point on the junction boundary the ribbon now ends at. */
151
+ center: RoadPoint;
152
+ /** Unit direction pointing from the junction center outward into the road. */
153
+ direction: readonly [number, number];
154
+ /** Left edge corner at the cut (`center` + width/2 along the local perpendicular). */
155
+ left: RoadPoint;
156
+ /** Right edge corner at the cut (`center` − width/2 along the local perpendicular). */
157
+ right: RoadPoint;
158
+ /** Arc-length the ribbon was pulled back from the junction center. */
159
+ apron: number;
160
+ }
161
+ /** A street sub-path after trimming, plus the cuts (0–2) that shortened it. Feed `path` to {@link buildRoadRibbon}. */
162
+ export interface TrimmedRoad {
163
+ /** Trimmed centerline (≥2 points) ready for meshing. */
164
+ path: RoadPoint[];
165
+ /** Cuts applied to this sub-path — at most one `start` and one `end`. */
166
+ cuts: RoadCut[];
167
+ }
168
+ /**
169
+ * Cut a street centerline back from the junctions it passes through so its ribbon ENDS at the
170
+ * junction boundary instead of ploughing through the node. Junctions are matched to path vertices
171
+ * within `nodeEpsilon` (endpoints and interior vertices alike); a junction sitting on an interior
172
+ * vertex SPLITS the path into two independently-trimmed sub-paths. Each cut records the exact
173
+ * boundary point and the road's left/right edge corners there, so {@link buildJunctionSurface} can
174
+ * weld its polygon onto the identical vertices with no overlap.
175
+ *
176
+ * Pure geometry, allocation-aware, bounded by the vertex and junction counts. Returns one
177
+ * {@link TrimmedRoad} per surviving sub-path (a mid-polyline junction yields two).
178
+ */
179
+ export declare function trimPathAtJunctions(path: readonly RoadPoint[], width: number, junctions: readonly RoadJunctionInput[], options?: JunctionGeometryOptions): TrimmedRoad[];
180
+ /** Options for {@link trimBandAtJunctions} — junction geometry tunables plus a band-specific clearance. */
181
+ export interface BandTrimOptions extends JunctionGeometryOptions {
182
+ /** Extra outward clearance added to every junction's apron radius before cutting the band. Default 0. */
183
+ clearance?: number;
184
+ }
185
+ /**
186
+ * Cut an offset band (a polyline running PARALLEL to a street — e.g. a sidewalk from
187
+ * `Street.sidewalks.{left,right}`) out of every junction's apron, so the band stops at the crossing
188
+ * instead of sailing straight through it. Unlike {@link trimPathAtJunctions} the band never passes
189
+ * through a node, so it is clipped by DISTANCE: each junction contributes a circular apron of radius
190
+ * `max arm half-width + apronMargin + bandWidth/2 + clearance` (plus a small curb-return allowance),
191
+ * and any part of the band inside any apron circle is removed, splitting the band into the sub-paths
192
+ * that survive outside. Entry/exit points land exactly on the apron boundary. A band that never
193
+ * enters an apron passes through as a single untouched copy.
194
+ *
195
+ * Pure geometry, deterministic, bounded by the band-vertex and junction counts.
196
+ *
197
+ * @example
198
+ * ```ts
199
+ * // Same `junctions` you fed the roads; trim both sidewalks of a street around every node.
200
+ * const left = trimBandAtJunctions(street.sidewalks.left, street.sidewalkWidth, junctions);
201
+ * const right = trimBandAtJunctions(street.sidewalks.right, street.sidewalkWidth, junctions);
202
+ * for (const sub of [...left, ...right]) meshes.push(buildRoadRibbon(sub, street.sidewalkWidth, sampleHeight));
203
+ * ```
204
+ *
205
+ * @capability world-intersections trim offset sidewalk/parallel bands around junction aprons
206
+ */
207
+ export declare function trimBandAtJunctions(bandPath: readonly RoadPoint[], bandWidth: number, junctions: readonly RoadJunctionInput[], options?: BandTrimOptions): RoadPoint[][];
208
+ /** One approach feeding {@link buildJunctionSurface}: the exact draped corner vertices a ribbon ends at. */
209
+ export interface JunctionApproach {
210
+ /** Junction-boundary centerline point where the ribbon ends. */
211
+ center: RoadPoint;
212
+ /** Left edge corner (draped `[x, y, z]`) — the ribbon's terminal left vertex. */
213
+ left: readonly [number, number, number];
214
+ /** Right edge corner (draped `[x, y, z]`) — the ribbon's terminal right vertex. */
215
+ right: readonly [number, number, number];
216
+ /** Unit direction from the node into this approach. Present on approaches emitted by {@link buildTrimmedIntersections}. */
217
+ direction?: readonly [number, number];
218
+ /** Unit tangent in the source street's authored path order. */
219
+ sourceTangent?: readonly [number, number];
220
+ /** Source street index, so consumers never have to infer identity from rendered vertices. */
221
+ streetIndex?: number;
222
+ /** Source trimmed-ribbon index, parallel to {@link TrimmedIntersections.trimmed}. */
223
+ trimmedIndex?: number;
224
+ /** Which end of the source trimmed path meets this junction. */
225
+ cutAt?: "start" | "end";
226
+ /** Full pavement width at this mouth. */
227
+ width?: number;
228
+ /** Sidewalk widths attached to the source path's left and right pavement edges. */
229
+ sidewalkWidths?: IntersectionSidewalkWidths;
230
+ /** Lane-paint declaration inherited from the source street. */
231
+ markings?: IntersectionMarkingIntent;
232
+ }
233
+ /**
234
+ * Build a tangent-continuous centerline through a two-arm junction. This is the shared path for
235
+ * paint, medians, curbs, or other linear dressing that should follow a bend but stop at crossings.
236
+ * Returns `null` for anything other than exactly two approaches.
237
+ * @capability world-intersections connect linear road dressing through two-arm bends
238
+ */
239
+ export declare function buildJunctionConnector(junction: {
240
+ x: number;
241
+ z: number;
242
+ }, approaches: readonly JunctionApproach[], segments?: number): RoadPoint[] | null;
243
+ /**
244
+ * Weld one triangulated junction surface onto the corner vertices its incident ribbons END at
245
+ * (from {@link trimPathAtJunctions}). Corners are grouped by approach (so unequal widths cannot
246
+ * interleave a neighbour between a mouth pair), ordered around the node, and bridged as follows:
247
+ *
248
+ * - **Road mouth** — the straight end-edge of the approach (shared seam with the ribbon).
249
+ * - **Through edge (~180°)** — straight chord along the continuing curb (T-junction far side).
250
+ * - **Exterior corner** — a compact circular curb-return of radius ≤ `curbReturnRadius`, clamped by
251
+ * adjacent widths and chord length; bows *outward* only, never a plaza disc.
252
+ * - **Two-arm turn** — both edges get the same compact returns (no diagonal cap, no remote tangent).
253
+ *
254
+ * The boundary is ear-clipped so every triangle faces +Y. Draped height matches
255
+ * {@link buildRoadRibbon}. Mouth corners are the approach corners verbatim.
256
+ */
257
+ export declare function buildJunctionSurface(junction: {
258
+ x: number;
259
+ z: number;
260
+ }, approaches: readonly JunctionApproach[], sampleHeight: (x: number, z: number) => number, options?: JunctionGeometryOptions): RoadRibbon;
261
+ /** Widths of renderer-neutral sidewalk bands on each authored side of a street. */
262
+ export interface IntersectionSidewalkWidths {
263
+ /** Width beyond the left pavement edge. Omit or use zero for no band. */
264
+ left?: number;
265
+ /** Width beyond the right pavement edge. Omit or use zero for no band. */
266
+ right?: number;
267
+ }
268
+ /** One longitudinal lane-marking ribbon, offset left (+) or right (-) from the authored centerline. */
269
+ export interface IntersectionMarkingLine {
270
+ /** Signed centerline offset in world units. Default 0. */
271
+ offset?: number;
272
+ /** Paint width. Default 0.15. */
273
+ width?: number;
274
+ }
275
+ /** Paint intent carried through trimming without renderer inference. */
276
+ export interface IntersectionMarkingIntent {
277
+ /** Longitudinal marking ribbons. */
278
+ lines?: readonly IntersectionMarkingLine[];
279
+ /** Emit a transverse stop line at this street's multi-arm approaches. Default false. */
280
+ stopLine?: boolean;
281
+ }
282
+ /** One street to trim + mesh through {@link buildTrimmedIntersections}. */
283
+ export interface IntersectionStreet {
284
+ /** Street centerline; endpoints/vertices coincide with junction nodes. */
285
+ path: readonly RoadPoint[];
286
+ /** Full road width. */
287
+ width: number;
288
+ /** Optional, independently-sized bands beyond the authored left/right pavement edges. */
289
+ sidewalks?: IntersectionSidewalkWidths;
290
+ /** Optional lane-paint declaration. Omission preserves the previous pavement-only output. */
291
+ markings?: IntersectionMarkingIntent;
292
+ }
293
+ /** Renderer-ready output of {@link buildTrimmedIntersections}: trimmed ribbons + welded junction surfaces. */
294
+ export interface TrimmedIntersections {
295
+ /** One trimmed ribbon per surviving sub-path (a through-street contributes two). */
296
+ ribbons: RoadRibbon[];
297
+ /** The trimmed sub-paths, parallel to `ribbons`, for lane markings / analysis. */
298
+ trimmed: TrimmedRoad[];
299
+ /** One welded surface per junction that had ≥1 incident approach. */
300
+ junctions: RoadRibbon[];
301
+ /** Index into the input `junctions` for each surface, parallel to `junctions` above. */
302
+ junctionIndices: number[];
303
+ /** Exact ribbon-mouth approaches for each surface, parallel to `junctions`; useful for dressing. */
304
+ junctionApproaches: JunctionApproach[][];
305
+ /** Source street index for each entry in `trimmed`/`ribbons`. */
306
+ trimmedStreetIndices: number[];
307
+ /** Source pavement width for each entry in `trimmed`/`ribbons`. */
308
+ trimmedWidths: number[];
309
+ /** Source paint intent for each entry in `trimmed`/`ribbons`. */
310
+ trimmedMarkings: (IntersectionMarkingIntent | undefined)[];
311
+ /** Road-side sidewalk bands, excluding junction interiors. */
312
+ sidewalks: RoadRibbon[];
313
+ /** Sidewalk curb-return aprons around junction pavement; road-mouth edges and center fill are absent. */
314
+ sidewalkAprons: RoadRibbon[];
315
+ /** Input junction index for each entry in `sidewalkAprons`. */
316
+ sidewalkApronJunctionIndices: number[];
317
+ }
318
+ /**
319
+ * Trim a set of streets against a set of junctions and weld the crossing surfaces in one call — the
320
+ * ergonomic entry the shell/playground consume for meshing.
321
+ *
322
+ * Each street is trimmed by {@link trimPathAtJunctions} (through-streets split in two), each surviving
323
+ * sub-path is meshed with {@link buildRoadRibbon}, and every junction that any ribbon actually ends
324
+ * at gets one {@link buildJunctionSurface}. The junction's boundary vertices are read back BITWISE
325
+ * from the ribbons' terminal cross-sections, so ribbon and surface share the exact same floats at
326
+ * the seam — no overlap, no z-fighting, no floating disc. Ribbons and surfaces both live on the
327
+ * seam-shared {@link GROUND_DECAL_LAYERS}.road/.junction layer. Deterministic (junctions emitted in
328
+ * ascending index order) and bounded by the street/junction counts.
329
+ *
330
+ * @capability world-intersections trim streets at junctions and weld curb-return crossing surfaces in one call
331
+ */
332
+ export declare function buildTrimmedIntersections(streets: readonly IntersectionStreet[], junctions: readonly RoadJunctionInput[], sampleHeight: (x: number, z: number) => number, options?: JunctionGeometryOptions): TrimmedIntersections;
333
+ /** Tunables for {@link buildIntersectionMarkings}. */
334
+ export interface IntersectionMarkingOptions {
335
+ /** Clearance between a multi-arm road mouth and longitudinal paint / stop lines. Default 1. */
336
+ mouthClearance?: number;
337
+ /** Default longitudinal paint width. Default 0.15. */
338
+ lineWidth?: number;
339
+ /** Transverse stop-line width along the approach. Default 0.35. */
340
+ stopLineWidth?: number;
341
+ /** Gap left between a stop line and each pavement edge. Default 0.5. */
342
+ stopLineEdgeClearance?: number;
343
+ /** Samples in a degree-2 marking connector. Default 8. */
344
+ connectorSegments?: number;
345
+ /** Painted dash length. Omit or use zero for a solid line. */
346
+ dashLength?: number;
347
+ /** Gap between painted dashes. Default 3 when `dashLength` is positive. */
348
+ dashGap?: number;
349
+ /** Marking lift above terrain. Default {@link GROUND_DECAL_LAYERS}.marking. */
350
+ elevation?: number;
351
+ /** Longest draping step. Default 4. */
352
+ maxSegmentLength?: number;
353
+ }
354
+ /**
355
+ * Mesh the paint declared on streets passed to {@link buildTrimmedIntersections}. Longitudinal
356
+ * ribbons follow the trimmed road paths. At degree-2 nodes corresponding lines are joined by a
357
+ * tangent-continuous cubic (signed offsets are preserved); at multi-arm nodes lines deliberately
358
+ * stop short of the mouth and optional transverse stop lines make that termination readable.
359
+ * @capability world-intersections connect sidewalks and lane guidance through generated intersections
360
+ */
361
+ export declare function buildIntersectionMarkings(intersections: TrimmedIntersections, sampleHeight: (x: number, z: number) => number, options?: IntersectionMarkingOptions): RoadRibbon[];