@jgengine/core 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (631) hide show
  1. package/CHANGELOG.md +34 -3
  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/spawnDirector.d.ts +19 -1
  21. package/dist/ai/spawnDirector.js +53 -26
  22. package/dist/ai/spawnPoint.d.ts +7 -0
  23. package/dist/ai/spawnPoint.js +7 -0
  24. package/dist/ai/targetAcquisition.d.ts +84 -0
  25. package/dist/ai/targetAcquisition.js +92 -0
  26. package/dist/anim/easing.d.ts +19 -0
  27. package/dist/anim/easing.js +19 -0
  28. package/dist/anim/oscillator.d.ts +12 -0
  29. package/dist/anim/oscillator.js +25 -0
  30. package/dist/area/areaEffectField.d.ts +127 -0
  31. package/dist/area/areaEffectField.js +175 -0
  32. package/dist/area/stackPolicy.d.ts +47 -0
  33. package/dist/area/stackPolicy.js +99 -0
  34. package/dist/audio/audioFalloff.d.ts +5 -2
  35. package/dist/audio/music.d.ts +53 -0
  36. package/dist/audio/music.js +34 -0
  37. package/dist/audio/synth.d.ts +60 -0
  38. package/dist/audio/synth.js +8 -0
  39. package/dist/authoring.d.ts +15 -0
  40. package/dist/authoring.js +15 -0
  41. package/dist/board/laneBoard.d.ts +13 -0
  42. package/dist/board/laneBoard.js +13 -0
  43. package/dist/board/timelineBoard.d.ts +10 -0
  44. package/dist/board/timelineBoard.js +10 -0
  45. package/dist/combat/abilityKit.d.ts +18 -0
  46. package/dist/combat/abilityKit.js +24 -9
  47. package/dist/combat/animationState.d.ts +5 -0
  48. package/dist/combat/animationState.js +5 -0
  49. package/dist/combat/breakMeters.d.ts +10 -0
  50. package/dist/combat/breakMeters.js +10 -0
  51. package/dist/combat/castRunner.d.ts +5 -0
  52. package/dist/combat/castRunner.js +5 -0
  53. package/dist/combat/comboPoints.d.ts +5 -0
  54. package/dist/combat/comboPoints.js +5 -0
  55. package/dist/combat/comboString.d.ts +5 -0
  56. package/dist/combat/comboString.js +5 -0
  57. package/dist/combat/damageInterceptors.d.ts +192 -0
  58. package/dist/combat/damageInterceptors.js +251 -0
  59. package/dist/combat/damageMatchup.d.ts +68 -0
  60. package/dist/combat/damageMatchup.js +42 -0
  61. package/dist/combat/damageResolution.d.ts +63 -0
  62. package/dist/combat/damageResolution.js +50 -0
  63. package/dist/combat/death.d.ts +7 -1
  64. package/dist/combat/death.js +5 -0
  65. package/dist/combat/deathReason.d.ts +14 -0
  66. package/dist/combat/deathReason.js +1 -0
  67. package/dist/combat/defensiveWindow.d.ts +5 -0
  68. package/dist/combat/defensiveWindow.js +5 -0
  69. package/dist/combat/dotField.d.ts +47 -0
  70. package/dist/combat/dotField.js +52 -0
  71. package/dist/combat/downed.d.ts +5 -0
  72. package/dist/combat/downed.js +5 -0
  73. package/dist/combat/effects.d.ts +5 -0
  74. package/dist/combat/effects.js +5 -0
  75. package/dist/combat/encounterSequence.d.ts +258 -0
  76. package/dist/combat/encounterSequence.js +426 -0
  77. package/dist/combat/hitReaction.d.ts +57 -1
  78. package/dist/combat/hitReaction.js +45 -5
  79. package/dist/combat/magazine.d.ts +54 -0
  80. package/dist/combat/magazine.js +96 -0
  81. package/dist/combat/projectiles.d.ts +7 -2
  82. package/dist/combat/projectiles.js +48 -17
  83. package/dist/combat/receivedDamage.d.ts +117 -0
  84. package/dist/combat/receivedDamage.js +92 -0
  85. package/dist/combat/regenShield.d.ts +39 -0
  86. package/dist/combat/regenShield.js +49 -0
  87. package/dist/combat/renderCues.d.ts +51 -0
  88. package/dist/combat/renderCues.js +44 -0
  89. package/dist/combat/resourcePool.d.ts +5 -0
  90. package/dist/combat/resourcePool.js +5 -0
  91. package/dist/combat/rewardAllocation.d.ts +121 -0
  92. package/dist/combat/rewardAllocation.js +251 -0
  93. package/dist/combat/shotOrigin.d.ts +30 -1
  94. package/dist/combat/shotOrigin.js +70 -2
  95. package/dist/combat/statusApplication.d.ts +96 -0
  96. package/dist/combat/statusApplication.js +81 -0
  97. package/dist/combat/telegraph.d.ts +11 -2
  98. package/dist/combat/telegraph.js +11 -2
  99. package/dist/combat/thresholdCrossings.d.ts +85 -0
  100. package/dist/combat/thresholdCrossings.js +116 -0
  101. package/dist/combat.d.ts +34 -0
  102. package/dist/combat.js +34 -0
  103. package/dist/commands/commandRegistry.d.ts +11 -0
  104. package/dist/commands/commandRegistry.js +9 -2
  105. package/dist/crafting/crop.d.ts +18 -0
  106. package/dist/crafting/crop.js +18 -0
  107. package/dist/crafting/production.d.ts +5 -0
  108. package/dist/crafting/production.js +5 -0
  109. package/dist/devtools/rewriteTunables.d.ts +17 -0
  110. package/dist/devtools/rewriteTunables.js +276 -0
  111. package/dist/devtools/saveEndpoint.d.ts +46 -0
  112. package/dist/devtools/saveEndpoint.js +48 -0
  113. package/dist/devtools/transformTunables.d.ts +3 -0
  114. package/dist/devtools/transformTunables.js +3 -0
  115. package/dist/devtools/tunableSchema.d.ts +31 -0
  116. package/dist/devtools/tunableSchema.js +31 -0
  117. package/dist/economy/currency.d.ts +12 -1
  118. package/dist/economy/currency.js +12 -1
  119. package/dist/economy/listingBook.d.ts +91 -0
  120. package/dist/economy/listingBook.js +144 -0
  121. package/dist/economy/resourceLedger.d.ts +222 -0
  122. package/dist/economy/resourceLedger.js +353 -0
  123. package/dist/economy/sharedWallet.d.ts +14 -0
  124. package/dist/economy/sharedWallet.js +14 -0
  125. package/dist/economy/techTree.d.ts +12 -0
  126. package/dist/economy/techTree.js +12 -0
  127. package/dist/economy/wallet.d.ts +26 -2
  128. package/dist/economy/wallet.js +35 -6
  129. package/dist/editor/commands.d.ts +248 -0
  130. package/dist/editor/commands.js +865 -0
  131. package/dist/editor/document.d.ts +186 -0
  132. package/dist/editor/document.js +884 -0
  133. package/dist/editor/grid.d.ts +229 -0
  134. package/dist/editor/grid.js +366 -0
  135. package/dist/editor/gridAdapters.d.ts +80 -0
  136. package/dist/editor/gridAdapters.js +134 -0
  137. package/dist/editor/index.d.ts +97 -0
  138. package/dist/editor/index.js +10 -0
  139. package/dist/editor/liveSync.d.ts +127 -0
  140. package/dist/editor/liveSync.js +249 -0
  141. package/dist/editor/runtimeInspector.d.ts +88 -0
  142. package/dist/editor/runtimeInspector.js +239 -0
  143. package/dist/editor/types.d.ts +175 -0
  144. package/dist/editor/types.js +29 -0
  145. package/dist/faction/reputation.d.ts +5 -0
  146. package/dist/faction/reputation.js +5 -0
  147. package/dist/format/distance.d.ts +17 -0
  148. package/dist/format/distance.js +18 -0
  149. package/dist/format/duration.d.ts +27 -0
  150. package/dist/format/duration.js +45 -0
  151. package/dist/format/speed.d.ts +17 -0
  152. package/dist/format/speed.js +25 -0
  153. package/dist/game/connectedPlayers.d.ts +30 -0
  154. package/dist/game/connectedPlayers.js +21 -0
  155. package/dist/game/cosmetics.d.ts +9 -0
  156. package/dist/game/cosmetics.js +16 -0
  157. package/dist/game/defineGame.d.ts +141 -2
  158. package/dist/game/defineGame.js +39 -1
  159. package/dist/game/defineSystem.d.ts +88 -0
  160. package/dist/game/defineSystem.js +45 -0
  161. package/dist/game/dialogue.d.ts +33 -0
  162. package/dist/game/dialogue.js +21 -0
  163. package/dist/game/events.d.ts +50 -13
  164. package/dist/game/events.js +5 -0
  165. package/dist/game/feed.d.ts +33 -0
  166. package/dist/game/feed.js +35 -2
  167. package/dist/game/gamePhase.d.ts +11 -0
  168. package/dist/game/gamePhase.js +16 -0
  169. package/dist/game/keyValueStore.d.ts +25 -0
  170. package/dist/game/keyValueStore.js +61 -0
  171. package/dist/game/leaderboard.d.ts +5 -0
  172. package/dist/game/leaderboard.js +5 -0
  173. package/dist/game/levelSequence.d.ts +24 -2
  174. package/dist/game/levelSequence.js +51 -2
  175. package/dist/game/loadout.d.ts +5 -0
  176. package/dist/game/loadout.js +5 -0
  177. package/dist/game/lootFilter.d.ts +2 -0
  178. package/dist/game/lootFilter.js +2 -0
  179. package/dist/game/lootPipeline.d.ts +164 -0
  180. package/dist/game/lootPipeline.js +216 -0
  181. package/dist/game/lootTable.d.ts +21 -0
  182. package/dist/game/lootTable.js +15 -4
  183. package/dist/game/modelAnimation.d.ts +8 -0
  184. package/dist/game/modelAnimation.js +18 -0
  185. package/dist/game/objectives.d.ts +43 -0
  186. package/dist/game/objectives.js +36 -0
  187. package/dist/game/paramLayers.d.ts +148 -0
  188. package/dist/game/paramLayers.js +185 -0
  189. package/dist/game/ping.d.ts +5 -0
  190. package/dist/game/ping.js +5 -0
  191. package/dist/game/playableGame.d.ts +160 -12
  192. package/dist/game/quest.d.ts +8 -0
  193. package/dist/game/quest.js +29 -0
  194. package/dist/game/race.d.ts +141 -0
  195. package/dist/game/race.js +169 -0
  196. package/dist/game/recordBook.d.ts +5 -5
  197. package/dist/game/recordBook.js +4 -1
  198. package/dist/game/ruleSelection.d.ts +75 -0
  199. package/dist/game/ruleSelection.js +127 -0
  200. package/dist/game/runDraft.d.ts +5 -0
  201. package/dist/game/runDraft.js +5 -0
  202. package/dist/game/saveStore.d.ts +111 -0
  203. package/dist/game/saveStore.js +312 -0
  204. package/dist/game/snapshotHistory.d.ts +67 -0
  205. package/dist/game/snapshotHistory.js +95 -0
  206. package/dist/game/social.d.ts +38 -1
  207. package/dist/game/social.js +71 -0
  208. package/dist/game/spawnPoints.d.ts +5 -0
  209. package/dist/game/spawnPoints.js +5 -0
  210. package/dist/game/systemRuntime.d.ts +50 -0
  211. package/dist/game/systemRuntime.js +157 -0
  212. package/dist/game/systemSchedule.d.ts +72 -0
  213. package/dist/game/systemSchedule.js +242 -0
  214. package/dist/game/toasts.d.ts +43 -0
  215. package/dist/game/toasts.js +44 -0
  216. package/dist/game/trade.d.ts +10 -0
  217. package/dist/game/trade.js +10 -0
  218. package/dist/game/unlocks.d.ts +8 -0
  219. package/dist/game/unlocks.js +16 -0
  220. package/dist/game/vfxInstance.d.ts +138 -0
  221. package/dist/game/vfxInstance.js +96 -0
  222. package/dist/game/worldItem.d.ts +17 -4
  223. package/dist/game/worldItem.js +17 -4
  224. package/dist/gameplay.d.ts +91 -0
  225. package/dist/gameplay.js +91 -0
  226. package/dist/index.d.ts +5 -7
  227. package/dist/index.js +5 -7
  228. package/dist/input/actionBindings.d.ts +24 -5
  229. package/dist/input/actionBindings.js +23 -5
  230. package/dist/input/axisInput.d.ts +13 -1
  231. package/dist/input/axisInput.js +22 -1
  232. package/dist/input/controlGroups.d.ts +67 -0
  233. package/dist/input/controlGroups.js +41 -0
  234. package/dist/input/touchScheme.d.ts +82 -6
  235. package/dist/input/touchScheme.js +123 -10
  236. package/dist/interaction/contextMenu.d.ts +1 -0
  237. package/dist/interaction/contextMenu.js +1 -0
  238. package/dist/interaction/lockpick.d.ts +61 -0
  239. package/dist/interaction/lockpick.js +168 -0
  240. package/dist/interaction/proximityPrompt.d.ts +5 -1
  241. package/dist/interaction/proximityPrompt.js +5 -3
  242. package/dist/interaction/qte.d.ts +5 -0
  243. package/dist/interaction/qte.js +5 -0
  244. package/dist/interaction/skillCheck.d.ts +5 -0
  245. package/dist/interaction/skillCheck.js +5 -0
  246. package/dist/inventory/inventoryModel.d.ts +12 -0
  247. package/dist/inventory/inventoryModel.js +12 -0
  248. package/dist/inventory/shapedGrid.d.ts +16 -0
  249. package/dist/inventory/shapedGrid.js +16 -0
  250. package/dist/inventory/slotModel.d.ts +10 -0
  251. package/dist/inventory/slotModel.js +10 -0
  252. package/dist/item/durability.d.ts +5 -0
  253. package/dist/item/durability.js +5 -0
  254. package/dist/item/itemIdentity.d.ts +171 -0
  255. package/dist/item/itemIdentity.js +138 -0
  256. package/dist/item/itemInstanceRegistry.d.ts +32 -0
  257. package/dist/item/itemInstanceRegistry.js +34 -0
  258. package/dist/item/itemgen.d.ts +163 -0
  259. package/dist/item/itemgen.js +151 -0
  260. package/dist/item/modularItem.d.ts +5 -0
  261. package/dist/item/modularItem.js +5 -0
  262. package/dist/item/use.d.ts +5 -0
  263. package/dist/item/use.js +5 -0
  264. package/dist/item/useBehavior.d.ts +142 -0
  265. package/dist/item/useBehavior.js +105 -0
  266. package/dist/item/weapon.d.ts +5 -0
  267. package/dist/item/weapon.js +5 -0
  268. package/dist/math/scalar.d.ts +25 -0
  269. package/dist/math/scalar.js +47 -0
  270. package/dist/meta/changelog.d.ts +4 -1
  271. package/dist/meta/changelog.js +36 -1
  272. package/dist/movement/avoidance.d.ts +45 -0
  273. package/dist/movement/avoidance.js +123 -0
  274. package/dist/movement/cameraRig.d.ts +8 -0
  275. package/dist/movement/cameraRig.js +8 -0
  276. package/dist/movement/dash.d.ts +11 -0
  277. package/dist/movement/dash.js +11 -0
  278. package/dist/movement/formation.d.ts +135 -0
  279. package/dist/movement/formation.js +194 -0
  280. package/dist/movement/glideModel.d.ts +5 -0
  281. package/dist/movement/glideModel.js +5 -0
  282. package/dist/movement/grappleSwing.d.ts +5 -0
  283. package/dist/movement/grappleSwing.js +5 -0
  284. package/dist/movement/leaderTrail.d.ts +5 -0
  285. package/dist/movement/leaderTrail.js +5 -0
  286. package/dist/movement/movementModel.d.ts +38 -7
  287. package/dist/movement/movementModel.js +54 -13
  288. package/dist/movement/playerMovement.d.ts +41 -0
  289. package/dist/movement/playerMovement.js +236 -0
  290. package/dist/movement/poseState.d.ts +13 -0
  291. package/dist/movement/poseState.js +16 -0
  292. package/dist/movement/steering.d.ts +8 -0
  293. package/dist/movement/steering.js +18 -0
  294. package/dist/multiplayer/combatSnapshot.d.ts +3 -0
  295. package/dist/multiplayer/combatSnapshot.js +3 -0
  296. package/dist/multiplayer/lagCompensation.d.ts +5 -0
  297. package/dist/multiplayer/lagCompensation.js +5 -0
  298. package/dist/multiplayer/presenceModel.d.ts +9 -1
  299. package/dist/multiplayer/presenceModel.js +9 -1
  300. package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
  301. package/dist/multiplayer/simultaneousCommit.js +3 -0
  302. package/dist/multiplayer.d.ts +11 -0
  303. package/dist/multiplayer.js +11 -0
  304. package/dist/nav/pathFollow.d.ts +57 -0
  305. package/dist/nav/pathFollow.js +109 -0
  306. package/dist/orders/orderKinds.d.ts +156 -0
  307. package/dist/orders/orderKinds.js +197 -0
  308. package/dist/orders/orderQueue.d.ts +208 -0
  309. package/dist/orders/orderQueue.js +211 -0
  310. package/dist/physics/drivableVehicle.d.ts +29 -0
  311. package/dist/physics/drivableVehicle.js +16 -0
  312. package/dist/physics/kinematicVehicle.d.ts +21 -1
  313. package/dist/physics/kinematicVehicle.js +23 -8
  314. package/dist/physics/physicsWorld.d.ts +24 -12
  315. package/dist/physics/physicsWorld.js +11 -5
  316. package/dist/physics/radialImpulse.d.ts +25 -0
  317. package/dist/physics/radialImpulse.js +27 -0
  318. package/dist/procedural.d.ts +3 -0
  319. package/dist/procedural.js +3 -0
  320. package/dist/progression/statGraph.d.ts +116 -0
  321. package/dist/progression/statGraph.js +318 -0
  322. package/dist/puzzle/cellGrid.d.ts +9 -0
  323. package/dist/puzzle/cellGrid.js +9 -0
  324. package/dist/puzzle/fallingPiece.d.ts +9 -0
  325. package/dist/puzzle/fallingPiece.js +9 -0
  326. package/dist/puzzle/nonogram.d.ts +39 -0
  327. package/dist/puzzle/nonogram.js +136 -0
  328. package/dist/random/nameGen.d.ts +5 -0
  329. package/dist/random/nameGen.js +5 -0
  330. package/dist/random/pick.d.ts +8 -0
  331. package/dist/random/pick.js +31 -0
  332. package/dist/random/rng.d.ts +24 -0
  333. package/dist/random/rng.js +30 -8
  334. package/dist/random/seedLink.d.ts +4 -0
  335. package/dist/random/seedLink.js +4 -0
  336. package/dist/relation/keyedValues.d.ts +54 -0
  337. package/dist/relation/keyedValues.js +115 -0
  338. package/dist/relation/thresholds.d.ts +62 -0
  339. package/dist/relation/thresholds.js +62 -0
  340. package/dist/render/color.d.ts +12 -0
  341. package/dist/render/color.js +26 -0
  342. package/dist/render/lookPreset.d.ts +41 -0
  343. package/dist/render/lookPreset.js +29 -0
  344. package/dist/render/postProcessing.d.ts +76 -0
  345. package/dist/render/postProcessing.js +21 -0
  346. package/dist/rules/predicate.d.ts +53 -0
  347. package/dist/rules/predicate.js +64 -0
  348. package/dist/rules/ruleEffects.d.ts +38 -0
  349. package/dist/rules/ruleEffects.js +37 -0
  350. package/dist/rules/triggeredRules.d.ts +160 -0
  351. package/dist/rules/triggeredRules.js +241 -0
  352. package/dist/runtime/adapter.d.ts +58 -0
  353. package/dist/runtime/adapter.js +54 -5
  354. package/dist/runtime/cameraDirector.d.ts +1 -0
  355. package/dist/runtime/cameraDirector.js +1 -0
  356. package/dist/runtime/commandRunner.d.ts +1 -0
  357. package/dist/runtime/commandRunner.js +1 -0
  358. package/dist/runtime/context/combatFx.d.ts +23 -0
  359. package/dist/runtime/context/combatFx.js +161 -0
  360. package/dist/runtime/context/registries.d.ts +13 -0
  361. package/dist/runtime/context/registries.js +84 -0
  362. package/dist/runtime/context/worldItems.d.ts +21 -0
  363. package/dist/runtime/context/worldItems.js +37 -0
  364. package/dist/runtime/descriptors/baseline.d.ts +48 -0
  365. package/dist/runtime/descriptors/baseline.js +134 -0
  366. package/dist/runtime/descriptors/features.d.ts +74 -0
  367. package/dist/runtime/descriptors/features.js +281 -0
  368. package/dist/runtime/gameContext.d.ts +163 -19
  369. package/dist/runtime/gameContext.js +385 -339
  370. package/dist/runtime/gameRuntime.d.ts +1 -0
  371. package/dist/runtime/gameRuntime.js +1 -0
  372. package/dist/runtime/headlessRunner.d.ts +60 -0
  373. package/dist/runtime/headlessRunner.js +44 -0
  374. package/dist/runtime/hostPersistence.d.ts +12 -0
  375. package/dist/runtime/hostPersistence.js +12 -0
  376. package/dist/runtime/hostedGameRunner.d.ts +54 -0
  377. package/dist/runtime/hostedGameRunner.js +85 -0
  378. package/dist/runtime/hostedWorldSession.d.ts +73 -0
  379. package/dist/runtime/hostedWorldSession.js +64 -0
  380. package/dist/runtime/inputSnapshot.d.ts +21 -3
  381. package/dist/runtime/inputSnapshot.js +8 -2
  382. package/dist/runtime/motionIntents.d.ts +12 -1
  383. package/dist/runtime/motionIntents.js +26 -1
  384. package/dist/runtime/perContext.d.ts +15 -0
  385. package/dist/runtime/perContext.js +21 -0
  386. package/dist/runtime/runtimeSave.d.ts +79 -0
  387. package/dist/runtime/runtimeSave.js +105 -0
  388. package/dist/runtime/save.d.ts +4 -0
  389. package/dist/runtime/save.js +4 -0
  390. package/dist/runtime/snapshot.d.ts +7 -0
  391. package/dist/runtime/snapshot.js +7 -0
  392. package/dist/runtime/visibility.d.ts +2 -1
  393. package/dist/runtime/visibility.js +2 -1
  394. package/dist/runtime/worldChannel.d.ts +62 -0
  395. package/dist/runtime/worldChannel.js +114 -0
  396. package/dist/runtime/worldMirror.d.ts +36 -0
  397. package/dist/runtime/worldMirror.js +44 -0
  398. package/dist/runtime/worldProjection.d.ts +47 -0
  399. package/dist/runtime/worldProjection.js +52 -0
  400. package/dist/runtime/worldReplication.d.ts +69 -0
  401. package/dist/runtime/worldReplication.js +217 -0
  402. package/dist/runtime/worldSnapshot.d.ts +44 -0
  403. package/dist/runtime/worldSnapshot.js +30 -0
  404. package/dist/scene/assetCatalog.d.ts +22 -0
  405. package/dist/scene/assetCatalog.js +4 -0
  406. package/dist/scene/assetDiagnostics.d.ts +69 -0
  407. package/dist/scene/assetDiagnostics.js +110 -0
  408. package/dist/scene/assetGenerator.d.ts +65 -0
  409. package/dist/scene/assetGenerator.js +64 -0
  410. package/dist/scene/assetSpace.d.ts +137 -0
  411. package/dist/scene/assetSpace.js +259 -0
  412. package/dist/scene/authoredTriggers.d.ts +169 -0
  413. package/dist/scene/authoredTriggers.js +340 -0
  414. package/dist/scene/behaviorRuntime.d.ts +75 -0
  415. package/dist/scene/behaviorRuntime.js +217 -0
  416. package/dist/scene/behaviors.d.ts +14 -2
  417. package/dist/scene/behaviors.js +7 -2
  418. package/dist/scene/bodyBind.d.ts +60 -0
  419. package/dist/scene/bodyBind.js +51 -0
  420. package/dist/scene/builtinSceneKinds.d.ts +5 -0
  421. package/dist/scene/builtinSceneKinds.js +62 -0
  422. package/dist/scene/colliders.d.ts +18 -0
  423. package/dist/scene/colliders.js +61 -1
  424. package/dist/scene/entityStats.d.ts +13 -0
  425. package/dist/scene/entityStats.js +30 -0
  426. package/dist/scene/entityStore.d.ts +41 -1
  427. package/dist/scene/entityStore.js +75 -0
  428. package/dist/scene/facing.d.ts +18 -0
  429. package/dist/scene/facing.js +26 -0
  430. package/dist/scene/modelSockets.d.ts +33 -0
  431. package/dist/scene/modelSockets.js +29 -0
  432. package/dist/scene/objectQuery.d.ts +2 -0
  433. package/dist/scene/objectQuery.js +2 -0
  434. package/dist/scene/objectStore.d.ts +4 -0
  435. package/dist/scene/objectStore.js +6 -0
  436. package/dist/scene/possession.d.ts +8 -0
  437. package/dist/scene/possession.js +14 -0
  438. package/dist/scene/roster.d.ts +3 -0
  439. package/dist/scene/roster.js +12 -0
  440. package/dist/scene/sceneKinds.d.ts +240 -0
  441. package/dist/scene/sceneKinds.js +214 -0
  442. package/dist/scene/sceneOwnership.d.ts +169 -0
  443. package/dist/scene/sceneOwnership.js +179 -0
  444. package/dist/scene/selectionBookmarks.d.ts +93 -0
  445. package/dist/scene/selectionBookmarks.js +122 -0
  446. package/dist/scene/vehicleSeat.d.ts +68 -0
  447. package/dist/scene/vehicleSeat.js +59 -0
  448. package/dist/sensor/concealment.d.ts +3 -0
  449. package/dist/sensor/concealment.js +3 -0
  450. package/dist/sensor/freezeMonitor.d.ts +1 -0
  451. package/dist/sensor/freezeMonitor.js +1 -0
  452. package/dist/sensor/frustumSensor.d.ts +7 -3
  453. package/dist/sensor/frustumSensor.js +7 -3
  454. package/dist/sensor/hiddenStateProbe.d.ts +5 -2
  455. package/dist/sensor/hiddenStateProbe.js +5 -2
  456. package/dist/sensor/recordingBuffer.d.ts +2 -1
  457. package/dist/sensor/recordingBuffer.js +2 -1
  458. package/dist/sensor/replayLoop.d.ts +6 -2
  459. package/dist/sensor/replayLoop.js +6 -2
  460. package/dist/sensor/revealQuery.d.ts +2 -1
  461. package/dist/sensor/revealQuery.js +2 -1
  462. package/dist/sensor/visionCone.d.ts +10 -3
  463. package/dist/sensor/visionCone.js +10 -3
  464. package/dist/session/contestedChannel.d.ts +1 -0
  465. package/dist/session/contestedChannel.js +1 -0
  466. package/dist/session/extraction.d.ts +1 -0
  467. package/dist/session/extraction.js +1 -0
  468. package/dist/session/roles.d.ts +6 -0
  469. package/dist/session/roles.js +6 -0
  470. package/dist/session/roundState.d.ts +8 -0
  471. package/dist/session/roundState.js +2 -0
  472. package/dist/settings/settingsModel.d.ts +1 -0
  473. package/dist/settings/settingsModel.js +1 -0
  474. package/dist/stats/accumulatorMeter.d.ts +6 -0
  475. package/dist/stats/accumulatorMeter.js +6 -0
  476. package/dist/stats/eventMeter.d.ts +5 -0
  477. package/dist/stats/eventMeter.js +5 -0
  478. package/dist/stats/rollCheck.d.ts +5 -0
  479. package/dist/stats/rollCheck.js +5 -0
  480. package/dist/stats/statModifiers.d.ts +5 -0
  481. package/dist/stats/statModifiers.js +5 -0
  482. package/dist/store/defineKeyedStore.d.ts +38 -0
  483. package/dist/store/defineKeyedStore.js +42 -0
  484. package/dist/store/defineStore.d.ts +33 -0
  485. package/dist/store/defineStore.js +35 -0
  486. package/dist/store/observableKeyedStore.d.ts +9 -0
  487. package/dist/store/observableKeyedStore.js +43 -2
  488. package/dist/survival/decayMeter.d.ts +55 -0
  489. package/dist/survival/decayMeter.js +130 -55
  490. package/dist/survival/moodle.d.ts +2 -0
  491. package/dist/survival/regionHealth.d.ts +6 -0
  492. package/dist/survival/regionHealth.js +5 -0
  493. package/dist/tactics/fallingGrid.d.ts +6 -4
  494. package/dist/tactics/fallingGrid.js +6 -4
  495. package/dist/tactics/predictiveQuery.d.ts +3 -0
  496. package/dist/tactics/predictiveQuery.js +3 -0
  497. package/dist/tactics/snapshot.d.ts +2 -0
  498. package/dist/tactics/snapshot.js +2 -0
  499. package/dist/tactics/surface.d.ts +1 -0
  500. package/dist/tactics/surface.js +1 -0
  501. package/dist/tactics/tacticalGrid.d.ts +1 -0
  502. package/dist/tactics/tacticalGrid.js +1 -0
  503. package/dist/time/beatClock.d.ts +14 -4
  504. package/dist/time/beatClock.js +14 -4
  505. package/dist/time/calendarClock.d.ts +3 -0
  506. package/dist/time/calendarClock.js +3 -0
  507. package/dist/time/idleProgress.d.ts +4 -0
  508. package/dist/time/idleProgress.js +4 -0
  509. package/dist/time/simClock.d.ts +2 -0
  510. package/dist/time/simClock.js +20 -5
  511. package/dist/ui/actionModel.d.ts +110 -0
  512. package/dist/ui/actionModel.js +159 -0
  513. package/dist/ui/gameLayout.d.ts +144 -0
  514. package/dist/ui/gameLayout.js +148 -0
  515. package/dist/ui/hudDocument.d.ts +114 -0
  516. package/dist/ui/hudDocument.js +220 -0
  517. package/dist/ui/hudLayout.d.ts +33 -1
  518. package/dist/ui/hudLayout.js +204 -17
  519. package/dist/ui/orientation.d.ts +39 -0
  520. package/dist/ui/orientation.js +49 -0
  521. package/dist/ui/selectionModel.d.ts +92 -0
  522. package/dist/ui/selectionModel.js +88 -0
  523. package/dist/ui/swingTimer.d.ts +42 -0
  524. package/dist/ui/swingTimer.js +38 -0
  525. package/dist/ui/tooltipModel.d.ts +63 -0
  526. package/dist/ui/tooltipModel.js +82 -0
  527. package/dist/ui.d.ts +15 -0
  528. package/dist/ui.js +15 -0
  529. package/dist/visibility/bounds.d.ts +8 -1
  530. package/dist/visibility/bounds.js +8 -1
  531. package/dist/visibility/frustum.d.ts +12 -3
  532. package/dist/visibility/frustum.js +12 -3
  533. package/dist/visibility/spatialIndex.js +34 -20
  534. package/dist/work/jobQueue.d.ts +201 -0
  535. package/dist/work/jobQueue.js +253 -0
  536. package/dist/work/unitTraining.d.ts +58 -0
  537. package/dist/work/unitTraining.js +52 -0
  538. package/dist/world/authoredObjects.d.ts +58 -0
  539. package/dist/world/authoredObjects.js +69 -0
  540. package/dist/world/buildingGenerator.d.ts +18 -0
  541. package/dist/world/buildingGenerator.js +62 -0
  542. package/dist/world/buildings.d.ts +5 -0
  543. package/dist/world/buildings.js +5 -0
  544. package/dist/world/catenary.d.ts +22 -0
  545. package/dist/world/catenary.js +69 -0
  546. package/dist/world/environmentSummary.d.ts +11 -2
  547. package/dist/world/environmentSummary.js +11 -1
  548. package/dist/world/features.d.ts +244 -7
  549. package/dist/world/features.js +92 -4
  550. package/dist/world/footprintGrid.d.ts +59 -0
  551. package/dist/world/footprintGrid.js +141 -0
  552. package/dist/world/geometry.d.ts +64 -0
  553. package/dist/world/geometry.js +94 -0
  554. package/dist/world/grassKind.d.ts +51 -0
  555. package/dist/world/grassKind.js +101 -0
  556. package/dist/world/pathInstances.d.ts +27 -0
  557. package/dist/world/pathInstances.js +27 -0
  558. package/dist/world/pathTerrain.d.ts +80 -0
  559. package/dist/world/pathTerrain.js +142 -0
  560. package/dist/world/placeAsset.d.ts +81 -0
  561. package/dist/world/placeAsset.js +77 -0
  562. package/dist/world/placement.d.ts +4 -0
  563. package/dist/world/placement.js +4 -0
  564. package/dist/world/placementController.d.ts +6 -0
  565. package/dist/world/placementController.js +6 -0
  566. package/dist/world/polyline.d.ts +34 -0
  567. package/dist/world/polyline.js +81 -0
  568. package/dist/world/roads.d.ts +55 -0
  569. package/dist/world/roads.js +184 -0
  570. package/dist/world/scatterRegion.d.ts +164 -0
  571. package/dist/world/scatterRegion.js +409 -0
  572. package/dist/world/sceneShapes.d.ts +43 -0
  573. package/dist/world/sceneShapes.js +1 -0
  574. package/dist/world/segment.d.ts +27 -0
  575. package/dist/world/segment.js +43 -0
  576. package/dist/world/soilKind.d.ts +48 -0
  577. package/dist/world/soilKind.js +92 -0
  578. package/dist/world/spatialSample.d.ts +241 -0
  579. package/dist/world/spatialSample.js +465 -0
  580. package/dist/world/streets.d.ts +80 -0
  581. package/dist/world/streets.js +144 -0
  582. package/dist/world/terraform.d.ts +213 -1
  583. package/dist/world/terraform.js +655 -20
  584. package/dist/world/terrain.d.ts +138 -12
  585. package/dist/world/terrain.js +346 -28
  586. package/dist/world/terrainGuides.d.ts +182 -0
  587. package/dist/world/terrainGuides.js +343 -0
  588. package/dist/world/vec2.d.ts +81 -0
  589. package/dist/world/vec2.js +128 -0
  590. package/dist/world/vec3.d.ts +49 -0
  591. package/dist/world/vec3.js +76 -0
  592. package/dist/world/vegetation.d.ts +71 -0
  593. package/dist/world/vegetation.js +151 -0
  594. package/dist/world/visibilityField.d.ts +154 -0
  595. package/dist/world/visibilityField.js +271 -0
  596. package/dist/world/volumetricClouds.d.ts +52 -0
  597. package/dist/world/volumetricClouds.js +43 -0
  598. package/dist/world/walls.d.ts +9 -0
  599. package/dist/world/walls.js +9 -0
  600. package/dist/world/waterKind.d.ts +55 -0
  601. package/dist/world/waterKind.js +99 -0
  602. package/dist/world.d.ts +132 -0
  603. package/dist/world.js +132 -0
  604. package/package.json +32 -8
  605. package/skills/jgengine/SKILL.md +51 -0
  606. package/skills/jgengine/api.md +434 -0
  607. package/skills/jgengine/capabilities.md +29 -0
  608. package/skills/jgengine/reference-cartridge.md +72 -0
  609. package/skills/jgengine-combat/SKILL.md +34 -0
  610. package/skills/jgengine-combat/api.md +549 -0
  611. package/skills/jgengine-combat/capabilities.md +169 -0
  612. package/skills/jgengine-combat/reference.md +98 -0
  613. package/skills/jgengine-gameplay/SKILL.md +39 -0
  614. package/skills/jgengine-gameplay/api.md +1794 -0
  615. package/skills/jgengine-gameplay/capabilities.md +378 -0
  616. package/skills/jgengine-gameplay/reference-systems.md +60 -0
  617. package/skills/jgengine-world/SKILL.md +38 -0
  618. package/skills/jgengine-world/api.md +2652 -0
  619. package/skills/jgengine-world/capabilities.md +370 -0
  620. package/skills/jgengine-world/reference.md +222 -0
  621. package/dist/cartridge/runtime.d.ts +0 -15
  622. package/dist/cartridge/runtime.js +0 -556
  623. package/dist/cartridge/spec.d.ts +0 -188
  624. package/dist/cartridge/spec.js +0 -19
  625. package/dist/cartridge/validate.d.ts +0 -2
  626. package/dist/cartridge/validate.js +0 -78
  627. package/dist/store/engineStore.d.ts +0 -22
  628. package/dist/store/engineStore.js +0 -50
  629. package/dist/store/features.d.ts +0 -10
  630. package/dist/store/features.js +0 -23
  631. package/llms.txt +0 -4983
@@ -0,0 +1,465 @@
1
+ import { pointInAabb } from "./geometry.js";
2
+ import { pointInPolygon, polygonBounds } from "./scatterRegion.js";
3
+ const DEFAULT_MAX_ATTEMPTS = 30;
4
+ const TWO_PI = Math.PI * 2;
5
+ function distanceSq(a, b) {
6
+ const n = a.length < b.length ? a.length : b.length;
7
+ let sum = 0;
8
+ for (let i = 0; i < n; i += 1) {
9
+ const d = a[i] - b[i];
10
+ sum += d * d;
11
+ }
12
+ return sum;
13
+ }
14
+ /**
15
+ * A uniform spatial hash over cells of `cellSize`, used to enforce minimum separation in O(1)
16
+ * neighborhood checks instead of an O(n²) scan — the allocation-aware index behind batch spacing.
17
+ * @internal
18
+ */
19
+ class SeparationIndex {
20
+ cellSize;
21
+ dimensions;
22
+ buckets = new Map();
23
+ minSq;
24
+ constructor(cellSize, dimensions) {
25
+ this.cellSize = cellSize;
26
+ this.dimensions = dimensions;
27
+ this.minSq = cellSize * cellSize;
28
+ }
29
+ key(cell) {
30
+ return cell.join(":");
31
+ }
32
+ cellOf(point) {
33
+ const cell = [];
34
+ for (let i = 0; i < this.dimensions; i += 1)
35
+ cell.push(Math.floor(point[i] / this.cellSize));
36
+ return cell;
37
+ }
38
+ /** True when `point` sits within `cellSize` of any inserted point. */
39
+ tooClose(point) {
40
+ const base = this.cellOf(point);
41
+ const dims = this.dimensions;
42
+ const stack = [];
43
+ const walk = (axis) => {
44
+ if (axis === dims) {
45
+ const bucket = this.buckets.get(this.key(stack));
46
+ if (bucket !== undefined)
47
+ for (const other of bucket)
48
+ if (distanceSq(point, other) < this.minSq)
49
+ return true;
50
+ return false;
51
+ }
52
+ for (let d = -1; d <= 1; d += 1) {
53
+ stack[axis] = base[axis] + d;
54
+ if (walk(axis + 1))
55
+ return true;
56
+ }
57
+ return false;
58
+ };
59
+ return walk(0);
60
+ }
61
+ insert(point) {
62
+ const key = this.key(this.cellOf(point));
63
+ const bucket = this.buckets.get(key);
64
+ if (bucket !== undefined)
65
+ bucket.push(point);
66
+ else
67
+ this.buckets.set(key, [point]);
68
+ }
69
+ }
70
+ function passesConstraints(point, constraints, index) {
71
+ if (constraints === undefined)
72
+ return index === null || !index.tooClose(point);
73
+ if (constraints.include !== undefined)
74
+ for (const region of constraints.include)
75
+ if (!region.contains(point))
76
+ return false;
77
+ if (constraints.exclude !== undefined)
78
+ for (const region of constraints.exclude)
79
+ if (region.contains(point))
80
+ return false;
81
+ if (index !== null && index.tooClose(point))
82
+ return false;
83
+ if (constraints.accept !== undefined && !constraints.accept(point))
84
+ return false;
85
+ return true;
86
+ }
87
+ function resolveFallback(fallback, last, attempts, reason) {
88
+ if (fallback !== undefined && fallback !== "none") {
89
+ if (fallback === "last-candidate") {
90
+ if (last !== null)
91
+ return { ok: false, point: last, attempts, reason, usedFallback: true };
92
+ }
93
+ else {
94
+ return { ok: false, point: fallback.point, attempts, reason, usedFallback: true };
95
+ }
96
+ }
97
+ return { ok: false, point: null, attempts, reason, usedFallback: false };
98
+ }
99
+ /**
100
+ * Draw one point from `region` that clears every constraint, retrying up to `maxAttempts` times with
101
+ * the injected `rng`, then apply the `fallback` policy. Returns a structured {@link SampleResult} —
102
+ * a clean hit is `ok: true`; exhaustion or a degenerate region is reported with the attempt count and
103
+ * an explicit fallback flag, never a silently-accepted bad point.
104
+ *
105
+ * @capability spatial-sample draw one deterministic position from a region under include/exclude/distance constraints
106
+ */
107
+ export function samplePoint(options) {
108
+ const { region, rng, constraints } = options;
109
+ const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
110
+ if (region.isEmpty)
111
+ return resolveFallback(options.fallback, null, 0, "empty-region");
112
+ let index = null;
113
+ const minSeparation = constraints?.minSeparation ?? 0;
114
+ const placed = options.placed ?? [];
115
+ if (minSeparation > 0 && placed.length > 0) {
116
+ index = new SeparationIndex(minSeparation, region.dimensions);
117
+ for (const point of placed)
118
+ index.insert(point);
119
+ }
120
+ let last = null;
121
+ let attempts = 0;
122
+ while (attempts < maxAttempts) {
123
+ attempts += 1;
124
+ let candidate = region.sample(rng);
125
+ if (constraints?.project !== undefined)
126
+ candidate = constraints.project(candidate);
127
+ if (candidate === null)
128
+ continue;
129
+ last = candidate;
130
+ if (passesConstraints(candidate, constraints, index)) {
131
+ return { ok: true, point: candidate, attempts, reason: "accepted", usedFallback: false };
132
+ }
133
+ }
134
+ return resolveFallback(options.fallback, last, attempts, "exhausted");
135
+ }
136
+ /**
137
+ * Place up to `count` points from `region`, each clearing the shared constraints and honoring
138
+ * `minSeparation` against every point already placed in this batch (via a spatial hash, not an
139
+ * O(n²) scan). Order is deterministic for a given `rng` stream. Batches never silently under-fill:
140
+ * the result reports `placed`, `complete`, and the total attempt count.
141
+ *
142
+ * @capability spatial-sample-batch place many deterministic spaced points from a region with minimum separation
143
+ */
144
+ export function sampleBatch(options) {
145
+ const { region, rng, constraints } = options;
146
+ const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
147
+ const requested = Math.max(0, Math.floor(options.count));
148
+ const points = [];
149
+ if (requested === 0 || region.isEmpty) {
150
+ return { points, requested, placed: 0, complete: requested === 0, attempts: 0 };
151
+ }
152
+ const minSeparation = constraints?.minSeparation ?? 0;
153
+ const index = minSeparation > 0 ? new SeparationIndex(minSeparation, region.dimensions) : null;
154
+ let attempts = 0;
155
+ for (let i = 0; i < requested; i += 1) {
156
+ let placed = null;
157
+ let tries = 0;
158
+ while (tries < maxAttempts) {
159
+ tries += 1;
160
+ attempts += 1;
161
+ let candidate = region.sample(rng);
162
+ if (constraints?.project !== undefined)
163
+ candidate = constraints.project(candidate);
164
+ if (candidate === null)
165
+ continue;
166
+ if (passesConstraints(candidate, constraints, index)) {
167
+ placed = candidate;
168
+ break;
169
+ }
170
+ }
171
+ if (placed === null)
172
+ break;
173
+ points.push(placed);
174
+ if (index !== null)
175
+ index.insert(placed);
176
+ }
177
+ return { points, requested, placed: points.length, complete: points.length === requested, attempts };
178
+ }
179
+ /**
180
+ * A fixed set of candidate points sampled by (optionally weighted) selection — the "spawn point
181
+ * table" region. `contains` is exact membership. Empty when the set is empty.
182
+ *
183
+ * @capability spatial-region-point-set sample from a fixed, optionally weighted candidate point table
184
+ */
185
+ export function pointSetRegion(points, options = {}) {
186
+ const pool = points.map((p) => [p[0], p[1]]);
187
+ const weights = options.weights;
188
+ const total = weights === undefined ? pool.length : weights.reduce((sum, w) => sum + Math.max(0, w), 0);
189
+ return {
190
+ dimensions: 2,
191
+ isEmpty: pool.length === 0 || total <= 0,
192
+ sample(rng) {
193
+ if (weights === undefined)
194
+ return pool[Math.min(pool.length - 1, Math.floor(rng() * pool.length))];
195
+ let roll = rng() * total;
196
+ for (let i = 0; i < pool.length; i += 1) {
197
+ roll -= Math.max(0, weights[i] ?? 0);
198
+ if (roll <= 0)
199
+ return pool[i];
200
+ }
201
+ return pool[pool.length - 1];
202
+ },
203
+ contains(point) {
204
+ return pool.some((p) => p[0] === point[0] && p[1] === point[1]);
205
+ },
206
+ };
207
+ }
208
+ /**
209
+ * An axis-aligned rectangle on the XZ plane. `"uniform"` spreads evenly (draws x then z);
210
+ * `"edge"` biases onto a boundary band of `edgeThickness` meters (perimeter-weighted side, then
211
+ * inward depth) — the two are never conflated, the caller opts in.
212
+ */
213
+ export function rectRegion(area, options = {}) {
214
+ const width = area.maxX - area.minX;
215
+ const depth = area.maxZ - area.minZ;
216
+ const distribution = options.distribution ?? "uniform";
217
+ const edgeThickness = Math.max(0, options.edgeThickness ?? Math.min(width, depth) * 0.25);
218
+ return {
219
+ dimensions: 2,
220
+ isEmpty: !(width > 0) || !(depth > 0),
221
+ sample(rng) {
222
+ if (distribution === "edge") {
223
+ const perim = 2 * (width + depth);
224
+ const sidePick = rng() * perim;
225
+ const t = rng();
226
+ const inset = Math.min(edgeThickness, Math.min(width, depth) / 2) * rng();
227
+ if (sidePick < width)
228
+ return [area.minX + t * width, area.minZ + inset];
229
+ if (sidePick < width + depth)
230
+ return [area.maxX - inset, area.minZ + t * depth];
231
+ if (sidePick < 2 * width + depth)
232
+ return [area.minX + t * width, area.maxZ - inset];
233
+ return [area.minX + inset, area.minZ + t * depth];
234
+ }
235
+ const x = area.minX + rng() * width;
236
+ const z = area.minZ + rng() * depth;
237
+ return [x, z];
238
+ },
239
+ contains(point) {
240
+ return pointInAabb(point, area);
241
+ },
242
+ };
243
+ }
244
+ function radialRadius(rng, inner, outer, distribution) {
245
+ const u = rng();
246
+ if (distribution === "area")
247
+ return Math.sqrt(inner * inner + u * (outer * outer - inner * inner));
248
+ return inner + u * (outer - inner);
249
+ }
250
+ /**
251
+ * A filled circle. `"area"` is area-uniform (√-corrected radius, even density); `"radial"` is
252
+ * radius-uniform (clumps toward the center). Angle is drawn first, then radius — matching the common
253
+ * `angle = rng()·2π; r = rng()·R` idiom so migrations keep their stream.
254
+ */
255
+ export function discRegion(center, radius, options = {}) {
256
+ const distribution = options.distribution ?? "area";
257
+ const r = Math.max(0, radius);
258
+ return {
259
+ dimensions: 2,
260
+ isEmpty: !(r > 0),
261
+ sample(rng) {
262
+ const angle = rng() * TWO_PI;
263
+ const dist = radialRadius(rng, 0, r, distribution);
264
+ return [center[0] + Math.cos(angle) * dist, center[1] + Math.sin(angle) * dist];
265
+ },
266
+ contains(point) {
267
+ return distanceSq(point, center) <= r * r;
268
+ },
269
+ };
270
+ }
271
+ /**
272
+ * A ring (annulus) between `innerRadius` and `outerRadius`. `"area"` fills the band with even
273
+ * density; `"radial"` spreads uniformly in radius. Angle first, then radius.
274
+ */
275
+ export function annulusRegion(center, innerRadius, outerRadius, options = {}) {
276
+ const distribution = options.distribution ?? "area";
277
+ const inner = Math.max(0, Math.min(innerRadius, outerRadius));
278
+ const outer = Math.max(innerRadius, outerRadius, 0);
279
+ return {
280
+ dimensions: 2,
281
+ isEmpty: !(outer > 0) || outer <= inner,
282
+ sample(rng) {
283
+ const angle = rng() * TWO_PI;
284
+ const dist = radialRadius(rng, inner, outer, distribution);
285
+ return [center[0] + Math.cos(angle) * dist, center[1] + Math.sin(angle) * dist];
286
+ },
287
+ contains(point) {
288
+ const d2 = distanceSq(point, center);
289
+ return d2 >= inner * inner && d2 <= outer * outer;
290
+ },
291
+ };
292
+ }
293
+ /**
294
+ * An arbitrary closed polygon on the XZ plane. Candidates are drawn uniformly from the polygon's
295
+ * bounding box and gated by point-in-polygon `contains`, so a run's draw count stays fixed (the
296
+ * sampler's attempt budget bounds the rejection, not a hidden inner loop).
297
+ *
298
+ * @capability spatial-region-polygon sample within an arbitrary closed polygon on the XZ plane
299
+ */
300
+ export function polygonRegion(polygon) {
301
+ const bounds = polygonBounds(polygon);
302
+ const width = bounds === null ? 0 : bounds.maxX - bounds.minX;
303
+ const depth = bounds === null ? 0 : bounds.maxZ - bounds.minZ;
304
+ return {
305
+ dimensions: 2,
306
+ isEmpty: bounds === null || polygon.length < 3 || !(width > 0) || !(depth > 0),
307
+ sample(rng) {
308
+ const b = bounds ?? { minX: 0, minZ: 0, maxX: 0, maxZ: 0 };
309
+ return [b.minX + rng() * width, b.minZ + rng() * depth];
310
+ },
311
+ contains(point) {
312
+ return pointInPolygon(point, polygon);
313
+ },
314
+ };
315
+ }
316
+ /**
317
+ * A composite that first picks one member by weight, then delegates to its sampler — the
318
+ * "weighted subregions" distribution policy. `contains` is true when any member contains the point.
319
+ *
320
+ * @capability spatial-region-weighted compose sub-regions behind a weighted selection policy
321
+ */
322
+ export function weightedRegion(entries) {
323
+ const usable = entries.filter((e) => e.weight > 0 && !e.region.isEmpty);
324
+ const total = usable.reduce((sum, e) => sum + e.weight, 0);
325
+ const dimensions = entries[0]?.region.dimensions ?? 2;
326
+ return {
327
+ dimensions,
328
+ isEmpty: usable.length === 0,
329
+ sample(rng) {
330
+ let roll = rng() * total;
331
+ for (const entry of usable) {
332
+ roll -= entry.weight;
333
+ if (roll <= 0)
334
+ return entry.region.sample(rng);
335
+ }
336
+ return usable[usable.length - 1].region.sample(rng);
337
+ },
338
+ contains(point) {
339
+ return entries.some((e) => e.region.contains(point));
340
+ },
341
+ };
342
+ }
343
+ /**
344
+ * Wrap a caller-defined sampler and bounds test as a {@link SampleRegion} — the escape hatch for
345
+ * regions the built-ins do not cover (a navmesh cell, a heightfield mask, a spline tube).
346
+ *
347
+ * @capability spatial-region-custom wrap a caller-defined sampler and bounds test as a region
348
+ */
349
+ export function customRegion(spec) {
350
+ return {
351
+ dimensions: spec.dimensions,
352
+ isEmpty: spec.isEmpty ?? false,
353
+ sample: spec.sample,
354
+ contains: spec.contains,
355
+ };
356
+ }
357
+ // ---------------------------------------------------------------------------
358
+ // 3D region builders
359
+ // ---------------------------------------------------------------------------
360
+ /**
361
+ * An axis-aligned box `[min..max]` in 3D. Uniform density; draws x, y, z in order.
362
+ *
363
+ * @capability spatial-region-box sample uniformly within an axis-aligned 3D box
364
+ */
365
+ export function boxRegion(min, max) {
366
+ const size = [max[0] - min[0], max[1] - min[1], max[2] - min[2]];
367
+ return {
368
+ dimensions: 3,
369
+ isEmpty: !(size[0] > 0) || !(size[1] > 0) || !(size[2] > 0),
370
+ sample(rng) {
371
+ return [min[0] + rng() * size[0], min[1] + rng() * size[1], min[2] + rng() * size[2]];
372
+ },
373
+ contains(point) {
374
+ return (point[0] >= min[0] && point[0] <= max[0] &&
375
+ point[1] >= min[1] && point[1] <= max[1] &&
376
+ point[2] >= min[2] && point[2] <= max[2]);
377
+ },
378
+ };
379
+ }
380
+ function sphereDirection(rng) {
381
+ const cosTheta = 1 - 2 * rng();
382
+ const sinTheta = Math.sqrt(Math.max(0, 1 - cosTheta * cosTheta));
383
+ const phi = rng() * TWO_PI;
384
+ return [sinTheta * Math.cos(phi), sinTheta * Math.sin(phi), cosTheta];
385
+ }
386
+ function volumeRadius(rng, inner, outer, distribution) {
387
+ const u = rng();
388
+ if (distribution === "volume")
389
+ return Math.cbrt(inner ** 3 + u * (outer ** 3 - inner ** 3));
390
+ return inner + u * (outer - inner);
391
+ }
392
+ /**
393
+ * A filled ball. `"volume"` is volume-uniform (∛-corrected radius); `"radial"` is radius-uniform.
394
+ * Direction is drawn first (two draws), then radius.
395
+ *
396
+ * @capability spatial-region-sphere sample within a filled 3D ball, volume- or radius-uniform
397
+ */
398
+ export function sphereRegion(center, radius, options = {}) {
399
+ const distribution = options.distribution ?? "volume";
400
+ const r = Math.max(0, radius);
401
+ return {
402
+ dimensions: 3,
403
+ isEmpty: !(r > 0),
404
+ sample(rng) {
405
+ const dir = sphereDirection(rng);
406
+ const dist = volumeRadius(rng, 0, r, distribution);
407
+ return [center[0] + dir[0] * dist, center[1] + dir[1] * dist, center[2] + dir[2] * dist];
408
+ },
409
+ contains(point) {
410
+ return distanceSq(point, center) <= r * r;
411
+ },
412
+ };
413
+ }
414
+ /**
415
+ * A spherical shell between `innerRadius` and `outerRadius`. `"volume"` fills the shell with even
416
+ * density; `"radial"` spreads uniformly in radius. Direction first, then radius.
417
+ *
418
+ * @capability spatial-region-shell sample within a 3D spherical shell, volume- or radius-uniform
419
+ */
420
+ export function shellRegion(center, innerRadius, outerRadius, options = {}) {
421
+ const distribution = options.distribution ?? "volume";
422
+ const inner = Math.max(0, Math.min(innerRadius, outerRadius));
423
+ const outer = Math.max(innerRadius, outerRadius, 0);
424
+ return {
425
+ dimensions: 3,
426
+ isEmpty: !(outer > 0) || outer <= inner,
427
+ sample(rng) {
428
+ const dir = sphereDirection(rng);
429
+ const dist = volumeRadius(rng, inner, outer, distribution);
430
+ return [center[0] + dir[0] * dist, center[1] + dir[1] * dist, center[2] + dir[2] * dist];
431
+ },
432
+ contains(point) {
433
+ const d2 = distanceSq(point, center);
434
+ return d2 >= inner * inner && d2 <= outer * outer;
435
+ },
436
+ };
437
+ }
438
+ /**
439
+ * Stratified 2D sampling: one jittered point per grid cell over `area`, in deterministic row-major
440
+ * order. Unlike pure rejection sampling this guarantees even coverage (no clumps, no gaps) — the
441
+ * distinct "stratified" distribution policy, kept separate from area-uniform draws.
442
+ *
443
+ * @capability spatial-sample-stratified evenly cover an area with one jittered point per grid cell, deterministic
444
+ */
445
+ export function sampleStratified(options) {
446
+ const { area, rng } = options;
447
+ const cols = Math.max(0, Math.floor(options.cols));
448
+ const rows = Math.max(0, Math.floor(options.rows));
449
+ const width = area.maxX - area.minX;
450
+ const depth = area.maxZ - area.minZ;
451
+ if (cols === 0 || rows === 0 || !(width > 0) || !(depth > 0))
452
+ return [];
453
+ const jitter = Math.min(1, Math.max(0, options.jitter ?? 1));
454
+ const cellW = width / cols;
455
+ const cellD = depth / rows;
456
+ const points = [];
457
+ for (let row = 0; row < rows; row += 1) {
458
+ for (let col = 0; col < cols; col += 1) {
459
+ const jx = 0.5 + jitter * (rng() - 0.5);
460
+ const jz = 0.5 + jitter * (rng() - 0.5);
461
+ points.push([area.minX + (col + jx) * cellW, area.minZ + (row + jz) * cellD]);
462
+ }
463
+ }
464
+ return points;
465
+ }
@@ -0,0 +1,80 @@
1
+ import type { RoadEnvironmentDescriptor } from "./features.js";
2
+ import { type RoadPoint } from "./roads.js";
3
+ /**
4
+ * Offset a centerline sideways by a signed distance along its local perpendicular — the
5
+ * building block for lanes, curb lines, and sidewalk paths. Positive offsets fall on the
6
+ * left of the direction of travel, negative on the right.
7
+ */
8
+ export declare function offsetPath(path: readonly RoadPoint[], offset: number): readonly RoadPoint[];
9
+ /** A directed lane derived from a road: an offset centerline plus its direction of travel. */
10
+ export interface StreetLane {
11
+ /** Lane centerline, ordered in the direction of travel. */
12
+ path: readonly RoadPoint[];
13
+ /** "forward" runs with the road's declared path order; "reverse" runs against it. */
14
+ direction: "forward" | "reverse";
15
+ }
16
+ /**
17
+ * Two right-hand-traffic lane centerlines for a road — each offset a quarter of the drivable
18
+ * width from the center and ordered in its direction of travel. Feed a lane's `path` straight
19
+ * into `nav/pathFollow` for traffic AI, or use its endpoints as directed car spawn points.
20
+ */
21
+ export declare function laneCenters(road: RoadEnvironmentDescriptor): readonly [StreetLane, StreetLane];
22
+ /** Resolved sidewalk band widths for a road; zero when the road declares no sidewalk. */
23
+ export declare function sidewalkWidthOf(road: RoadEnvironmentDescriptor): number;
24
+ /**
25
+ * The two sidewalk walking paths of a road — offset polylines running down the middle of each
26
+ * sidewalk band. Pedestrians spawn and route along these instead of the asphalt.
27
+ */
28
+ export declare function sidewalkPaths(road: RoadEnvironmentDescriptor): readonly (readonly RoadPoint[])[];
29
+ /** A placement anchor on the curb line: position, outward-facing heading, and which side it sits on. */
30
+ export interface FurnitureSpot {
31
+ position: RoadPoint;
32
+ /** Yaw (radians, engine `rotationY` convention) facing away from the road. */
33
+ heading: number;
34
+ side: "left" | "right";
35
+ /** Arc-length distance along the road at this spot. */
36
+ along: number;
37
+ }
38
+ /** Options for {@link furnitureSpots}. */
39
+ export interface FurnitureSpotOptions {
40
+ /** Distance between consecutive spots along the road. Default 24. */
41
+ spacing?: number;
42
+ /** Which curb lines to populate. Default "both". */
43
+ sides?: "both" | "left" | "right";
44
+ /** Alternate sides spot-by-spot instead of mirroring every spot. Default true. */
45
+ stagger?: boolean;
46
+ /** Extra outward shift past the curb line (e.g. to center furniture in the sidewalk). Default 0. */
47
+ outset?: number;
48
+ }
49
+ /**
50
+ * Evenly spaced street-furniture anchors along a road's curb lines — streetlights, palms, signs,
51
+ * hydrants, benches. Each spot sits just outside the asphalt (plus `outset`), faces away from
52
+ * the street, and alternates sides by default so lights stagger like a real avenue. This is the
53
+ * answer to "where do I put it": furniture is an asset of the street, never a hand-typed coordinate.
54
+ */
55
+ export declare function furnitureSpots(road: RoadEnvironmentDescriptor, options?: FurnitureSpotOptions): readonly FurnitureSpot[];
56
+ /** Options for {@link parkingSpots}. */
57
+ export interface ParkingSpotOptions {
58
+ /** Distance between consecutive parked-car anchors. Default 18. */
59
+ spacing?: number;
60
+ /** Which side(s) of the street to line with parking. Default "both". */
61
+ sides?: "both" | "left" | "right";
62
+ }
63
+ /** A curbside parking anchor: position at the road edge and a heading parallel to the street. */
64
+ export interface ParkingSpot {
65
+ position: RoadPoint;
66
+ /** Yaw (radians) aligned with the direction of travel on that side (right-hand traffic). */
67
+ heading: number;
68
+ side: "left" | "right";
69
+ }
70
+ /**
71
+ * Curbside parking anchors along a road: hugging the edge of the asphalt, headed parallel to the
72
+ * street in that side's direction of travel. Spawn parked vehicles here instead of eyeballing
73
+ * coordinates in the middle of the carriageway.
74
+ */
75
+ export declare function parkingSpots(road: RoadEnvironmentDescriptor, options?: ParkingSpotOptions): readonly ParkingSpot[];
76
+ /**
77
+ * A deterministic point on one of a road's sidewalks at a normalized position — `side` picks the
78
+ * band, `fraction` (0..1) picks how far along. The canonical pedestrian spawn helper.
79
+ */
80
+ export declare function sidewalkPoint(road: RoadEnvironmentDescriptor, side: "left" | "right", fraction: number): RoadPoint | null;
@@ -0,0 +1,144 @@
1
+ import { pathLength } from "./roads.js";
2
+ function normalAt(path, index) {
3
+ const prev = path[Math.max(0, index - 1)];
4
+ const next = path[Math.min(path.length - 1, index + 1)];
5
+ const dx = next[0] - prev[0];
6
+ const dz = next[1] - prev[1];
7
+ const length = Math.hypot(dx, dz) || 1;
8
+ return [-dz / length, dx / length];
9
+ }
10
+ /**
11
+ * Offset a centerline sideways by a signed distance along its local perpendicular — the
12
+ * building block for lanes, curb lines, and sidewalk paths. Positive offsets fall on the
13
+ * left of the direction of travel, negative on the right.
14
+ */
15
+ export function offsetPath(path, offset) {
16
+ return path.map((point, index) => {
17
+ const [nx, nz] = normalAt(path, index);
18
+ return [point[0] + nx * offset, point[1] + nz * offset];
19
+ });
20
+ }
21
+ /**
22
+ * Two right-hand-traffic lane centerlines for a road — each offset a quarter of the drivable
23
+ * width from the center and ordered in its direction of travel. Feed a lane's `path` straight
24
+ * into `nav/pathFollow` for traffic AI, or use its endpoints as directed car spawn points.
25
+ */
26
+ export function laneCenters(road) {
27
+ const laneOffset = road.width / 4;
28
+ const forward = offsetPath(road.path, -laneOffset);
29
+ const reverse = offsetPath(road.path, laneOffset);
30
+ return [
31
+ { path: forward, direction: "forward" },
32
+ { path: [...reverse].reverse(), direction: "reverse" },
33
+ ];
34
+ }
35
+ /** Resolved sidewalk band widths for a road; zero when the road declares no sidewalk. */
36
+ export function sidewalkWidthOf(road) {
37
+ return road.sidewalk === false ? 0 : road.sidewalk.width;
38
+ }
39
+ /**
40
+ * The two sidewalk walking paths of a road — offset polylines running down the middle of each
41
+ * sidewalk band. Pedestrians spawn and route along these instead of the asphalt.
42
+ */
43
+ export function sidewalkPaths(road) {
44
+ const width = sidewalkWidthOf(road);
45
+ if (width <= 0)
46
+ return [];
47
+ const offset = road.width / 2 + width / 2;
48
+ return [offsetPath(road.path, offset), offsetPath(road.path, -offset)];
49
+ }
50
+ function pointAlong(path, along) {
51
+ let remaining = along;
52
+ for (let i = 0; i < path.length - 1; i += 1) {
53
+ const a = path[i];
54
+ const b = path[i + 1];
55
+ const segLength = Math.hypot(b[0] - a[0], b[1] - a[1]);
56
+ if (remaining <= segLength || i === path.length - 2) {
57
+ const t = segLength <= 0 ? 0 : Math.min(1, remaining / segLength);
58
+ const length = segLength || 1;
59
+ return {
60
+ point: [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t],
61
+ tangent: [(b[0] - a[0]) / length, (b[1] - a[1]) / length],
62
+ };
63
+ }
64
+ remaining -= segLength;
65
+ }
66
+ const first = path[0] ?? [0, 0];
67
+ return { point: first, tangent: [0, 1] };
68
+ }
69
+ /**
70
+ * Evenly spaced street-furniture anchors along a road's curb lines — streetlights, palms, signs,
71
+ * hydrants, benches. Each spot sits just outside the asphalt (plus `outset`), faces away from
72
+ * the street, and alternates sides by default so lights stagger like a real avenue. This is the
73
+ * answer to "where do I put it": furniture is an asset of the street, never a hand-typed coordinate.
74
+ */
75
+ export function furnitureSpots(road, options = {}) {
76
+ const spacing = options.spacing ?? 24;
77
+ const sides = options.sides ?? "both";
78
+ const stagger = options.stagger ?? true;
79
+ const outset = options.outset ?? 0;
80
+ if (spacing <= 0)
81
+ return [];
82
+ const total = pathLength(road.path);
83
+ const curbOffset = road.width / 2 + 0.6 + outset;
84
+ const spots = [];
85
+ let index = 0;
86
+ for (let along = spacing / 2; along < total; along += spacing) {
87
+ const { point, tangent } = pointAlong(road.path, along);
88
+ const normal = [-tangent[1], tangent[0]];
89
+ const wanted = sides === "both" ? (stagger ? [index % 2 === 0 ? "left" : "right"] : ["left", "right"]) : [sides];
90
+ for (const side of wanted) {
91
+ const sign = side === "left" ? 1 : -1;
92
+ const position = [point[0] + normal[0] * curbOffset * sign, point[1] + normal[1] * curbOffset * sign];
93
+ spots.push({
94
+ position,
95
+ heading: Math.atan2(normal[0] * sign, normal[1] * sign),
96
+ side,
97
+ along,
98
+ });
99
+ }
100
+ index += 1;
101
+ }
102
+ return spots;
103
+ }
104
+ /**
105
+ * Curbside parking anchors along a road: hugging the edge of the asphalt, headed parallel to the
106
+ * street in that side's direction of travel. Spawn parked vehicles here instead of eyeballing
107
+ * coordinates in the middle of the carriageway.
108
+ */
109
+ export function parkingSpots(road, options = {}) {
110
+ const spacing = options.spacing ?? 18;
111
+ const sides = options.sides ?? "both";
112
+ if (spacing <= 0)
113
+ return [];
114
+ const total = pathLength(road.path);
115
+ const edgeOffset = road.width / 2 - 1.2;
116
+ const spots = [];
117
+ for (let along = spacing; along < total - spacing / 2; along += spacing) {
118
+ const { point, tangent } = pointAlong(road.path, along);
119
+ const normal = [-tangent[1], tangent[0]];
120
+ const wanted = sides === "both" ? ["left", "right"] : [sides];
121
+ for (const side of wanted) {
122
+ const sign = side === "left" ? 1 : -1;
123
+ const dir = side === "left" ? 1 : -1;
124
+ spots.push({
125
+ position: [point[0] + normal[0] * edgeOffset * sign, point[1] + normal[1] * edgeOffset * sign],
126
+ heading: Math.atan2(tangent[0] * dir, tangent[1] * dir),
127
+ side,
128
+ });
129
+ }
130
+ }
131
+ return spots;
132
+ }
133
+ /**
134
+ * A deterministic point on one of a road's sidewalks at a normalized position — `side` picks the
135
+ * band, `fraction` (0..1) picks how far along. The canonical pedestrian spawn helper.
136
+ */
137
+ export function sidewalkPoint(road, side, fraction) {
138
+ const paths = sidewalkPaths(road);
139
+ const path = side === "left" ? paths[0] : paths[1];
140
+ if (path === undefined)
141
+ return null;
142
+ const along = Math.max(0, Math.min(1, fraction)) * pathLength(path);
143
+ return pointAlong(path, along).point;
144
+ }