@jgengine/core 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (727) hide show
  1. package/CHANGELOG.md +39 -2
  2. package/LICENSE +203 -661
  3. package/README.md +1 -1
  4. package/dist/ai/crowd.d.ts +55 -0
  5. package/dist/ai/crowd.js +114 -0
  6. package/dist/ai/flock.d.ts +5 -2
  7. package/dist/ai/flock.js +5 -2
  8. package/dist/ai/groupAssist.d.ts +1 -0
  9. package/dist/ai/groupAssist.js +1 -0
  10. package/dist/ai/heatSystem.d.ts +76 -0
  11. package/dist/ai/heatSystem.js +97 -0
  12. package/dist/ai/interestScheduler.d.ts +107 -0
  13. package/dist/ai/interestScheduler.js +118 -0
  14. package/dist/ai/jobBoard.d.ts +1 -0
  15. package/dist/ai/jobBoard.js +1 -0
  16. package/dist/ai/laneSelect.d.ts +5 -2
  17. package/dist/ai/laneSelect.js +5 -2
  18. package/dist/ai/mobBrain.d.ts +1 -0
  19. package/dist/ai/mobBrain.js +1 -0
  20. package/dist/ai/populationDirector.d.ts +103 -0
  21. package/dist/ai/populationDirector.js +190 -0
  22. package/dist/ai/pursuit.d.ts +56 -0
  23. package/dist/ai/pursuit.js +53 -0
  24. package/dist/ai/spawnDirector.d.ts +7 -2
  25. package/dist/ai/spawnDirector.js +18 -15
  26. package/dist/ai/spawnPoint.d.ts +3 -1
  27. package/dist/ai/spawnPoint.js +3 -1
  28. package/dist/ai/targetAcquisition.d.ts +84 -0
  29. package/dist/ai/targetAcquisition.js +92 -0
  30. package/dist/anim/easing.d.ts +19 -0
  31. package/dist/anim/easing.js +19 -0
  32. package/dist/anim/oscillator.d.ts +12 -0
  33. package/dist/anim/oscillator.js +25 -0
  34. package/dist/area/areaEffectField.d.ts +127 -0
  35. package/dist/area/areaEffectField.js +175 -0
  36. package/dist/area/stackPolicy.d.ts +47 -0
  37. package/dist/area/stackPolicy.js +99 -0
  38. package/dist/authoring.d.ts +2 -1
  39. package/dist/authoring.js +2 -1
  40. package/dist/board/laneBoard.d.ts +13 -0
  41. package/dist/board/laneBoard.js +13 -0
  42. package/dist/board/timelineBoard.d.ts +10 -0
  43. package/dist/board/timelineBoard.js +10 -0
  44. package/dist/combat/abilityKit.d.ts +18 -0
  45. package/dist/combat/abilityKit.js +24 -9
  46. package/dist/combat/animationState.d.ts +5 -0
  47. package/dist/combat/animationState.js +5 -0
  48. package/dist/combat/breakMeters.d.ts +10 -0
  49. package/dist/combat/breakMeters.js +10 -0
  50. package/dist/combat/castRunner.d.ts +5 -0
  51. package/dist/combat/castRunner.js +5 -0
  52. package/dist/combat/comboPoints.d.ts +5 -0
  53. package/dist/combat/comboPoints.js +5 -0
  54. package/dist/combat/comboString.d.ts +5 -0
  55. package/dist/combat/comboString.js +5 -0
  56. package/dist/combat/damageInterceptors.d.ts +192 -0
  57. package/dist/combat/damageInterceptors.js +251 -0
  58. package/dist/combat/damageMatchup.d.ts +68 -0
  59. package/dist/combat/damageMatchup.js +42 -0
  60. package/dist/combat/damageResolution.d.ts +63 -0
  61. package/dist/combat/damageResolution.js +50 -0
  62. package/dist/combat/death.d.ts +7 -1
  63. package/dist/combat/death.js +5 -0
  64. package/dist/combat/deathReason.d.ts +14 -0
  65. package/dist/combat/deathReason.js +1 -0
  66. package/dist/combat/defensiveWindow.d.ts +5 -0
  67. package/dist/combat/defensiveWindow.js +5 -0
  68. package/dist/combat/dotField.d.ts +5 -1
  69. package/dist/combat/dotField.js +5 -1
  70. package/dist/combat/downed.d.ts +5 -0
  71. package/dist/combat/downed.js +5 -0
  72. package/dist/combat/effects.d.ts +5 -0
  73. package/dist/combat/effects.js +5 -0
  74. package/dist/combat/encounterSequence.d.ts +258 -0
  75. package/dist/combat/encounterSequence.js +426 -0
  76. package/dist/combat/hitReaction.d.ts +57 -1
  77. package/dist/combat/hitReaction.js +45 -5
  78. package/dist/combat/magazine.d.ts +54 -0
  79. package/dist/combat/magazine.js +96 -0
  80. package/dist/combat/projectiles.d.ts +5 -0
  81. package/dist/combat/projectiles.js +32 -14
  82. package/dist/combat/receivedDamage.d.ts +117 -0
  83. package/dist/combat/receivedDamage.js +92 -0
  84. package/dist/combat/regenShield.d.ts +5 -1
  85. package/dist/combat/regenShield.js +5 -1
  86. package/dist/combat/renderCues.d.ts +51 -0
  87. package/dist/combat/renderCues.js +44 -0
  88. package/dist/combat/resourcePool.d.ts +5 -0
  89. package/dist/combat/resourcePool.js +5 -0
  90. package/dist/combat/rewardAllocation.d.ts +121 -0
  91. package/dist/combat/rewardAllocation.js +251 -0
  92. package/dist/combat/shotOrigin.d.ts +18 -1
  93. package/dist/combat/shotOrigin.js +39 -0
  94. package/dist/combat/statusApplication.d.ts +96 -0
  95. package/dist/combat/statusApplication.js +81 -0
  96. package/dist/combat/telegraph.d.ts +11 -2
  97. package/dist/combat/telegraph.js +11 -2
  98. package/dist/combat/thresholdCrossings.d.ts +85 -0
  99. package/dist/combat/thresholdCrossings.js +116 -0
  100. package/dist/combat.d.ts +35 -0
  101. package/dist/combat.js +35 -0
  102. package/dist/commands/commandRegistry.d.ts +11 -0
  103. package/dist/commands/commandRegistry.js +9 -2
  104. package/dist/crafting/crop.d.ts +18 -0
  105. package/dist/crafting/crop.js +18 -0
  106. package/dist/crafting/production.d.ts +5 -0
  107. package/dist/crafting/production.js +5 -0
  108. package/dist/devtools/controls.d.ts +38 -0
  109. package/dist/devtools/controls.js +181 -0
  110. package/dist/devtools/devtools.d.ts +5 -197
  111. package/dist/devtools/devtools.js +38 -774
  112. package/dist/devtools/discover.d.ts +32 -0
  113. package/dist/devtools/discover.js +240 -0
  114. package/dist/devtools/fallbackSeams.d.ts +50 -0
  115. package/dist/devtools/fallbackSeams.js +111 -0
  116. package/dist/devtools/frame.d.ts +15 -0
  117. package/dist/devtools/frame.js +247 -0
  118. package/dist/devtools/logs.d.ts +15 -0
  119. package/dist/devtools/logs.js +86 -0
  120. package/dist/devtools/overrides.d.ts +16 -0
  121. package/dist/devtools/overrides.js +66 -0
  122. package/dist/devtools/rewriteTunables.d.ts +17 -0
  123. package/dist/devtools/rewriteTunables.js +276 -0
  124. package/dist/devtools/saveEndpoint.d.ts +46 -0
  125. package/dist/devtools/saveEndpoint.js +48 -0
  126. package/dist/devtools/transformTunables.d.ts +3 -0
  127. package/dist/devtools/transformTunables.js +3 -0
  128. package/dist/devtools/tunableSchema.d.ts +31 -0
  129. package/dist/devtools/tunableSchema.js +31 -0
  130. package/dist/devtools/types.d.ts +212 -0
  131. package/dist/devtools/types.js +1 -0
  132. package/dist/economy/auctionBook.d.ts +122 -0
  133. package/dist/economy/auctionBook.js +213 -0
  134. package/dist/economy/currency.d.ts +12 -1
  135. package/dist/economy/currency.js +12 -1
  136. package/dist/economy/listingBook.d.ts +91 -0
  137. package/dist/economy/listingBook.js +144 -0
  138. package/dist/economy/priceHistory.d.ts +44 -0
  139. package/dist/economy/priceHistory.js +89 -0
  140. package/dist/economy/resourceLedger.d.ts +222 -0
  141. package/dist/economy/resourceLedger.js +353 -0
  142. package/dist/economy/sharedWallet.d.ts +14 -0
  143. package/dist/economy/sharedWallet.js +14 -0
  144. package/dist/economy/techTree.d.ts +12 -0
  145. package/dist/economy/techTree.js +12 -0
  146. package/dist/economy/unlockPoints.d.ts +92 -0
  147. package/dist/economy/unlockPoints.js +103 -0
  148. package/dist/economy/wallet.d.ts +26 -2
  149. package/dist/economy/wallet.js +35 -6
  150. package/dist/editor/commandApply.d.ts +5 -0
  151. package/dist/editor/commandApply.js +755 -0
  152. package/dist/editor/commands.d.ts +235 -7
  153. package/dist/editor/commands.js +82 -124
  154. package/dist/editor/directives.d.ts +94 -0
  155. package/dist/editor/directives.js +206 -0
  156. package/dist/editor/document.d.ts +194 -13
  157. package/dist/editor/document.js +1166 -19
  158. package/dist/editor/entityCatalog.d.ts +42 -0
  159. package/dist/editor/entityCatalog.js +101 -0
  160. package/dist/editor/environment.d.ts +74 -0
  161. package/dist/editor/environment.js +169 -0
  162. package/dist/editor/grid.d.ts +229 -0
  163. package/dist/editor/grid.js +366 -0
  164. package/dist/editor/gridAdapters.d.ts +80 -0
  165. package/dist/editor/gridAdapters.js +134 -0
  166. package/dist/editor/index.d.ts +98 -6
  167. package/dist/editor/index.js +13 -2
  168. package/dist/editor/liveSync.d.ts +127 -0
  169. package/dist/editor/liveSync.js +249 -0
  170. package/dist/editor/minimap.d.ts +31 -0
  171. package/dist/editor/minimap.js +73 -0
  172. package/dist/editor/runtimeInspector.d.ts +88 -0
  173. package/dist/editor/runtimeInspector.js +239 -0
  174. package/dist/editor/streamer.d.ts +66 -0
  175. package/dist/editor/streamer.js +68 -0
  176. package/dist/editor/types.d.ts +250 -1
  177. package/dist/editor/world.d.ts +136 -0
  178. package/dist/editor/world.js +303 -0
  179. package/dist/faction/reputation.d.ts +5 -0
  180. package/dist/faction/reputation.js +5 -0
  181. package/dist/format/distance.d.ts +17 -0
  182. package/dist/format/distance.js +18 -0
  183. package/dist/format/duration.d.ts +27 -0
  184. package/dist/format/duration.js +45 -0
  185. package/dist/format/speed.d.ts +17 -0
  186. package/dist/format/speed.js +25 -0
  187. package/dist/game/breeding.d.ts +161 -0
  188. package/dist/game/breeding.js +181 -0
  189. package/dist/game/cameraConfig.d.ts +451 -0
  190. package/dist/game/cameraConfig.js +1 -0
  191. package/dist/game/connectedPlayers.d.ts +6 -4
  192. package/dist/game/connectedPlayers.js +2 -2
  193. package/dist/game/cosmetics.d.ts +9 -0
  194. package/dist/game/cosmetics.js +16 -0
  195. package/dist/game/defineGame.d.ts +110 -5
  196. package/dist/game/defineGame.js +49 -4
  197. package/dist/game/defineSystem.d.ts +90 -0
  198. package/dist/game/defineSystem.js +47 -0
  199. package/dist/game/dialogue.d.ts +33 -0
  200. package/dist/game/dialogue.js +21 -0
  201. package/dist/game/events.d.ts +63 -13
  202. package/dist/game/events.js +5 -0
  203. package/dist/game/feed.d.ts +33 -0
  204. package/dist/game/feed.js +35 -2
  205. package/dist/game/gamePhase.d.ts +11 -0
  206. package/dist/game/gamePhase.js +16 -0
  207. package/dist/game/leaderboard.d.ts +5 -0
  208. package/dist/game/leaderboard.js +5 -0
  209. package/dist/game/loadout.d.ts +5 -0
  210. package/dist/game/loadout.js +5 -0
  211. package/dist/game/lootFilter.d.ts +2 -0
  212. package/dist/game/lootFilter.js +2 -0
  213. package/dist/game/lootPipeline.d.ts +164 -0
  214. package/dist/game/lootPipeline.js +216 -0
  215. package/dist/game/lootTable.d.ts +19 -2
  216. package/dist/game/lootTable.js +15 -5
  217. package/dist/game/objectives.d.ts +43 -0
  218. package/dist/game/objectives.js +36 -0
  219. package/dist/game/paramLayers.d.ts +148 -0
  220. package/dist/game/paramLayers.js +185 -0
  221. package/dist/game/ping.d.ts +5 -0
  222. package/dist/game/ping.js +5 -0
  223. package/dist/game/playableGame.d.ts +116 -432
  224. package/dist/game/playableGame.js +1 -1
  225. package/dist/game/progression.d.ts +35 -0
  226. package/dist/game/progression.js +19 -0
  227. package/dist/game/quest.d.ts +8 -0
  228. package/dist/game/quest.js +30 -3
  229. package/dist/game/race.d.ts +141 -0
  230. package/dist/game/race.js +169 -0
  231. package/dist/game/recordBook.d.ts +3 -1
  232. package/dist/game/recordBook.js +4 -1
  233. package/dist/game/ruleSelection.d.ts +75 -0
  234. package/dist/game/ruleSelection.js +127 -0
  235. package/dist/game/runDraft.d.ts +5 -0
  236. package/dist/game/runDraft.js +5 -0
  237. package/dist/game/saveStore.d.ts +111 -0
  238. package/dist/game/saveStore.js +312 -0
  239. package/dist/game/snapshotHistory.d.ts +67 -0
  240. package/dist/game/snapshotHistory.js +95 -0
  241. package/dist/game/social.d.ts +38 -1
  242. package/dist/game/social.js +71 -0
  243. package/dist/game/spawnPoints.d.ts +5 -0
  244. package/dist/game/spawnPoints.js +5 -0
  245. package/dist/game/systemRuntime.d.ts +50 -0
  246. package/dist/game/systemRuntime.js +157 -0
  247. package/dist/game/systemSchedule.d.ts +72 -0
  248. package/dist/game/systemSchedule.js +242 -0
  249. package/dist/game/toasts.d.ts +43 -0
  250. package/dist/game/toasts.js +44 -0
  251. package/dist/game/trade.d.ts +10 -0
  252. package/dist/game/trade.js +10 -0
  253. package/dist/game/tribe.d.ts +184 -0
  254. package/dist/game/tribe.js +432 -0
  255. package/dist/game/unlocks.d.ts +8 -0
  256. package/dist/game/unlocks.js +16 -0
  257. package/dist/game/vfxInstance.d.ts +138 -0
  258. package/dist/game/vfxInstance.js +96 -0
  259. package/dist/game/worldItem.d.ts +17 -4
  260. package/dist/game/worldItem.js +17 -4
  261. package/dist/gameplay.d.ts +93 -0
  262. package/dist/gameplay.js +93 -0
  263. package/dist/index.d.ts +5 -14
  264. package/dist/index.js +5 -14
  265. package/dist/input/actionBindings.d.ts +23 -6
  266. package/dist/input/actionBindings.js +23 -6
  267. package/dist/input/axisInput.d.ts +7 -2
  268. package/dist/input/axisInput.js +7 -2
  269. package/dist/input/controlGroups.d.ts +67 -0
  270. package/dist/input/controlGroups.js +41 -0
  271. package/dist/input/touchScheme.d.ts +82 -6
  272. package/dist/input/touchScheme.js +123 -10
  273. package/dist/interaction/lockpick.d.ts +61 -0
  274. package/dist/interaction/lockpick.js +168 -0
  275. package/dist/interaction/proximityPrompt.d.ts +2 -0
  276. package/dist/interaction/proximityPrompt.js +2 -0
  277. package/dist/interaction/qte.d.ts +5 -0
  278. package/dist/interaction/qte.js +5 -0
  279. package/dist/interaction/skillCheck.d.ts +5 -0
  280. package/dist/interaction/skillCheck.js +5 -0
  281. package/dist/inventory/encumbrance.d.ts +69 -0
  282. package/dist/inventory/encumbrance.js +68 -0
  283. package/dist/inventory/inventoryModel.d.ts +12 -0
  284. package/dist/inventory/inventoryModel.js +12 -0
  285. package/dist/inventory/shapedGrid.d.ts +16 -0
  286. package/dist/inventory/shapedGrid.js +16 -0
  287. package/dist/inventory/slotModel.d.ts +10 -0
  288. package/dist/inventory/slotModel.js +10 -0
  289. package/dist/item/durability.d.ts +5 -0
  290. package/dist/item/durability.js +6 -3
  291. package/dist/item/itemIdentity.d.ts +171 -0
  292. package/dist/item/itemIdentity.js +138 -0
  293. package/dist/item/itemInstanceRegistry.d.ts +32 -0
  294. package/dist/item/itemInstanceRegistry.js +34 -0
  295. package/dist/item/itemgen.d.ts +163 -0
  296. package/dist/item/itemgen.js +151 -0
  297. package/dist/item/modularItem.d.ts +5 -0
  298. package/dist/item/modularItem.js +5 -0
  299. package/dist/item/use.d.ts +5 -0
  300. package/dist/item/use.js +5 -0
  301. package/dist/item/useBehavior.d.ts +142 -0
  302. package/dist/item/useBehavior.js +105 -0
  303. package/dist/item/weapon.d.ts +5 -0
  304. package/dist/item/weapon.js +5 -0
  305. package/dist/math/scalar.d.ts +25 -0
  306. package/dist/math/scalar.js +47 -0
  307. package/dist/meta/changelog.d.ts +4 -1
  308. package/dist/meta/changelog.js +39 -2
  309. package/dist/movement/avoidance.d.ts +45 -0
  310. package/dist/movement/avoidance.js +123 -0
  311. package/dist/movement/cameraRig.d.ts +8 -0
  312. package/dist/movement/cameraRig.js +8 -0
  313. package/dist/movement/dash.d.ts +11 -0
  314. package/dist/movement/dash.js +11 -0
  315. package/dist/movement/formation.d.ts +135 -0
  316. package/dist/movement/formation.js +194 -0
  317. package/dist/movement/glideModel.d.ts +5 -0
  318. package/dist/movement/glideModel.js +5 -0
  319. package/dist/movement/grappleSwing.d.ts +5 -0
  320. package/dist/movement/grappleSwing.js +5 -0
  321. package/dist/movement/leaderTrail.d.ts +5 -0
  322. package/dist/movement/leaderTrail.js +5 -0
  323. package/dist/movement/movementModel.d.ts +50 -9
  324. package/dist/movement/movementModel.js +75 -29
  325. package/dist/movement/playerMovement.js +167 -12
  326. package/dist/movement/poseState.d.ts +13 -0
  327. package/dist/movement/poseState.js +16 -0
  328. package/dist/movement/steering.d.ts +8 -0
  329. package/dist/movement/steering.js +18 -0
  330. package/dist/multiplayer/combatSnapshot.d.ts +3 -0
  331. package/dist/multiplayer/combatSnapshot.js +16 -8
  332. package/dist/multiplayer/lagCompensation.d.ts +5 -0
  333. package/dist/multiplayer/lagCompensation.js +5 -0
  334. package/dist/multiplayer/presenceModel.d.ts +11 -1
  335. package/dist/multiplayer/presenceModel.js +17 -1
  336. package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
  337. package/dist/multiplayer/simultaneousCommit.js +3 -0
  338. package/dist/multiplayer.d.ts +11 -0
  339. package/dist/multiplayer.js +11 -0
  340. package/dist/nav/pathFollow.d.ts +57 -0
  341. package/dist/nav/pathFollow.js +109 -0
  342. package/dist/orders/orderKinds.d.ts +156 -0
  343. package/dist/orders/orderKinds.js +197 -0
  344. package/dist/orders/orderQueue.d.ts +208 -0
  345. package/dist/orders/orderQueue.js +211 -0
  346. package/dist/physics/drivableVehicle.d.ts +31 -0
  347. package/dist/physics/drivableVehicle.js +16 -0
  348. package/dist/physics/flightDynamics.d.ts +82 -0
  349. package/dist/physics/flightDynamics.js +165 -0
  350. package/dist/physics/gravityField.d.ts +25 -0
  351. package/dist/physics/gravityField.js +41 -0
  352. package/dist/physics/kinematicVehicle.d.ts +108 -1
  353. package/dist/physics/kinematicVehicle.js +212 -15
  354. package/dist/physics/physicsWorld.d.ts +50 -12
  355. package/dist/physics/physicsWorld.js +120 -122
  356. package/dist/physics/radialImpulse.d.ts +25 -0
  357. package/dist/physics/radialImpulse.js +27 -0
  358. package/dist/physics/vehicleObstacles.d.ts +44 -0
  359. package/dist/physics/vehicleObstacles.js +115 -0
  360. package/dist/procedural.d.ts +3 -0
  361. package/dist/procedural.js +3 -0
  362. package/dist/progression/statGraph.d.ts +116 -0
  363. package/dist/progression/statGraph.js +318 -0
  364. package/dist/puzzle/cellGrid.d.ts +9 -0
  365. package/dist/puzzle/cellGrid.js +9 -0
  366. package/dist/puzzle/fallingPiece.d.ts +9 -0
  367. package/dist/puzzle/fallingPiece.js +9 -0
  368. package/dist/puzzle/nonogram.d.ts +39 -0
  369. package/dist/puzzle/nonogram.js +136 -0
  370. package/dist/random/nameGen.d.ts +5 -0
  371. package/dist/random/nameGen.js +5 -0
  372. package/dist/random/pick.d.ts +8 -0
  373. package/dist/random/pick.js +31 -0
  374. package/dist/random/rng.d.ts +26 -1
  375. package/dist/random/rng.js +32 -9
  376. package/dist/random/seedLink.d.ts +4 -0
  377. package/dist/random/seedLink.js +4 -0
  378. package/dist/relation/keyedValues.d.ts +54 -0
  379. package/dist/relation/keyedValues.js +115 -0
  380. package/dist/relation/thresholds.d.ts +62 -0
  381. package/dist/relation/thresholds.js +62 -0
  382. package/dist/render/color.d.ts +12 -0
  383. package/dist/render/color.js +26 -0
  384. package/dist/render/lookPreset.d.ts +41 -0
  385. package/dist/render/lookPreset.js +29 -0
  386. package/dist/render/postProcessing.d.ts +20 -0
  387. package/dist/render/postProcessing.js +21 -1
  388. package/dist/rules/predicate.d.ts +53 -0
  389. package/dist/rules/predicate.js +64 -0
  390. package/dist/rules/ruleEffects.d.ts +38 -0
  391. package/dist/rules/ruleEffects.js +37 -0
  392. package/dist/rules/triggeredRules.d.ts +160 -0
  393. package/dist/rules/triggeredRules.js +241 -0
  394. package/dist/runtime/adapter.d.ts +55 -3
  395. package/dist/runtime/adapter.js +57 -1
  396. package/dist/runtime/cameraDirector.d.ts +1 -0
  397. package/dist/runtime/cameraDirector.js +1 -0
  398. package/dist/runtime/commandRunner.d.ts +1 -0
  399. package/dist/runtime/commandRunner.js +1 -0
  400. package/dist/runtime/context/combat.d.ts +51 -0
  401. package/dist/runtime/context/combat.js +130 -0
  402. package/dist/runtime/context/combatFx.d.ts +23 -0
  403. package/dist/runtime/context/combatFx.js +161 -0
  404. package/dist/runtime/context/deathLoot.d.ts +30 -0
  405. package/dist/runtime/context/deathLoot.js +39 -0
  406. package/dist/runtime/context/player.d.ts +48 -0
  407. package/dist/runtime/context/player.js +125 -0
  408. package/dist/runtime/context/registries.d.ts +13 -0
  409. package/dist/runtime/context/registries.js +84 -0
  410. package/dist/runtime/context/scene.d.ts +59 -0
  411. package/dist/runtime/context/scene.js +291 -0
  412. package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
  413. package/dist/runtime/context/snapshotCodecs.js +26 -0
  414. package/dist/runtime/context/worldItems.d.ts +21 -0
  415. package/dist/runtime/context/worldItems.js +37 -0
  416. package/dist/runtime/descriptors/baseline.d.ts +48 -0
  417. package/dist/runtime/descriptors/baseline.js +157 -0
  418. package/dist/runtime/descriptors/features.d.ts +79 -0
  419. package/dist/runtime/descriptors/features.js +299 -0
  420. package/dist/runtime/gameContext.d.ts +2 -327
  421. package/dist/runtime/gameContext.js +273 -778
  422. package/dist/runtime/gameContextTypes.d.ts +467 -0
  423. package/dist/runtime/gameContextTypes.js +1 -0
  424. package/dist/runtime/gameRuntime.d.ts +1 -0
  425. package/dist/runtime/gameRuntime.js +1 -0
  426. package/dist/runtime/headlessRunner.d.ts +62 -0
  427. package/dist/runtime/headlessRunner.js +45 -0
  428. package/dist/runtime/hostPersistence.d.ts +12 -0
  429. package/dist/runtime/hostPersistence.js +12 -0
  430. package/dist/runtime/hostPolicy.d.ts +51 -0
  431. package/dist/runtime/hostPolicy.js +68 -0
  432. package/dist/runtime/hostedGameRunner.d.ts +11 -4
  433. package/dist/runtime/hostedGameRunner.js +27 -3
  434. package/dist/runtime/hostedWorldSession.d.ts +15 -5
  435. package/dist/runtime/hostedWorldSession.js +12 -4
  436. package/dist/runtime/inputSnapshot.d.ts +8 -3
  437. package/dist/runtime/inputSnapshot.js +6 -2
  438. package/dist/runtime/motionIntents.d.ts +11 -2
  439. package/dist/runtime/motionIntents.js +16 -2
  440. package/dist/runtime/perContext.d.ts +15 -0
  441. package/dist/runtime/perContext.js +21 -0
  442. package/dist/runtime/runtimeSave.d.ts +79 -0
  443. package/dist/runtime/runtimeSave.js +105 -0
  444. package/dist/runtime/save.d.ts +4 -0
  445. package/dist/runtime/save.js +4 -0
  446. package/dist/runtime/snapshot.d.ts +7 -0
  447. package/dist/runtime/snapshot.js +7 -0
  448. package/dist/runtime/visibility.d.ts +2 -1
  449. package/dist/runtime/visibility.js +2 -1
  450. package/dist/runtime/worldChannel.d.ts +7 -3
  451. package/dist/runtime/worldChannel.js +51 -6
  452. package/dist/runtime/worldMirror.d.ts +14 -2
  453. package/dist/runtime/worldMirror.js +15 -2
  454. package/dist/runtime/worldProjection.d.ts +47 -0
  455. package/dist/runtime/worldProjection.js +52 -0
  456. package/dist/runtime/worldReplication.d.ts +30 -7
  457. package/dist/runtime/worldReplication.js +41 -9
  458. package/dist/runtime/worldSnapshot.d.ts +42 -3
  459. package/dist/runtime/worldSnapshot.js +34 -7
  460. package/dist/scene/assetCatalog.d.ts +26 -0
  461. package/dist/scene/assetCatalog.js +4 -0
  462. package/dist/scene/assetDiagnostics.d.ts +69 -0
  463. package/dist/scene/assetDiagnostics.js +110 -0
  464. package/dist/scene/assetGenerator.d.ts +65 -0
  465. package/dist/scene/assetGenerator.js +64 -0
  466. package/dist/scene/assetSpace.d.ts +137 -0
  467. package/dist/scene/assetSpace.js +257 -0
  468. package/dist/scene/authoredTriggers.d.ts +219 -0
  469. package/dist/scene/authoredTriggers.js +454 -0
  470. package/dist/scene/behaviorRuntime.d.ts +75 -0
  471. package/dist/scene/behaviorRuntime.js +217 -0
  472. package/dist/scene/behaviors.d.ts +14 -2
  473. package/dist/scene/behaviors.js +7 -2
  474. package/dist/scene/bodyBind.d.ts +60 -0
  475. package/dist/scene/bodyBind.js +51 -0
  476. package/dist/scene/builtinSceneKinds.d.ts +5 -0
  477. package/dist/scene/builtinSceneKinds.js +67 -0
  478. package/dist/scene/colliders.d.ts +71 -1
  479. package/dist/scene/colliders.js +145 -1
  480. package/dist/scene/collisionMesh.d.ts +94 -0
  481. package/dist/scene/collisionMesh.js +699 -0
  482. package/dist/scene/companion.d.ts +147 -0
  483. package/dist/scene/companion.js +193 -0
  484. package/dist/scene/entityStats.d.ts +18 -11
  485. package/dist/scene/entityStats.js +21 -16
  486. package/dist/scene/entityStore.d.ts +12 -1
  487. package/dist/scene/entityStore.js +15 -0
  488. package/dist/scene/facing.d.ts +18 -0
  489. package/dist/scene/facing.js +26 -0
  490. package/dist/scene/modelSockets.d.ts +33 -0
  491. package/dist/scene/modelSockets.js +29 -0
  492. package/dist/scene/objectQuery.d.ts +2 -0
  493. package/dist/scene/objectQuery.js +2 -0
  494. package/dist/scene/objectStore.d.ts +4 -0
  495. package/dist/scene/objectStore.js +6 -0
  496. package/dist/scene/possession.d.ts +8 -0
  497. package/dist/scene/possession.js +14 -0
  498. package/dist/scene/roster.d.ts +3 -0
  499. package/dist/scene/roster.js +12 -0
  500. package/dist/scene/sceneKinds.d.ts +256 -0
  501. package/dist/scene/sceneKinds.js +218 -0
  502. package/dist/scene/sceneOwnership.d.ts +169 -0
  503. package/dist/scene/sceneOwnership.js +179 -0
  504. package/dist/scene/sceneRaycast.js +15 -0
  505. package/dist/scene/selectionBookmarks.d.ts +93 -0
  506. package/dist/scene/selectionBookmarks.js +122 -0
  507. package/dist/scene/vehicleSeat.d.ts +68 -0
  508. package/dist/scene/vehicleSeat.js +59 -0
  509. package/dist/sensor/concealment.d.ts +3 -0
  510. package/dist/sensor/concealment.js +3 -0
  511. package/dist/sensor/freezeMonitor.d.ts +1 -0
  512. package/dist/sensor/freezeMonitor.js +1 -0
  513. package/dist/sensor/frustumSensor.d.ts +7 -3
  514. package/dist/sensor/frustumSensor.js +7 -3
  515. package/dist/sensor/hiddenStateProbe.d.ts +5 -2
  516. package/dist/sensor/hiddenStateProbe.js +5 -2
  517. package/dist/sensor/recordingBuffer.d.ts +2 -1
  518. package/dist/sensor/recordingBuffer.js +2 -1
  519. package/dist/sensor/replayLoop.d.ts +6 -2
  520. package/dist/sensor/replayLoop.js +6 -2
  521. package/dist/sensor/revealQuery.d.ts +2 -1
  522. package/dist/sensor/revealQuery.js +2 -1
  523. package/dist/sensor/visionCone.d.ts +10 -3
  524. package/dist/sensor/visionCone.js +10 -3
  525. package/dist/session/contestedChannel.d.ts +1 -0
  526. package/dist/session/contestedChannel.js +1 -0
  527. package/dist/session/extraction.d.ts +1 -0
  528. package/dist/session/extraction.js +1 -0
  529. package/dist/session/roles.d.ts +6 -0
  530. package/dist/session/roles.js +6 -0
  531. package/dist/session/roundState.d.ts +8 -0
  532. package/dist/session/roundState.js +2 -0
  533. package/dist/settings/settingsModel.d.ts +1 -0
  534. package/dist/settings/settingsModel.js +1 -0
  535. package/dist/stats/accumulatorMeter.d.ts +6 -0
  536. package/dist/stats/accumulatorMeter.js +6 -0
  537. package/dist/stats/eventMeter.d.ts +5 -0
  538. package/dist/stats/eventMeter.js +5 -0
  539. package/dist/stats/rollCheck.d.ts +5 -0
  540. package/dist/stats/rollCheck.js +5 -0
  541. package/dist/stats/spawnLevelStats.d.ts +110 -0
  542. package/dist/stats/spawnLevelStats.js +140 -0
  543. package/dist/stats/statModifiers.d.ts +5 -0
  544. package/dist/stats/statModifiers.js +5 -0
  545. package/dist/stats/statPool.d.ts +70 -0
  546. package/dist/stats/statPool.js +59 -0
  547. package/dist/store/changeSignal.d.ts +3 -0
  548. package/dist/store/changeSignal.js +2 -0
  549. package/dist/store/defineKeyedStore.d.ts +38 -0
  550. package/dist/store/defineKeyedStore.js +42 -0
  551. package/dist/store/defineStore.d.ts +33 -0
  552. package/dist/store/defineStore.js +35 -0
  553. package/dist/store/observableKeyedStore.d.ts +7 -0
  554. package/dist/store/observableKeyedStore.js +35 -2
  555. package/dist/survival/decayMeter.d.ts +55 -0
  556. package/dist/survival/decayMeter.js +130 -57
  557. package/dist/survival/moodle.d.ts +2 -0
  558. package/dist/survival/regionHealth.d.ts +6 -0
  559. package/dist/survival/regionHealth.js +6 -3
  560. package/dist/tactics/fallingGrid.d.ts +4 -2
  561. package/dist/tactics/fallingGrid.js +4 -2
  562. package/dist/tactics/predictiveQuery.d.ts +3 -0
  563. package/dist/tactics/predictiveQuery.js +3 -0
  564. package/dist/tactics/snapshot.d.ts +2 -0
  565. package/dist/tactics/snapshot.js +2 -0
  566. package/dist/tactics/surface.d.ts +1 -0
  567. package/dist/tactics/surface.js +1 -0
  568. package/dist/tactics/tacticalGrid.d.ts +1 -0
  569. package/dist/tactics/tacticalGrid.js +1 -0
  570. package/dist/time/beatClock.d.ts +14 -4
  571. package/dist/time/beatClock.js +14 -4
  572. package/dist/time/calendarClock.d.ts +3 -0
  573. package/dist/time/calendarClock.js +3 -0
  574. package/dist/time/idleProgress.d.ts +4 -0
  575. package/dist/time/idleProgress.js +4 -0
  576. package/dist/time/simClock.d.ts +2 -0
  577. package/dist/time/simClock.js +20 -5
  578. package/dist/ui/actionModel.d.ts +110 -0
  579. package/dist/ui/actionModel.js +159 -0
  580. package/dist/ui/gameLayout.d.ts +30 -11
  581. package/dist/ui/gameLayout.js +30 -11
  582. package/dist/ui/hudDocument.d.ts +114 -0
  583. package/dist/ui/hudDocument.js +220 -0
  584. package/dist/ui/hudLayout.d.ts +38 -1
  585. package/dist/ui/hudLayout.js +220 -17
  586. package/dist/ui/selectionModel.d.ts +92 -0
  587. package/dist/ui/selectionModel.js +88 -0
  588. package/dist/ui/tooltipModel.d.ts +63 -0
  589. package/dist/ui/tooltipModel.js +82 -0
  590. package/dist/ui.d.ts +15 -0
  591. package/dist/ui.js +15 -0
  592. package/dist/visibility/bounds.d.ts +8 -1
  593. package/dist/visibility/bounds.js +8 -1
  594. package/dist/visibility/frustum.d.ts +12 -3
  595. package/dist/visibility/frustum.js +12 -3
  596. package/dist/work/jobQueue.d.ts +201 -0
  597. package/dist/work/jobQueue.js +253 -0
  598. package/dist/work/unitTraining.d.ts +58 -0
  599. package/dist/work/unitTraining.js +52 -0
  600. package/dist/world/authoredEntities.d.ts +29 -0
  601. package/dist/world/authoredEntities.js +29 -0
  602. package/dist/world/authoredObjects.d.ts +72 -0
  603. package/dist/world/authoredObjects.js +81 -0
  604. package/dist/world/authoredSpawn.d.ts +39 -0
  605. package/dist/world/authoredSpawn.js +37 -0
  606. package/dist/world/buildSockets.d.ts +152 -0
  607. package/dist/world/buildSockets.js +188 -0
  608. package/dist/world/buildingGenerator.d.ts +18 -0
  609. package/dist/world/buildingGenerator.js +62 -0
  610. package/dist/world/buildings.d.ts +5 -0
  611. package/dist/world/buildings.js +5 -0
  612. package/dist/world/catenary.d.ts +22 -0
  613. package/dist/world/catenary.js +69 -0
  614. package/dist/world/cityBlocks.d.ts +152 -0
  615. package/dist/world/cityBlocks.js +670 -0
  616. package/dist/world/cityContent.d.ts +77 -0
  617. package/dist/world/cityContent.js +261 -0
  618. package/dist/world/cityGeometry.d.ts +114 -0
  619. package/dist/world/cityGeometry.js +573 -0
  620. package/dist/world/cityKind.d.ts +314 -0
  621. package/dist/world/cityKind.js +1578 -0
  622. package/dist/world/features.d.ts +133 -10
  623. package/dist/world/features.js +66 -6
  624. package/dist/world/footprintGrid.d.ts +59 -0
  625. package/dist/world/footprintGrid.js +141 -0
  626. package/dist/world/geometry.d.ts +64 -0
  627. package/dist/world/geometry.js +94 -0
  628. package/dist/world/grassKind.d.ts +51 -0
  629. package/dist/world/grassKind.js +101 -0
  630. package/dist/world/markers.d.ts +50 -4
  631. package/dist/world/markers.js +49 -0
  632. package/dist/world/massing.js +1 -1
  633. package/dist/world/minimapBake.d.ts +78 -0
  634. package/dist/world/minimapBake.js +208 -0
  635. package/dist/world/minimapTrack.d.ts +17 -0
  636. package/dist/world/minimapTrack.js +22 -0
  637. package/dist/world/pathInstances.d.ts +27 -0
  638. package/dist/world/pathInstances.js +27 -0
  639. package/dist/world/pathNetwork.d.ts +159 -0
  640. package/dist/world/pathNetwork.js +684 -0
  641. package/dist/world/pathTerrain.d.ts +80 -0
  642. package/dist/world/pathTerrain.js +142 -0
  643. package/dist/world/place.d.ts +166 -0
  644. package/dist/world/place.js +96 -0
  645. package/dist/world/placeAsset.d.ts +81 -0
  646. package/dist/world/placeAsset.js +79 -0
  647. package/dist/world/placement.d.ts +4 -0
  648. package/dist/world/placement.js +4 -0
  649. package/dist/world/placementController.d.ts +6 -0
  650. package/dist/world/placementController.js +6 -0
  651. package/dist/world/poleLineKind.d.ts +40 -0
  652. package/dist/world/poleLineKind.js +97 -0
  653. package/dist/world/polyline.d.ts +34 -0
  654. package/dist/world/polyline.js +88 -0
  655. package/dist/world/resourceNode.d.ts +109 -0
  656. package/dist/world/resourceNode.js +140 -0
  657. package/dist/world/roads.d.ts +8 -0
  658. package/dist/world/roads.js +38 -0
  659. package/dist/world/scatter.js +2 -20
  660. package/dist/world/scatterRegion.d.ts +164 -0
  661. package/dist/world/scatterRegion.js +409 -0
  662. package/dist/world/sceneShapes.d.ts +43 -0
  663. package/dist/world/sceneShapes.js +1 -0
  664. package/dist/world/segment.d.ts +27 -0
  665. package/dist/world/segment.js +43 -0
  666. package/dist/world/soilKind.d.ts +48 -0
  667. package/dist/world/soilKind.js +92 -0
  668. package/dist/world/spatialSample.d.ts +241 -0
  669. package/dist/world/spatialSample.js +465 -0
  670. package/dist/world/streets.d.ts +29 -0
  671. package/dist/world/streets.js +55 -0
  672. package/dist/world/terraform.d.ts +213 -1
  673. package/dist/world/terraform.js +627 -22
  674. package/dist/world/terrain.d.ts +164 -20
  675. package/dist/world/terrain.js +325 -41
  676. package/dist/world/terrainGuides.d.ts +182 -0
  677. package/dist/world/terrainGuides.js +343 -0
  678. package/dist/world/vec2.d.ts +81 -0
  679. package/dist/world/vec2.js +128 -0
  680. package/dist/world/vec3.d.ts +49 -0
  681. package/dist/world/vec3.js +76 -0
  682. package/dist/world/vegetation.d.ts +71 -0
  683. package/dist/world/vegetation.js +151 -0
  684. package/dist/world/visibilityField.d.ts +154 -0
  685. package/dist/world/visibilityField.js +271 -0
  686. package/dist/world/volumetricClouds.d.ts +52 -0
  687. package/dist/world/volumetricClouds.js +43 -0
  688. package/dist/world/walls.d.ts +9 -0
  689. package/dist/world/walls.js +9 -0
  690. package/dist/world/waterKind.d.ts +55 -0
  691. package/dist/world/waterKind.js +99 -0
  692. package/dist/world.d.ts +141 -0
  693. package/dist/world.js +141 -0
  694. package/package.json +32 -8
  695. package/skills/game-design/SKILL.md +28 -0
  696. package/skills/game-design/agents/openai.yaml +4 -0
  697. package/skills/game-design/references/application-playbook.md +170 -0
  698. package/skills/game-design/references/field-guide.md +288 -0
  699. package/skills/jgengine/SKILL.md +54 -0
  700. package/skills/jgengine/api.md +527 -0
  701. package/skills/jgengine/capabilities.md +131 -0
  702. package/skills/jgengine/recipes/minimal-game.md +88 -0
  703. package/skills/jgengine-combat/SKILL.md +38 -0
  704. package/skills/jgengine-combat/api.md +585 -0
  705. package/skills/jgengine-combat/capabilities.md +213 -0
  706. package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
  707. package/skills/jgengine-combat/reference.md +108 -0
  708. package/skills/jgengine-gameplay/SKILL.md +39 -0
  709. package/skills/jgengine-gameplay/api.md +1920 -0
  710. package/skills/jgengine-gameplay/capabilities.md +454 -0
  711. package/skills/jgengine-gameplay/reference-systems.md +56 -0
  712. package/skills/jgengine-world/SKILL.md +51 -0
  713. package/skills/jgengine-world/api.md +3056 -0
  714. package/skills/jgengine-world/capabilities.md +476 -0
  715. package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
  716. package/skills/jgengine-world/reference.md +261 -0
  717. package/dist/cartridge/runtime.d.ts +0 -15
  718. package/dist/cartridge/runtime.js +0 -556
  719. package/dist/cartridge/spec.d.ts +0 -188
  720. package/dist/cartridge/spec.js +0 -19
  721. package/dist/cartridge/validate.d.ts +0 -2
  722. package/dist/cartridge/validate.js +0 -78
  723. package/dist/store/engineStore.d.ts +0 -22
  724. package/dist/store/engineStore.js +0 -50
  725. package/dist/store/features.d.ts +0 -10
  726. package/dist/store/features.js +0 -23
  727. package/llms.txt +0 -5389
@@ -0,0 +1,573 @@
1
+ /**
2
+ * Deterministic 2D polygon math for the `city` studio's block/parcel pipeline: signed areas,
3
+ * point-in-polygon, half-plane clipping, per-edge inward insets (the curb → sidewalk → land and
4
+ * parcel → buildable transforms), simple-loop recovery after aggressive insets, and rotated-rect
5
+ * fitting inside arbitrary polygons. Pure functions over `[x, z]` tuples — no allocation-heavy
6
+ * classes, no rendering, no randomness — so every consumer from the resolver to the tests shares
7
+ * one geometric truth.
8
+ *
9
+ * @capability city-district polygon math for road-derived blocks, parcels, and buildable footprints
10
+ */
11
+ /** Signed area of a polygon ring (positive = counter-clockwise in XZ). */
12
+ export function polygonSignedArea(ring) {
13
+ let sum = 0;
14
+ for (let i = 0; i < ring.length; i += 1) {
15
+ const [ax, az] = ring[i];
16
+ const [bx, bz] = ring[(i + 1) % ring.length];
17
+ sum += ax * bz - bx * az;
18
+ }
19
+ return sum / 2;
20
+ }
21
+ /** Absolute polygon area. */
22
+ export function polygonArea(ring) {
23
+ return Math.abs(polygonSignedArea(ring));
24
+ }
25
+ /** Ring perimeter length. */
26
+ export function polygonPerimeter(ring) {
27
+ let sum = 0;
28
+ for (let i = 0; i < ring.length; i += 1) {
29
+ const [ax, az] = ring[i];
30
+ const [bx, bz] = ring[(i + 1) % ring.length];
31
+ sum += Math.hypot(bx - ax, bz - az);
32
+ }
33
+ return sum;
34
+ }
35
+ /** Area centroid of a simple polygon (falls back to the vertex mean for degenerate rings). */
36
+ export function polygonCentroid(ring) {
37
+ let area = 0;
38
+ let cx = 0;
39
+ let cz = 0;
40
+ for (let i = 0; i < ring.length; i += 1) {
41
+ const [ax, az] = ring[i];
42
+ const [bx, bz] = ring[(i + 1) % ring.length];
43
+ const cross = ax * bz - bx * az;
44
+ area += cross;
45
+ cx += (ax + bx) * cross;
46
+ cz += (az + bz) * cross;
47
+ }
48
+ if (Math.abs(area) < 1e-9) {
49
+ let mx = 0;
50
+ let mz = 0;
51
+ for (const [x, z] of ring) {
52
+ mx += x;
53
+ mz += z;
54
+ }
55
+ const n = Math.max(1, ring.length);
56
+ return [mx / n, mz / n];
57
+ }
58
+ return [cx / (3 * area), cz / (3 * area)];
59
+ }
60
+ /** Ensure counter-clockwise winding (positive signed area) without mutating the input. */
61
+ export function ensureCcw(ring) {
62
+ return polygonSignedArea(ring) >= 0 ? ring.map((p) => p) : ring.map((p) => p).reverse();
63
+ }
64
+ /** Even-odd point-in-polygon test. */
65
+ export function pointInPolygon(ring, x, z) {
66
+ let inside = false;
67
+ for (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {
68
+ const [xi, zi] = ring[i];
69
+ const [xj, zj] = ring[j];
70
+ if (zi > z !== zj > z && x < ((xj - xi) * (z - zi)) / (zj - zi) + xi)
71
+ inside = !inside;
72
+ }
73
+ return inside;
74
+ }
75
+ /** Distance from a point to the nearest boundary segment of a ring. */
76
+ export function distanceToRing(ring, x, z) {
77
+ let best = Infinity;
78
+ for (let i = 0; i < ring.length; i += 1) {
79
+ const [ax, az] = ring[i];
80
+ const [bx, bz] = ring[(i + 1) % ring.length];
81
+ const vx = bx - ax;
82
+ const vz = bz - az;
83
+ const len2 = vx * vx + vz * vz;
84
+ const t = len2 === 0 ? 0 : Math.max(0, Math.min(1, ((x - ax) * vx + (z - az) * vz) / len2));
85
+ const d = Math.hypot(x - (ax + vx * t), z - (az + vz * t));
86
+ if (d < best)
87
+ best = d;
88
+ }
89
+ return best;
90
+ }
91
+ /**
92
+ * Clip a polygon to the half-plane `dot(p, normal) <= limit` (Sutherland–Hodgman step). Returns
93
+ * the surviving ring, possibly empty. The subject may be concave; the output of a single
94
+ * half-plane clip of a simple ring is always a valid (possibly pinched) ring.
95
+ */
96
+ export function clipHalfPlane(ring, normal, limit) {
97
+ const out = [];
98
+ const [nx, nz] = normal;
99
+ for (let i = 0; i < ring.length; i += 1) {
100
+ const a = ring[i];
101
+ const b = ring[(i + 1) % ring.length];
102
+ const da = a[0] * nx + a[1] * nz - limit;
103
+ const db = b[0] * nx + b[1] * nz - limit;
104
+ if (da <= 0)
105
+ out.push(a);
106
+ if ((da < 0 && db > 0) || (da > 0 && db < 0)) {
107
+ const t = da / (da - db);
108
+ out.push([a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t]);
109
+ }
110
+ }
111
+ return dedupeRing(out);
112
+ }
113
+ /** Split a polygon by the line `dot(p, normal) = limit` into the `<=` and `>=` sides. */
114
+ export function splitByLine(ring, normal, limit) {
115
+ return {
116
+ below: clipHalfPlane(ring, normal, limit),
117
+ above: clipHalfPlane(ring, [-normal[0], -normal[1]], -limit),
118
+ };
119
+ }
120
+ /** Remove consecutive (near-)duplicate vertices; returns [] when fewer than 3 survive. */
121
+ export function dedupeRing(ring, epsilon = 1e-6) {
122
+ const out = [];
123
+ for (const p of ring) {
124
+ const prev = out[out.length - 1];
125
+ if (prev !== undefined && Math.abs(prev[0] - p[0]) < epsilon && Math.abs(prev[1] - p[1]) < epsilon)
126
+ continue;
127
+ out.push(p);
128
+ }
129
+ while (out.length >= 2) {
130
+ const first = out[0];
131
+ const last = out[out.length - 1];
132
+ if (Math.abs(first[0] - last[0]) < epsilon && Math.abs(first[1] - last[1]) < epsilon)
133
+ out.pop();
134
+ else
135
+ break;
136
+ }
137
+ return out.length >= 3 ? out : [];
138
+ }
139
+ function segmentsCross(a, b, c, d) {
140
+ const o = (p, q, r) => (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0]);
141
+ const o1 = o(a, b, c);
142
+ const o2 = o(a, b, d);
143
+ const o3 = o(c, d, a);
144
+ const o4 = o(c, d, b);
145
+ return o1 * o2 < 0 && o3 * o4 < 0;
146
+ }
147
+ /** True when any two non-adjacent edges of the ring properly cross. O(n²), fine for block-scale n. */
148
+ export function ringSelfIntersects(ring) {
149
+ const n = ring.length;
150
+ for (let i = 0; i < n; i += 1) {
151
+ const a = ring[i];
152
+ const b = ring[(i + 1) % n];
153
+ for (let j = i + 2; j < n; j += 1) {
154
+ if (i === 0 && j === n - 1)
155
+ continue;
156
+ const c = ring[j];
157
+ const d = ring[(j + 1) % n];
158
+ if (segmentsCross(a, b, c, d))
159
+ return true;
160
+ }
161
+ }
162
+ return false;
163
+ }
164
+ /**
165
+ * Recover the dominant simple loop from a lightly self-intersecting ring: whenever two edges
166
+ * cross, the smaller of the two loops the crossing pinches off is dropped. Bounded passes; rings
167
+ * that stay tangled after that return []. This is the cleanup net under aggressive insets — a
168
+ * concave block inset past a neck pinches into a bow-tie, and the bigger lobe is the block.
169
+ */
170
+ export function extractSimpleLoop(ring, maxPasses = 6) {
171
+ let current = dedupeRing(ring);
172
+ for (let pass = 0; pass < maxPasses; pass += 1) {
173
+ if (current.length < 4)
174
+ return current;
175
+ let crossed = false;
176
+ const n = current.length;
177
+ outer: for (let i = 0; i < n; i += 1) {
178
+ const a = current[i];
179
+ const b = current[(i + 1) % n];
180
+ for (let j = i + 2; j < n; j += 1) {
181
+ if (i === 0 && j === n - 1)
182
+ continue;
183
+ const c = current[j];
184
+ const d = current[(j + 1) % n];
185
+ if (!segmentsCross(a, b, c, d))
186
+ continue;
187
+ // Intersection point of ab × cd.
188
+ const denom = (b[0] - a[0]) * (d[1] - c[1]) - (b[1] - a[1]) * (d[0] - c[0]);
189
+ if (Math.abs(denom) < 1e-12)
190
+ continue;
191
+ const t = ((c[0] - a[0]) * (d[1] - c[1]) - (c[1] - a[1]) * (d[0] - c[0])) / denom;
192
+ const px = a[0] + (b[0] - a[0]) * t;
193
+ const pz = a[1] + (b[1] - a[1]) * t;
194
+ // Two candidate loops: i+1..j (+X), and j+1..i (+X).
195
+ const loopA = [[px, pz]];
196
+ for (let k = i + 1; k <= j; k += 1)
197
+ loopA.push(current[k]);
198
+ const loopB = [[px, pz]];
199
+ for (let k = j + 1; k < n + i + 1; k += 1)
200
+ loopB.push(current[k % n]);
201
+ current = polygonArea(loopA) >= polygonArea(loopB) ? dedupeRing(loopA) : dedupeRing(loopB);
202
+ crossed = true;
203
+ break outer;
204
+ }
205
+ }
206
+ if (!crossed)
207
+ return current;
208
+ }
209
+ return [];
210
+ }
211
+ /**
212
+ * Inset a CCW ring inward with a PER-EDGE distance (edge i runs vertex i → i+1). True corners take
213
+ * the intersection of the two adjacent offset lines (so a street corner lands exactly where the
214
+ * two curb lines meet, even with different street widths); near-collinear vertices — polyline
215
+ * samples along a curve — fall back to the averaged-normal offset, which is exact in the limit.
216
+ * Returns [] when the inset collapses (sliver) or stays tangled after loop recovery.
217
+ */
218
+ export function insetRing(ring, edgeDistances) {
219
+ const n = ring.length;
220
+ if (n < 3 || edgeDistances.length !== n)
221
+ return [];
222
+ const out = [];
223
+ for (let i = 0; i < n; i += 1) {
224
+ const prev = ring[(i + n - 1) % n];
225
+ const cur = ring[i];
226
+ const next = ring[(i + 1) % n];
227
+ const d0 = edgeDistances[(i + n - 1) % n];
228
+ const d1 = edgeDistances[i];
229
+ const e0 = [cur[0] - prev[0], cur[1] - prev[1]];
230
+ const e1 = [next[0] - cur[0], next[1] - cur[1]];
231
+ const l0 = Math.hypot(e0[0], e0[1]) || 1;
232
+ const l1 = Math.hypot(e1[0], e1[1]) || 1;
233
+ const u0 = [e0[0] / l0, e0[1] / l0];
234
+ const u1 = [e1[0] / l1, e1[1] / l1];
235
+ // Inward normal of a CCW ring edge (dx, dz) is (-dz, dx) rotated... for CCW in XZ with
236
+ // signed area computed as above, the interior lies to the LEFT of each edge: left normal
237
+ // of (dx, dz) is (-dz, dx).
238
+ const n0 = [-u0[1], u0[0]];
239
+ const n1 = [-u1[1], u1[0]];
240
+ const cross = u0[0] * u1[1] - u0[1] * u1[0];
241
+ if (Math.abs(cross) < 0.17) {
242
+ // Near-collinear (sampled curve): averaged normal, averaged distance.
243
+ const ax = (n0[0] + n1[0]) / 2;
244
+ const az = (n0[1] + n1[1]) / 2;
245
+ const al = Math.hypot(ax, az) || 1;
246
+ const d = (d0 + d1) / 2;
247
+ out.push([cur[0] + (ax / al) * d, cur[1] + (az / al) * d]);
248
+ }
249
+ else {
250
+ // Offset-line intersection: line0 = prev-edge shifted by n0*d0, line1 = next-edge by n1*d1.
251
+ const p0 = [cur[0] + n0[0] * d0, cur[1] + n0[1] * d0];
252
+ const p1 = [cur[0] + n1[0] * d1, cur[1] + n1[1] * d1];
253
+ const denom = u0[0] * u1[1] - u0[1] * u1[0];
254
+ const t = ((p1[0] - p0[0]) * u1[1] - (p1[1] - p0[1]) * u1[0]) / denom;
255
+ const mx = p0[0] + u0[0] * t;
256
+ const mz = p0[1] + u0[1] * t;
257
+ // Clamp runaway miters (grazing angles) to a bevel-ish point near the vertex.
258
+ const miterLen = Math.hypot(mx - cur[0], mz - cur[1]);
259
+ const maxMiter = Math.max(d0, d1) * 4 + 0.5;
260
+ if (miterLen > maxMiter) {
261
+ const s = maxMiter / miterLen;
262
+ out.push([cur[0] + (mx - cur[0]) * s, cur[1] + (mz - cur[1]) * s]);
263
+ }
264
+ else {
265
+ out.push([mx, mz]);
266
+ }
267
+ }
268
+ }
269
+ // Over-inset detection BEFORE loop recovery, while vertices still correspond 1:1: an edge that
270
+ // crossed the medial axis runs backwards relative to its source edge. A little flipped length
271
+ // is a pinched lobe (loop recovery trims it); mostly-flipped means the whole ring inverted —
272
+ // note a symmetric over-inset point-reflects, so winding alone cannot catch it.
273
+ let flipped = 0;
274
+ let totalLen = 0;
275
+ for (let i = 0; i < n; i += 1) {
276
+ const a = ring[i];
277
+ const b = ring[(i + 1) % n];
278
+ const a2 = out[i];
279
+ const b2 = out[(i + 1) % n];
280
+ const len = Math.hypot(b[0] - a[0], b[1] - a[1]);
281
+ totalLen += len;
282
+ if ((b[0] - a[0]) * (b2[0] - a2[0]) + (b[1] - a[1]) * (b2[1] - a2[1]) < 0)
283
+ flipped += len;
284
+ }
285
+ if (totalLen > 0 && flipped / totalLen > 0.4)
286
+ return [];
287
+ const cleaned = extractSimpleLoop(out);
288
+ if (cleaned.length < 3)
289
+ return [];
290
+ // A valid inset shrinks and keeps its winding: reject results that flipped inside-out or exploded.
291
+ if (polygonSignedArea(cleaned) * polygonSignedArea(ring) <= 0)
292
+ return [];
293
+ const before = polygonArea(ring);
294
+ const after = polygonArea(cleaned);
295
+ if (after <= 1e-6 || after > before * 1.02)
296
+ return [];
297
+ // Every surviving vertex must stay inside (or on) the source ring.
298
+ for (const [x, z] of cleaned) {
299
+ if (!pointInPolygon(ring, x, z) && distanceToRing(ring, x, z) > 0.35)
300
+ return [];
301
+ }
302
+ return cleaned;
303
+ }
304
+ /** Uniform-distance convenience over {@link insetRing}. */
305
+ export function insetRingUniform(ring, distance) {
306
+ return insetRing(ring, ring.map(() => distance));
307
+ }
308
+ /**
309
+ * Mean "width" proxy for sliver detection: the diameter of the largest inscribed strip is
310
+ * approximated by 2·area / perimeter (exact for long rectangles, conservative elsewhere).
311
+ */
312
+ export function polygonMeanWidth(ring) {
313
+ const perimeter = polygonPerimeter(ring);
314
+ return perimeter <= 1e-6 ? 0 : (2 * polygonArea(ring)) / perimeter;
315
+ }
316
+ /** All four corners of a rotated rect (center, half-extents, yaw in engine rotationY convention). */
317
+ export function rectCorners(cx, cz, hw, hd, rotationY) {
318
+ const c = Math.cos(rotationY);
319
+ const s = Math.sin(rotationY);
320
+ const out = [];
321
+ for (const [dx, dz] of [
322
+ [hw, hd],
323
+ [hw, -hd],
324
+ [-hw, -hd],
325
+ [-hw, hd],
326
+ ]) {
327
+ out.push([cx + dx * c + dz * s, cz - dx * s + dz * c]);
328
+ }
329
+ return out;
330
+ }
331
+ /** True when the whole rotated rect (corners + edge midpoints) sits inside the ring. */
332
+ export function rectInsidePolygon(ring, cx, cz, hw, hd, rotationY) {
333
+ const corners = rectCorners(cx, cz, hw, hd, rotationY);
334
+ for (const [x, z] of corners) {
335
+ if (!pointInPolygon(ring, x, z))
336
+ return false;
337
+ }
338
+ for (let i = 0; i < 4; i += 1) {
339
+ const a = corners[i];
340
+ const b = corners[(i + 1) % 4];
341
+ if (!pointInPolygon(ring, (a[0] + b[0]) / 2, (a[1] + b[1]) / 2))
342
+ return false;
343
+ }
344
+ return true;
345
+ }
346
+ /**
347
+ * Fit the largest rect (up to `maxW`×`maxD`, oriented to `rotationY`, centered near `[cx, cz]`)
348
+ * inside a polygon by bounded bisection on a single scale factor. Deterministic; returns null
349
+ * when even `minScale` of the request does not fit after nudging the center inward.
350
+ */
351
+ export function fitRectInPolygon(ring, cx, cz, maxW, maxD, rotationY, minScale = 0.55) {
352
+ const centers = [[cx, cz]];
353
+ // Nudge candidates toward the polygon centroid when the raw center fails.
354
+ const [gx, gz] = polygonCentroid(ring);
355
+ centers.push([cx + (gx - cx) * 0.35, cz + (gz - cz) * 0.35], [cx + (gx - cx) * 0.7, cz + (gz - cz) * 0.7]);
356
+ for (const [ux, uz] of centers) {
357
+ if (!pointInPolygon(ring, ux, uz))
358
+ continue;
359
+ if (rectInsidePolygon(ring, ux, uz, maxW / 2, maxD / 2, rotationY))
360
+ return { w: maxW, d: maxD, cx: ux, cz: uz };
361
+ let lo = 0;
362
+ let hi = 1;
363
+ for (let iter = 0; iter < 9; iter += 1) {
364
+ const mid = (lo + hi) / 2;
365
+ if (rectInsidePolygon(ring, ux, uz, (maxW * mid) / 2, (maxD * mid) / 2, rotationY))
366
+ lo = mid;
367
+ else
368
+ hi = mid;
369
+ }
370
+ if (lo >= minScale)
371
+ return { w: maxW * lo, d: maxD * lo, cx: ux, cz: uz };
372
+ }
373
+ return null;
374
+ }
375
+ /**
376
+ * Distance from `origin` along `dir` to the first ring-boundary crossing (ignoring hits closer
377
+ * than `minT`, e.g. the edge the origin sits on). Infinity when the ray never leaves — degenerate.
378
+ */
379
+ export function rayDistanceToRing(ring, origin, dir, minT = 0.6) {
380
+ let best = Infinity;
381
+ for (let i = 0; i < ring.length; i += 1) {
382
+ const a = ring[i];
383
+ const b = ring[(i + 1) % ring.length];
384
+ const sx = b[0] - a[0];
385
+ const sz = b[1] - a[1];
386
+ const denom = dir[0] * sz - dir[1] * sx;
387
+ if (Math.abs(denom) < 1e-12)
388
+ continue;
389
+ const t = ((a[0] - origin[0]) * sz - (a[1] - origin[1]) * sx) / denom;
390
+ const u = ((a[0] - origin[0]) * dir[1] - (a[1] - origin[1]) * dir[0]) / denom;
391
+ if (t > minT && u >= -1e-6 && u <= 1 + 1e-6 && t < best)
392
+ best = t;
393
+ }
394
+ return best;
395
+ }
396
+ /** Axis-aligned bounding box of a ring. */
397
+ export function ringBounds(ring) {
398
+ let minX = Infinity;
399
+ let minZ = Infinity;
400
+ let maxX = -Infinity;
401
+ let maxZ = -Infinity;
402
+ for (const [x, z] of ring) {
403
+ if (x < minX)
404
+ minX = x;
405
+ if (z < minZ)
406
+ minZ = z;
407
+ if (x > maxX)
408
+ maxX = x;
409
+ if (z > maxZ)
410
+ maxZ = z;
411
+ }
412
+ return { minX, minZ, maxX, maxZ };
413
+ }
414
+ /**
415
+ * Ear-clip a simple polygon into triangles. Returns the cleaned/CCW-oriented vertex ring plus flat
416
+ * index triples into it (so a draping consumer can sample a height per returned vertex). O(n²) —
417
+ * fine for block/park rings. A polygon that stays un-clippable (self-touching after dedupe) yields
418
+ * whatever ears were found before the guard trips; degenerate input returns no triangles.
419
+ */
420
+ export function triangulatePolygon(ring) {
421
+ const positions = ensureCcw(dedupeRing(ring));
422
+ const n = positions.length;
423
+ const indices = [];
424
+ if (n < 3)
425
+ return { positions, indices };
426
+ const V = [];
427
+ for (let i = 0; i < n; i += 1)
428
+ V.push(i);
429
+ let count = 2 * n;
430
+ let v = n - 1;
431
+ let remaining = n;
432
+ while (remaining > 2) {
433
+ if (count <= 0)
434
+ break; // Non-simple ring — bail with the ears found so far.
435
+ count -= 1;
436
+ const u = v % remaining;
437
+ v = (u + 1) % remaining;
438
+ const w = (v + 1) % remaining;
439
+ if (isEar(positions, V[u], V[v], V[w], V, remaining)) {
440
+ indices.push(V[u], V[v], V[w]);
441
+ for (let s = v; s + 1 < remaining; s += 1)
442
+ V[s] = V[s + 1];
443
+ remaining -= 1;
444
+ count = 2 * remaining;
445
+ }
446
+ }
447
+ return { positions, indices };
448
+ }
449
+ /** True when triangle (a,b,c) is a valid ear of the CCW polygon: convex and empty of other verts. */
450
+ function isEar(poly, ia, ib, ic, V, remaining) {
451
+ const a = poly[ia];
452
+ const b = poly[ib];
453
+ const c = poly[ic];
454
+ const cross = (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
455
+ if (cross <= 1e-9)
456
+ return false; // Reflex or collinear.
457
+ for (let i = 0; i < remaining; i += 1) {
458
+ const p = V[i];
459
+ if (p === ia || p === ib || p === ic)
460
+ continue;
461
+ if (pointInTriangle(poly[p], a, b, c))
462
+ return false;
463
+ }
464
+ return true;
465
+ }
466
+ function pointInTriangle(p, a, b, c) {
467
+ const d1 = (p[0] - b[0]) * (a[1] - b[1]) - (a[0] - b[0]) * (p[1] - b[1]);
468
+ const d2 = (p[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (p[1] - c[1]);
469
+ const d3 = (p[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (p[1] - a[1]);
470
+ const neg = d1 < 0 || d2 < 0 || d3 < 0;
471
+ const pos = d1 > 0 || d2 > 0 || d3 > 0;
472
+ return !(neg && pos);
473
+ }
474
+ /**
475
+ * Triangulate the band between two nested rings (an outer ring with an inner hole, e.g. a curb ring
476
+ * around a land ring — the sidewalk). Pairs the loops by cumulative arc-length fraction, aligning
477
+ * the inner start to the outer's first vertex, so it is robust to differing vertex counts and to a
478
+ * rotational offset between the rings. Returns the merged vertex list (outer, then the rotated
479
+ * inner) and index triples into it. Zero-area triangles — where the two rings coincide (a street
480
+ * edge with no sidewalk) — are dropped so `computeVertexNormals` never sees a degenerate face.
481
+ */
482
+ export function triangulateRingBand(outer, inner) {
483
+ const o = dedupeRing(outer);
484
+ const raw = dedupeRing(inner);
485
+ const n = o.length;
486
+ const m = raw.length;
487
+ if (n < 3 || m < 3)
488
+ return { positions: [], indices: [] };
489
+ // Rotate the inner ring so its first vertex is the one nearest outer[0]: keeps the fraction-based
490
+ // pairing local rather than shearing the band diagonally.
491
+ let start = 0;
492
+ let bestDist = Infinity;
493
+ for (let k = 0; k < m; k += 1) {
494
+ const d = (raw[k][0] - o[0][0]) ** 2 + (raw[k][1] - o[0][1]) ** 2;
495
+ if (d < bestDist) {
496
+ bestDist = d;
497
+ start = k;
498
+ }
499
+ }
500
+ const i2 = [];
501
+ for (let k = 0; k < m; k += 1)
502
+ i2.push(raw[(start + k) % m]);
503
+ const positions = [...o, ...i2];
504
+ const off = n;
505
+ const ot = ringFractions(o);
506
+ const it = ringFractions(i2);
507
+ const indices = [];
508
+ const emit = (a, b, c) => {
509
+ const pa = positions[a];
510
+ const pb = positions[b];
511
+ const pc = positions[c];
512
+ const area2 = (pb[0] - pa[0]) * (pc[1] - pa[1]) - (pb[1] - pa[1]) * (pc[0] - pa[0]);
513
+ if (Math.abs(area2) < 1e-6)
514
+ return; // Coincident rings here (no sidewalk width): skip.
515
+ indices.push(a, b, c);
516
+ };
517
+ let i = 0;
518
+ let j = 0;
519
+ while (i < n || j < m) {
520
+ const advanceOuter = j >= m || (i < n && ot[i + 1] <= it[j + 1]);
521
+ if (advanceOuter) {
522
+ emit(i % n, off + (j % m), (i + 1) % n);
523
+ i += 1;
524
+ }
525
+ else {
526
+ emit(i % n, off + (j % m), off + ((j + 1) % m));
527
+ j += 1;
528
+ }
529
+ }
530
+ return { positions, indices };
531
+ }
532
+ /** Cumulative arc-length fractions for a closed ring: length n+1, [0]=0 … [n]=1 (the wrap). */
533
+ function ringFractions(ring) {
534
+ const n = ring.length;
535
+ const cum = [0];
536
+ let total = 0;
537
+ for (let i = 0; i < n; i += 1) {
538
+ const a = ring[i];
539
+ const b = ring[(i + 1) % n];
540
+ total += Math.hypot(b[0] - a[0], b[1] - a[1]);
541
+ cum.push(total);
542
+ }
543
+ const scale = total > 1e-9 ? 1 / total : 0;
544
+ for (let i = 0; i < cum.length; i += 1)
545
+ cum[i] *= scale;
546
+ return cum;
547
+ }
548
+ /** Conservative polygon-overlap test: any vertex of one strictly inside the other, or any edges crossing. */
549
+ export function polygonsOverlap(a, b, shrink = 0.05) {
550
+ const inset = (ring) => {
551
+ if (shrink <= 0)
552
+ return ring;
553
+ const small = insetRingUniform(ring, shrink);
554
+ return small.length >= 3 ? small : ring;
555
+ };
556
+ const sa = inset(a);
557
+ const sb = inset(b);
558
+ for (const [x, z] of sa)
559
+ if (pointInPolygon(sb, x, z))
560
+ return true;
561
+ for (const [x, z] of sb)
562
+ if (pointInPolygon(sa, x, z))
563
+ return true;
564
+ for (let i = 0; i < sa.length; i += 1) {
565
+ const p1 = sa[i];
566
+ const p2 = sa[(i + 1) % sa.length];
567
+ for (let j = 0; j < sb.length; j += 1) {
568
+ if (segmentsCross(p1, p2, sb[j], sb[(j + 1) % sb.length]))
569
+ return true;
570
+ }
571
+ }
572
+ return false;
573
+ }