@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
@@ -65,5 +65,11 @@ export interface PlacementController {
65
65
  commit(): PlacementCommit | null;
66
66
  reset(): void;
67
67
  }
68
+ /** Maps 0–3 quarter turns onto radians for ghost/commit rotation. */
68
69
  export declare function quarterTurnsToRotationY(quarterTurns: number): number;
70
+ /**
71
+ * Headless placement ghost: hover → valid/invalid preview, rotate, grid/free/surface snap, commit.
72
+ * Pair with `@jgengine/shell/structures` `PlacementGhost` and {@link placeAssetFromCommit}.
73
+ * @capability placement-controller interactive build-mode ghost preview and commit
74
+ */
69
75
  export declare function createPlacementController(config: PlacementControllerConfig): PlacementController;
@@ -5,10 +5,16 @@ const DEFAULT_SLOT_RADIUS = 1.5;
5
5
  function distanceVec3(a, b) {
6
6
  return Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]);
7
7
  }
8
+ /** Maps 0–3 quarter turns onto radians for ghost/commit rotation. */
8
9
  export function quarterTurnsToRotationY(quarterTurns) {
9
10
  const turns = ((quarterTurns % 4) + 4) % 4;
10
11
  return turns === 0 ? 0 : -turns * (Math.PI / 2);
11
12
  }
13
+ /**
14
+ * Headless placement ghost: hover → valid/invalid preview, rotate, grid/free/surface snap, commit.
15
+ * Pair with `@jgengine/shell/structures` `PlacementGhost` and {@link placeAssetFromCommit}.
16
+ * @capability placement-controller interactive build-mode ghost preview and commit
17
+ */
12
18
  export function createPlacementController(config) {
13
19
  let footprint = config.footprint;
14
20
  let rules = config.rules ?? {};
@@ -0,0 +1,40 @@
1
+ import { type Vec3 } from "./catenary.js";
2
+ import { type ParamSchema, type ParsedParams, type SceneKindObject, type SceneKindResolveContext } from "../scene/sceneKinds.js";
3
+ /**
4
+ * The editor path kind marking a polyline as a pole/cable run.
5
+ * @capability pole-line editor-authorable poles + sagging cables along a path
6
+ */
7
+ export declare const POLE_LINE_KIND = "pole_line";
8
+ /** One placed pole: grounded base position plus facing yaw along the run. */
9
+ export interface Pole {
10
+ id: string;
11
+ position: Vec3;
12
+ yaw: number;
13
+ }
14
+ /** One resolved cable span: a point string to loft into a tube, plus its radius. */
15
+ export interface Cable {
16
+ id: string;
17
+ points: Vec3[];
18
+ radius: number;
19
+ }
20
+ /** The renderable payload the resolver returns and the shell renderer consumes. */
21
+ export interface ResolvedPoleLine {
22
+ poles: Pole[];
23
+ cables: Cable[];
24
+ poleHeight: number;
25
+ poleAsset: string;
26
+ /** Wires per span — drives the renderer's crossarm width and insulator count. */
27
+ wireCount: number;
28
+ /** Lateral spread between adjacent wires, meters — the renderer hangs insulators at these offsets. */
29
+ wireSpacing: number;
30
+ }
31
+ /** The pole-line parameter schema — drives the inspector and `meta` parse via the studio seam. */
32
+ export declare const POLE_LINE_SCHEMA: ParamSchema;
33
+ /**
34
+ * Resolve poles + cables from a document object's points and parsed params. Poles come from the
35
+ * generic `placeAlongPath` sampler; between each consecutive pair, `wireCount` parallel cables are
36
+ * strung with lateral offset and quadratic-Bézier `sag` (deeper on longer spans). Pure data.
37
+ */
38
+ export declare function resolvePoleLine(object: SceneKindObject, params: ParsedParams, context?: SceneKindResolveContext): ResolvedPoleLine;
39
+ /** Registers the pole-line scene kind (schema + resolver + inspector note). Called by `registerBuiltinSceneKinds`. @internal */
40
+ export declare function registerPoleLineKind(): void;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * `pole_line` studio: poles + sagging cables strung along an editor-drawn path — power lines, fences,
3
+ * streetlight runs, ziplines. Pure config here (spacing/height/wire params + a resolver built from the
4
+ * generic `placeAlongPath` and `sagCurve` primitives); the instanced pole/cable meshes live in the
5
+ * `shell` renderer. An engine environment kind (like water/grass_field/soil) so wire runs are
6
+ * drawable and slider-authorable in every editor session and persisted in `editor.scene.json` —
7
+ * promoted from `examples/studios` for studio/editor parity (#1101).
8
+ */
9
+ import { placeAlongPath } from "./pathInstances.js";
10
+ import { sagCurve } from "./catenary.js";
11
+ import { registerSceneKind, } from "../scene/sceneKinds.js";
12
+ /**
13
+ * The editor path kind marking a polyline as a pole/cable run.
14
+ * @capability pole-line editor-authorable poles + sagging cables along a path
15
+ */
16
+ export const POLE_LINE_KIND = "pole_line";
17
+ /** The pole-line parameter schema — drives the inspector and `meta` parse via the studio seam. */
18
+ export const POLE_LINE_SCHEMA = {
19
+ fields: [
20
+ { type: "text", key: "poleAsset", label: "pole asset", default: "", group: "poles" },
21
+ { type: "range", key: "spacing", label: "spacing", min: 2, max: 40, step: 0.5, default: 8, unit: "m", group: "poles" },
22
+ { type: "range", key: "poleHeight", label: "pole height", min: 1, max: 20, step: 0.25, default: 6, unit: "m", group: "poles" },
23
+ { type: "bool", key: "snapToTerrain", label: "snap to ground", default: true, group: "poles" },
24
+ { type: "action", key: "randomizePoles", label: "randomize poles", action: "randomize", group: "poles" },
25
+ { type: "range", key: "wireCount", label: "wires", min: 0, max: 8, step: 1, default: 3, group: "cables" },
26
+ { type: "range", key: "wireSpacing", label: "wire spread", min: 0, max: 3, step: 0.05, default: 0.5, unit: "m", group: "cables" },
27
+ { type: "range", key: "cableRadius", label: "cable radius", min: 0.01, max: 0.5, step: 0.01, default: 0.05, unit: "m", group: "cables" },
28
+ { type: "range", key: "sag", label: "sag", min: 0, max: 6, step: 0.1, default: 0.8, unit: "m", group: "cables" },
29
+ { type: "range", key: "sagPerMeter", label: "sag / m", min: 0, max: 0.3, step: 0.005, default: 0.04, group: "cables" },
30
+ { type: "range", key: "cableSegments", label: "cable smoothness", min: 2, max: 48, step: 1, default: 12, group: "cables" },
31
+ { type: "seed", key: "seed", label: "seed", default: "", group: "cables" },
32
+ { type: "action", key: "randomizeCables", label: "randomize cables", action: "randomize", group: "cables" },
33
+ ],
34
+ groups: [
35
+ { id: "poles", label: "Poles" },
36
+ { id: "cables", label: "Cables" },
37
+ ],
38
+ };
39
+ /**
40
+ * Resolve poles + cables from a document object's points and parsed params. Poles come from the
41
+ * generic `placeAlongPath` sampler; between each consecutive pair, `wireCount` parallel cables are
42
+ * strung with lateral offset and quadratic-Bézier `sag` (deeper on longer spans). Pure data.
43
+ */
44
+ export function resolvePoleLine(object, params, context) {
45
+ const spacing = params["spacing"];
46
+ const poleHeight = params["poleHeight"];
47
+ const wireCount = Math.round(params["wireCount"]);
48
+ const wireSpacing = params["wireSpacing"];
49
+ const cableRadius = params["cableRadius"];
50
+ const sag = params["sag"];
51
+ const sagPerMeter = params["sagPerMeter"];
52
+ const cableSegments = Math.round(params["cableSegments"]);
53
+ const snap = params["snapToTerrain"];
54
+ const placed = placeAlongPath(object.points ?? [], {
55
+ spacing,
56
+ ...(snap && context?.sampleHeight !== undefined ? { sampleHeight: context.sampleHeight } : {}),
57
+ });
58
+ const poles = placed.map((instance) => ({ id: `${object.id}/pole/${instance.index}`, position: instance.position, yaw: instance.yaw }));
59
+ const cables = [];
60
+ if (wireCount > 0) {
61
+ for (let i = 0; i + 1 < poles.length; i += 1) {
62
+ const a = poles[i];
63
+ const b = poles[i + 1];
64
+ const dx = b.position[0] - a.position[0];
65
+ const dz = b.position[2] - a.position[2];
66
+ const span = Math.hypot(dx, dz) || 1;
67
+ const perpX = -dz / span;
68
+ const perpZ = dx / span;
69
+ const drop = sag + sagPerMeter * span;
70
+ const half = (wireCount - 1) / 2;
71
+ for (let w = 0; w < wireCount; w += 1) {
72
+ const offset = (w - half) * wireSpacing;
73
+ const topA = [a.position[0] + perpX * offset, a.position[1] + poleHeight, a.position[2] + perpZ * offset];
74
+ const topB = [b.position[0] + perpX * offset, b.position[1] + poleHeight, b.position[2] + perpZ * offset];
75
+ cables.push({ id: `${object.id}/cable/${i}/${w}`, points: sagCurve(topA, topB, drop, cableSegments), radius: cableRadius });
76
+ }
77
+ }
78
+ }
79
+ return { poles, cables, poleHeight, poleAsset: params["poleAsset"], wireCount, wireSpacing };
80
+ }
81
+ /** Registers the pole-line scene kind (schema + resolver + inspector note). Called by `registerBuiltinSceneKinds`. @internal */
82
+ export function registerPoleLineKind() {
83
+ registerSceneKind({
84
+ kind: POLE_LINE_KIND,
85
+ target: "path",
86
+ label: "Pole line / cables",
87
+ pathShape: "line",
88
+ addCategory: "Studios",
89
+ accent: "#fbbf24",
90
+ schema: POLE_LINE_SCHEMA,
91
+ resolve: (object, params, context) => resolvePoleLine(object, params, context),
92
+ note: (object, params) => {
93
+ const resolved = resolvePoleLine(object, params);
94
+ return `${resolved.poles.length} poles · ${resolved.cables.length} cables`;
95
+ },
96
+ });
97
+ }
@@ -0,0 +1,34 @@
1
+ import type { Vec2 } from "./geometry.js";
2
+ /** A polyline prepared for repeated distance/fraction sampling, with cumulative arc-length precomputed. */
3
+ export interface Polyline {
4
+ readonly points: readonly Vec2[];
5
+ readonly cumulative: readonly number[];
6
+ readonly length: number;
7
+ }
8
+ /** The closest point on a polyline to a query point, with where it lands along the line. */
9
+ export interface PolylineHit {
10
+ readonly point: Vec2;
11
+ readonly distanceAlong: number;
12
+ readonly segment: number;
13
+ readonly lateral: number;
14
+ }
15
+ /** Prepare a polyline from ordered points, computing cumulative arc-length once for O(log n) sampling.
16
+ * @internal
17
+ */
18
+ export declare function polyline(points: readonly Vec2[]): Polyline;
19
+ /** Point at an absolute arc-length distance along the line, clamped to the endpoints.
20
+ * @internal
21
+ */
22
+ export declare function pointAtDistance(line: Polyline, dist: number): Vec2;
23
+ /** Point at a `[0, 1]` fraction of the line's total length.
24
+ * @internal
25
+ */
26
+ export declare function pointAtFraction(line: Polyline, fraction: number): Vec2;
27
+ /** Unit tangent (direction of travel) at an absolute distance along the line.
28
+ * @internal
29
+ */
30
+ export declare function tangentAtDistance(line: Polyline, dist: number): Vec2;
31
+ /** Closest point on the line to `query`, reporting arc-length position, segment index, and signed lateral offset.
32
+ * @internal
33
+ */
34
+ export declare function closestPoint(line: Polyline, query: Vec2): PolylineHit;
@@ -0,0 +1,88 @@
1
+ import { distance, lerp, normalize, perp, sub } from "./vec2.js";
2
+ /** Prepare a polyline from ordered points, computing cumulative arc-length once for O(log n) sampling.
3
+ * @internal
4
+ */
5
+ export function polyline(points) {
6
+ const cumulative = [0];
7
+ for (let i = 1; i < points.length; i += 1) {
8
+ cumulative.push(cumulative[i - 1] + distance(points[i - 1], points[i]));
9
+ }
10
+ return { points, cumulative, length: cumulative[cumulative.length - 1] ?? 0 };
11
+ }
12
+ function segmentAt(line, dist) {
13
+ const { cumulative } = line;
14
+ const clamped = dist < 0 ? 0 : dist > line.length ? line.length : dist;
15
+ let lo = 1;
16
+ let hi = cumulative.length - 1;
17
+ while (lo < hi) {
18
+ const mid = (lo + hi) >> 1;
19
+ if (cumulative[mid] < clamped)
20
+ lo = mid + 1;
21
+ else
22
+ hi = mid;
23
+ }
24
+ const start = cumulative[lo - 1];
25
+ const span = cumulative[lo] - start;
26
+ return { index: lo, t: span <= 0 ? 0 : (clamped - start) / span };
27
+ }
28
+ /** Point at an absolute arc-length distance along the line, clamped to the endpoints.
29
+ * @internal
30
+ */
31
+ export function pointAtDistance(line, dist) {
32
+ if (line.points.length === 0)
33
+ return [0, 0];
34
+ if (line.points.length === 1)
35
+ return line.points[0];
36
+ const { index, t } = segmentAt(line, dist);
37
+ return lerp(line.points[index - 1], line.points[index], t);
38
+ }
39
+ /** Point at a `[0, 1]` fraction of the line's total length.
40
+ * @internal
41
+ */
42
+ export function pointAtFraction(line, fraction) {
43
+ return pointAtDistance(line, fraction * line.length);
44
+ }
45
+ /** Unit tangent (direction of travel) at an absolute distance along the line.
46
+ * @internal
47
+ */
48
+ export function tangentAtDistance(line, dist) {
49
+ if (line.points.length < 2)
50
+ return [0, 1];
51
+ const { index } = segmentAt(line, dist);
52
+ return normalize(sub(line.points[index], line.points[index - 1]));
53
+ }
54
+ /** Closest point on the line to `query`, reporting arc-length position, segment index, and signed lateral offset.
55
+ * @internal
56
+ */
57
+ export function closestPoint(line, query) {
58
+ const { points, cumulative } = line;
59
+ if (points.length === 0)
60
+ return { point: [0, 0], distanceAlong: 0, segment: 0, lateral: 0 };
61
+ if (points.length === 1) {
62
+ return { point: points[0], distanceAlong: 0, segment: 0, lateral: distance(points[0], query) };
63
+ }
64
+ let best = { point: points[0], distanceAlong: 0, segment: 0, lateral: Infinity };
65
+ // Track the unsigned nearest distance separately: `best.lateral` carries a *signed* offset for
66
+ // the caller, so comparing the next candidate's unsigned distance against it would freeze the
67
+ // search the moment a negative-side segment lands (unsigned >= 0 never beats a stored negative).
68
+ let bestDistance = Infinity;
69
+ for (let i = 1; i < points.length; i += 1) {
70
+ const a = points[i - 1];
71
+ const b = points[i];
72
+ const abx = b[0] - a[0];
73
+ const aby = b[1] - a[1];
74
+ const segLenSq = abx * abx + aby * aby;
75
+ const t = segLenSq <= 0 ? 0 : Math.max(0, Math.min(1, ((query[0] - a[0]) * abx + (query[1] - a[1]) * aby) / segLenSq));
76
+ const point = [a[0] + abx * t, a[1] + aby * t];
77
+ const lateral = distance(point, query);
78
+ if (lateral < bestDistance) {
79
+ bestDistance = lateral;
80
+ const along = cumulative[i - 1] + t * Math.sqrt(segLenSq);
81
+ const unit = normalize([abx, aby]);
82
+ const normal = perp(unit);
83
+ const side = Math.sign(normal[0] * (query[0] - point[0]) + normal[1] * (query[1] - point[1]));
84
+ best = { point, distanceAlong: along, segment: i - 1, lateral: lateral * (side === 0 ? 1 : side) };
85
+ }
86
+ }
87
+ return best;
88
+ }
@@ -0,0 +1,109 @@
1
+ /** A quantity that is either fixed or a uniformly sampled `[min, max]` range resolved by the field rng. */
2
+ export type Quantity = number | readonly [number, number];
3
+ /** One resource kind a node can yield and its base per-harvest amount (before tool bias and harvester multiplier). */
4
+ export interface ResourceYield {
5
+ /** Generic resource kind id — "wood", "ore", "fiber", "hide". The field never interprets it. */
6
+ kind: string;
7
+ /** Base amount granted per harvest hit; a `[min, max]` range samples deterministic variance from the field rng. */
8
+ amount: Quantity;
9
+ }
10
+ /** A harvestable node definition: a finite budget, the resources it yields, and how it respawns. */
11
+ export interface ResourceNodeDef {
12
+ id: string;
13
+ /** Total harvestable budget (hit points / finite quantity). Each harvest consumes the tool's `power`. */
14
+ budget: number;
15
+ /** Resource kinds this node can yield; a tool's bias selects and scales among them. */
16
+ resources: readonly ResourceYield[];
17
+ /** Seconds to refill after depletion. Omit for a node that never respawns (a one-shot deposit). */
18
+ respawn?: number;
19
+ /** Budget restored on respawn; defaults to `budget`. */
20
+ respawnBudget?: number;
21
+ }
22
+ /**
23
+ * How a tool extracts from a node — its per-hit power and per-resource yield bias. Two profiles over the
24
+ * same multi-resource node return different resources and amounts: the generic pick-vs-hatchet mechanic.
25
+ */
26
+ export interface ToolProfile {
27
+ /** Budget consumed per harvest hit; defaults to 1. Clamped to the node's remaining budget. */
28
+ power?: number;
29
+ /** Per-resource-kind yield multiplier. A kind absent here falls back to `defaultBias`. */
30
+ biases?: Readonly<Record<string, number>>;
31
+ /** Multiplier for resource kinds not listed in `biases`; defaults to 1 (set 0 for a tool that only extracts listed kinds). */
32
+ defaultBias?: number;
33
+ }
34
+ /** Options for a single harvest. */
35
+ export interface HarvestOptions {
36
+ /** Scalar applied to every granted amount — a stronger creature/harvester yields more; defaults to 1. */
37
+ multiplier?: number;
38
+ }
39
+ /** One resource kind granted by a harvest and its resolved amount. */
40
+ export interface ResourceGrant {
41
+ kind: string;
42
+ amount: number;
43
+ }
44
+ /** Outcome of one harvest attempt. */
45
+ export interface HarvestResult {
46
+ nodeId: string;
47
+ /** Resources granted this harvest; empty when the node was already depleted or the tool extracted nothing. */
48
+ granted: readonly ResourceGrant[];
49
+ /** Budget actually consumed (0 when the node was already depleted). */
50
+ spent: number;
51
+ /** Whether the node still had budget and produced a harvest. */
52
+ harvested: boolean;
53
+ /** Whether this harvest reduced the node to empty. */
54
+ depleted: boolean;
55
+ }
56
+ /** Serializable per-node runtime state — round-trips through save/load and multiplayer sync. */
57
+ export interface ResourceNodeState {
58
+ id: string;
59
+ /** Remaining budget. */
60
+ budget: number;
61
+ /** Budget the node refills to on respawn — the nominal "full" value for `fraction`. */
62
+ maxBudget: number;
63
+ depleted: boolean;
64
+ /** Seconds remaining until respawn; 0 when full or when the node never respawns. */
65
+ respawnTimer: number;
66
+ /** Explicit respawn-block flag (a structure claimed the spot); OR-ed with the field's suppression predicate. */
67
+ respawnBlocked: boolean;
68
+ /** 0..1 remaining fraction of `maxBudget`. */
69
+ fraction: number;
70
+ }
71
+ /** Construction options for {@link createResourceNodeField}: node definitions and an optional RNG/suppression hook. */
72
+ export interface ResourceNodeFieldConfig {
73
+ nodes: readonly ResourceNodeDef[];
74
+ /** Injected [0,1) generator for deterministic yield variance; defaults to `Math.random`. */
75
+ rng?: () => number;
76
+ /**
77
+ * Freeze respawn for a node while this returns true — a structure within radius, a nearby occupant.
78
+ * Consulted every tick alongside the per-node `respawnBlocked` flag (either one suppresses).
79
+ */
80
+ respawnSuppressed?: (state: ResourceNodeState) => boolean;
81
+ }
82
+ /** A set of harvestable nodes: harvest with tool profiles, tick respawn timers, snapshot/hydrate for save-load. */
83
+ export interface ResourceNodeField {
84
+ /** Apply one harvest hit with `tool`; returns the granted resources and decrements the node's budget. */
85
+ harvest(nodeId: string, tool: ToolProfile, options?: HarvestOptions): HarvestResult;
86
+ /** Count down respawn timers by `dt`; refill any node whose timer elapses and is not suppressed. */
87
+ tick(dt: number): void;
88
+ state(nodeId: string): ResourceNodeState;
89
+ isDepleted(nodeId: string): boolean;
90
+ /** Set the explicit respawn-block flag; persisted in state and honored by `tick`. */
91
+ setRespawnBlocked(nodeId: string, blocked: boolean): void;
92
+ ids(): readonly string[];
93
+ snapshot(): Record<string, ResourceNodeState>;
94
+ /** Restore mutable per-node state (budget, depletion, timers, block flag) from a {@link snapshot}. */
95
+ hydrate(snapshot: Record<string, ResourceNodeState>): void;
96
+ }
97
+ /**
98
+ * A field of depletable, respawning harvest nodes with tool-dependent yields — the generic rock / tree /
99
+ * bush / vein / corpse. Each node holds a finite budget across one or more resource kinds. A harvest applies
100
+ * a {@link ToolProfile} whose per-resource biases decide *which* resources and *how much* the same node
101
+ * returns (pick favors ore, hatchet favors wood), scaled by a creature/harvester multiplier and optional
102
+ * deterministic rng variance; the budget drops by the tool's power. When a node empties it starts a respawn
103
+ * timer that `tick(dt)` counts down and refills — unless respawn is suppressed by the per-node flag or the
104
+ * injected predicate (a structure claimed the spot). All state is plain and serializable for save-load and
105
+ * multiplayer sync via {@link snapshot}/{@link hydrate}.
106
+ *
107
+ * @capability resource-node depletable, respawning harvest nodes with tool-dependent yields
108
+ */
109
+ export declare function createResourceNodeField(config: ResourceNodeFieldConfig): ResourceNodeField;
@@ -0,0 +1,140 @@
1
+ import { clamp } from "../math/scalar.js";
2
+ function resolveQuantity(quantity, rng) {
3
+ if (typeof quantity === "number")
4
+ return quantity;
5
+ const [lo, hi] = quantity;
6
+ return lo + rng() * (hi - lo);
7
+ }
8
+ function toState(node) {
9
+ return {
10
+ id: node.def.id,
11
+ budget: node.budget,
12
+ maxBudget: node.maxBudget,
13
+ depleted: node.depleted,
14
+ respawnTimer: node.respawnTimer,
15
+ respawnBlocked: node.respawnBlocked,
16
+ fraction: node.maxBudget > 0 ? clamp(node.budget / node.maxBudget, 0, 1) : 0,
17
+ };
18
+ }
19
+ /**
20
+ * A field of depletable, respawning harvest nodes with tool-dependent yields — the generic rock / tree /
21
+ * bush / vein / corpse. Each node holds a finite budget across one or more resource kinds. A harvest applies
22
+ * a {@link ToolProfile} whose per-resource biases decide *which* resources and *how much* the same node
23
+ * returns (pick favors ore, hatchet favors wood), scaled by a creature/harvester multiplier and optional
24
+ * deterministic rng variance; the budget drops by the tool's power. When a node empties it starts a respawn
25
+ * timer that `tick(dt)` counts down and refills — unless respawn is suppressed by the per-node flag or the
26
+ * injected predicate (a structure claimed the spot). All state is plain and serializable for save-load and
27
+ * multiplayer sync via {@link snapshot}/{@link hydrate}.
28
+ *
29
+ * @capability resource-node depletable, respawning harvest nodes with tool-dependent yields
30
+ */
31
+ export function createResourceNodeField(config) {
32
+ const rng = config.rng ?? Math.random;
33
+ const nodes = new Map();
34
+ const order = [];
35
+ for (const def of config.nodes) {
36
+ if (nodes.has(def.id))
37
+ throw new Error(`duplicate resource node "${def.id}"`);
38
+ const respawnBudget = def.respawnBudget ?? def.budget;
39
+ nodes.set(def.id, {
40
+ def,
41
+ budget: def.budget,
42
+ maxBudget: def.budget,
43
+ respawnBudget,
44
+ depleted: def.budget <= 0,
45
+ respawnTimer: 0,
46
+ respawnBlocked: false,
47
+ });
48
+ order.push(def.id);
49
+ }
50
+ const getNode = (id) => {
51
+ const node = nodes.get(id);
52
+ if (node === undefined)
53
+ throw new Error(`unknown resource node "${id}"`);
54
+ return node;
55
+ };
56
+ const isSuppressed = (node) => {
57
+ if (node.respawnBlocked)
58
+ return true;
59
+ if (config.respawnSuppressed === undefined)
60
+ return false;
61
+ return config.respawnSuppressed(toState(node));
62
+ };
63
+ return {
64
+ harvest(nodeId, tool, options = {}) {
65
+ const node = getNode(nodeId);
66
+ if (node.depleted || node.budget <= 0) {
67
+ return { nodeId, granted: [], spent: 0, harvested: false, depleted: node.depleted };
68
+ }
69
+ const power = tool.power !== undefined && tool.power > 0 ? tool.power : 1;
70
+ const spent = Math.min(power, node.budget);
71
+ const multiplier = options.multiplier ?? 1;
72
+ const defaultBias = tool.defaultBias ?? 1;
73
+ const granted = [];
74
+ for (const resource of node.def.resources) {
75
+ // Resolve variance for every resource so the rng stream stays independent of tool choice.
76
+ const base = resolveQuantity(resource.amount, rng);
77
+ const bias = tool.biases?.[resource.kind] ?? defaultBias;
78
+ const amount = base * bias * multiplier;
79
+ if (amount > 0)
80
+ granted.push({ kind: resource.kind, amount });
81
+ }
82
+ node.budget -= spent;
83
+ let depleted = false;
84
+ if (node.budget <= 0) {
85
+ node.budget = 0;
86
+ node.depleted = true;
87
+ depleted = true;
88
+ node.respawnTimer = node.def.respawn ?? 0;
89
+ }
90
+ return { nodeId, granted, spent, harvested: true, depleted };
91
+ },
92
+ tick(dt) {
93
+ if (dt <= 0)
94
+ return;
95
+ for (const id of order) {
96
+ const node = nodes.get(id);
97
+ if (!node.depleted || node.def.respawn === undefined)
98
+ continue;
99
+ if (isSuppressed(node))
100
+ continue;
101
+ node.respawnTimer -= dt;
102
+ if (node.respawnTimer <= 0) {
103
+ node.budget = node.respawnBudget;
104
+ node.depleted = false;
105
+ node.respawnTimer = 0;
106
+ }
107
+ }
108
+ },
109
+ state(nodeId) {
110
+ return toState(getNode(nodeId));
111
+ },
112
+ isDepleted(nodeId) {
113
+ return getNode(nodeId).depleted;
114
+ },
115
+ setRespawnBlocked(nodeId, blocked) {
116
+ getNode(nodeId).respawnBlocked = blocked;
117
+ },
118
+ ids() {
119
+ return order;
120
+ },
121
+ snapshot() {
122
+ const out = {};
123
+ for (const id of order)
124
+ out[id] = toState(nodes.get(id));
125
+ return out;
126
+ },
127
+ hydrate(snapshot) {
128
+ for (const id of order) {
129
+ const saved = snapshot[id];
130
+ if (saved === undefined)
131
+ continue;
132
+ const node = nodes.get(id);
133
+ node.budget = saved.budget;
134
+ node.depleted = saved.depleted;
135
+ node.respawnTimer = saved.respawnTimer;
136
+ node.respawnBlocked = saved.respawnBlocked;
137
+ }
138
+ },
139
+ };
140
+ }
@@ -7,6 +7,14 @@ export interface RoadRibbon {
7
7
  /** Triangle indices into `positions`. */
8
8
  indices: Uint32Array;
9
9
  }
10
+ /**
11
+ * Fillets sharp corners of a centerline into short arcs so a ribbon built from it reads as a smooth
12
+ * road instead of overlapping/notching rectangles at each bend. Each interior vertex is replaced by a
13
+ * quadratic-bezier arc of `radius` (clamped to half the shorter adjacent segment) sampled at
14
+ * `cornerSegments` steps; endpoints and near-straight vertices pass through unchanged.
15
+ * @internal — the corner-smoothing behind `<AuthoredPaths>`; games get it for free through the render.
16
+ */
17
+ export declare function roundPathCorners(points: readonly RoadPoint[], radius: number, cornerSegments?: number): RoadPoint[];
10
18
  /** Options for {@link buildRoadRibbon}. */
11
19
  export interface RoadRibbonOptions {
12
20
  /** Lift above the sampled ground so the ribbon never z-fights the terrain. Default 0.08. */
@@ -1,3 +1,41 @@
1
+ /**
2
+ * Fillets sharp corners of a centerline into short arcs so a ribbon built from it reads as a smooth
3
+ * road instead of overlapping/notching rectangles at each bend. Each interior vertex is replaced by a
4
+ * quadratic-bezier arc of `radius` (clamped to half the shorter adjacent segment) sampled at
5
+ * `cornerSegments` steps; endpoints and near-straight vertices pass through unchanged.
6
+ * @internal — the corner-smoothing behind `<AuthoredPaths>`; games get it for free through the render.
7
+ */
8
+ export function roundPathCorners(points, radius, cornerSegments = 5) {
9
+ if (points.length < 3 || radius <= 0)
10
+ return points.map((point) => [point[0], point[1]]);
11
+ const out = [[points[0][0], points[0][1]]];
12
+ for (let i = 1; i < points.length - 1; i += 1) {
13
+ const a = points[i - 1];
14
+ const v = points[i];
15
+ const b = points[i + 1];
16
+ const ax = a[0] - v[0];
17
+ const az = a[1] - v[1];
18
+ const bx = b[0] - v[0];
19
+ const bz = b[1] - v[1];
20
+ const la = Math.hypot(ax, az) || 1;
21
+ const lb = Math.hypot(bx, bz) || 1;
22
+ const r = Math.min(radius, la / 2, lb / 2);
23
+ const p0 = [v[0] + (ax / la) * r, v[1] + (az / la) * r];
24
+ const p1 = [v[0] + (bx / lb) * r, v[1] + (bz / lb) * r];
25
+ out.push(p0);
26
+ for (let s = 1; s < cornerSegments; s += 1) {
27
+ const t = s / cornerSegments;
28
+ const u = 1 - t;
29
+ out.push([
30
+ u * u * p0[0] + 2 * u * t * v[0] + t * t * p1[0],
31
+ u * u * p0[1] + 2 * u * t * v[1] + t * t * p1[1],
32
+ ]);
33
+ }
34
+ out.push(p1);
35
+ }
36
+ out.push([points[points.length - 1][0], points[points.length - 1][1]]);
37
+ return out;
38
+ }
1
39
  function subdividePath(path, maxLength) {
2
40
  const out = [];
3
41
  for (let i = 0; i < path.length - 1; i += 1) {
@@ -1,4 +1,5 @@
1
1
  import { expandAabb, pointInAabb } from "./geometry.js";
2
+ import { seededRng } from "../random/rng.js";
2
3
  function isAabb(area) {
3
4
  return (typeof area.minX === "number" &&
4
5
  typeof area.minZ === "number" &&
@@ -15,25 +16,6 @@ export function scatterAabb(area) {
15
16
  const halfD = area.d / 2;
16
17
  return { minX: cx - halfW, minZ: cz - halfD, maxX: cx + halfW, maxZ: cz + halfD };
17
18
  }
18
- function hashSeed(seed) {
19
- const text = typeof seed === "number" ? seed.toString() : seed;
20
- let h = 2166136261 >>> 0;
21
- for (let i = 0; i < text.length; i++) {
22
- h ^= text.charCodeAt(i);
23
- h = Math.imul(h, 16777619);
24
- }
25
- return h >>> 0;
26
- }
27
- function mulberry32(state) {
28
- let a = state >>> 0;
29
- return () => {
30
- a = (a + 0x6d2b79f5) >>> 0;
31
- let t = a;
32
- t = Math.imul(t ^ (t >>> 15), t | 1);
33
- t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
34
- return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
35
- };
36
- }
37
19
  export function scatter(config) {
38
20
  const aabb = scatterAabb(config.area);
39
21
  const width = aabb.maxX - aabb.minX;
@@ -47,7 +29,7 @@ export function scatter(config) {
47
29
  const jitter = config.jitter ?? 1;
48
30
  const maxAttempts = config.maxAttempts ?? target * 30;
49
31
  const avoid = (config.avoid ?? []).map((a) => (avoidMargin !== 0 ? expandAabb(a, avoidMargin) : a));
50
- const rng = mulberry32(hashSeed(config.seed ?? "scatter"));
32
+ const rng = seededRng(config.seed ?? "scatter");
51
33
  const useDistance = minDistance > 0;
52
34
  const buckets = new Map();
53
35
  const bucketKey = (x, z) => `${Math.floor(x / minDistance)}:${Math.floor(z / minDistance)}`;