@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
@@ -1,4 +1,9 @@
1
1
  import type { BuildingPaletteOverrides, BuildingStyle } from "./buildings.js";
2
+ import type { AvoidZone } from "./geometry.js";
3
+ import type { TerrainPathProfile } from "./pathTerrain.js";
4
+ import type { PlaceWorldFeature } from "./place.js";
5
+ import type { TerraformSnapshot } from "./terraform.js";
6
+ import type { VolumetricCloudsConfig } from "./volumetricClouds.js";
2
7
  export interface WorldBounds {
3
8
  w: number;
4
9
  d: number;
@@ -42,6 +47,35 @@ export interface TerrainDetailConfig {
42
47
  roughness?: number;
43
48
  /** Overall detail intensity 0..1. Default 1. */
44
49
  strength?: number;
50
+ /** Real PBR texture maps blended over the procedural detail — the seam for `@jgengine/assets` `buildMaterialCatalog` output. Omit to keep the procedural-only look. */
51
+ material?: TerrainDetailMaterialConfig;
52
+ }
53
+ /**
54
+ * PBR map URLs for a real ground texture — the same shape
55
+ * `buildMaterialCatalog({ basePath }).resolve(id)!.maps` from `@jgengine/assets` returns. Kept
56
+ * dependency-free here so `core` never imports the assets package; any URLs (pulled maps, a CDN, a
57
+ * data URI) satisfy it.
58
+ */
59
+ export interface TerrainMaterialMaps {
60
+ color: string;
61
+ normal: string;
62
+ roughness: string;
63
+ ao: string;
64
+ displacement: string;
65
+ }
66
+ /**
67
+ * Real PBR texture applied over the ground surface — the seam that lets a game put a
68
+ * `buildMaterialCatalog` material on terrain. Blends with, never replaces, the procedural detail
69
+ * shader: color/roughness/ao tile the maps by world position, `strength` fades them over the
70
+ * existing vertex-colour + noise look.
71
+ */
72
+ export interface TerrainDetailMaterialConfig {
73
+ /** e.g. `buildMaterialCatalog({ basePath: "/materials" }).resolve("material/grass")!.maps`. */
74
+ maps: TerrainMaterialMaps;
75
+ /** World units per texture tile; smaller tiles the texture more densely. Default 4. */
76
+ repeat?: number;
77
+ /** Blend strength of the texture over the procedural/vertex-colour base, 0..1. Default 1. */
78
+ strength?: number;
45
79
  }
46
80
  export interface TerrainFlattenMask {
47
81
  center: EnvironmentVec2;
@@ -88,11 +122,26 @@ export interface TerrainRectRegion extends TerrainRegionStyle {
88
122
  * and blend back across `falloff`; later regions in the list win overlaps.
89
123
  */
90
124
  export type TerrainMaterialRegion = TerrainCircleRegion | TerrainPolylineRegion | TerrainRectRegion;
125
+ /** Per-band fog override cross-faded along z by `createBiomeFogSampler`; unset fields fall through to the base sky fog. */
126
+ export interface BiomeFog {
127
+ color?: string;
128
+ near?: number;
129
+ far?: number;
130
+ density?: number;
131
+ }
132
+ /** Per-band sky/light override cross-faded along z by `createBiomeSkySampler`; unset fields fall through to the base sky. */
133
+ export interface BiomeSky {
134
+ horizonColor?: string;
135
+ zenithColor?: string;
136
+ sunIntensity?: number;
137
+ ambientIntensity?: number;
138
+ }
91
139
  /**
92
140
  * A z-ordered ground palette zone — the linear-boundary counterpart to the radial `materialRegions`.
93
141
  * Adjacent bands cross-fade into each other across a `fade`-wide window centered on the midpoint z
94
142
  * between their centers, so a multi-biome world (vale → marsh → peaks along z) blends its ground
95
- * color instead of hard-switching. Order the list by ascending `z`.
143
+ * color instead of hard-switching. Bands may also carry per-zone `fog`, `sky`, and `weather`. Order
144
+ * the list by ascending `z`.
96
145
  */
97
146
  export interface BiomeBand {
98
147
  /** World-space center z of the zone. */
@@ -103,6 +152,12 @@ export interface BiomeBand {
103
152
  material?: TerrainMaterial;
104
153
  /** Explicit low/high/waterline hex colors for the zone. */
105
154
  colors?: TerrainColors;
155
+ /** Fog color/near/far/density for the zone, cross-faded per camera z; unset fields keep the base sky fog. */
156
+ fog?: BiomeFog;
157
+ /** Sky horizon/zenith colors and sun/ambient intensity for the zone, cross-faded per camera z; unset fields keep the base sky. */
158
+ sky?: BiomeSky;
159
+ /** Precipitation covering the zone — expands into a full-width weather strip centered at `[0, z]`, `fade`-deep. */
160
+ weather?: "rain" | "snow";
106
161
  }
107
162
  export interface TerrainEnvironmentConfig {
108
163
  bounds?: WorldBounds;
@@ -131,22 +186,50 @@ export interface TerrainEnvironmentConfig {
131
186
  waterLevel?: number;
132
187
  /** Flat pads carved into the noise field, e.g. for building pads or spawn circles. */
133
188
  flatten?: readonly TerrainFlattenMask[];
189
+ /** Authored path profiles that flatten/grade/carve the heightfield along a centerline (roads, rivers, ramps) with optional retaining walls. Applied after `flatten`. */
190
+ pathProfiles?: readonly TerrainPathProfile[];
134
191
  /** Procedural detail surface (noise-driven rock/sand/snow over the biome base). Omit for the flat vertex-colour ground. */
135
192
  detail?: TerrainDetailConfig;
136
193
  }
137
194
  export interface RainEnvironmentConfig {
195
+ /**
196
+ * `w`/`d`/`h` size a wrap-volume of raindrops **anchored to and re-centered on the camera every
197
+ * frame** — not a world-space region. `area.position` (and the `position` sugar below) has **no
198
+ * visual effect** on rain/snow: the shell's `RainField`/`SnowField` always run `followCamera` and
199
+ * never apply the mesh's transform, only `camera.position`. Keep `w`/`d`/`h` near camera scale
200
+ * (roughly 50-120 per axis) so drops stay a visible size at normal view distance — sizing the
201
+ * volume to a world region (e.g. matching a district's footprint) spreads the same drop count
202
+ * across that much more space until they're sub-pixel and the storm reads as empty sky, even
203
+ * though `summarizeEnvironment` shows the layer exists. Reach for `density`, `width`, and `opacity`
204
+ * to make a storm read heavier/taller instead of enlarging `area`.
205
+ */
138
206
  area?: EnvironmentArea;
139
- /** World-space center `[x, z]` of the band, matching `building()`/`ocean()` — sugar for `area.position`, letting a biome zone site its own weather away from the origin. */
207
+ /** World-space center `[x, z]` of the band, matching `building()`/`ocean()` — sugar for `area.position`. No visual effect on rain/snow (see `area`); kept for API symmetry with other weather-adjacent features. */
140
208
  position?: EnvironmentVec2;
141
209
  density?: number;
142
210
  speed?: number;
143
211
  dropLength?: number;
144
212
  wind?: EnvironmentVec2;
145
213
  color?: string;
214
+ /** Streak width of each raindrop quad, in world units. Default 0.018 — raise for a heavier-reading storm without enlarging `area`. */
215
+ width?: number;
216
+ /** Drop opacity, 0-1. Default 0.48 — raise for a denser-reading storm without enlarging `area`. */
217
+ opacity?: number;
146
218
  }
147
219
  export interface SnowEnvironmentConfig {
220
+ /**
221
+ * `w`/`d`/`h` size a wrap-volume of snowflakes **anchored to and re-centered on the camera every
222
+ * frame** — not a world-space region. `area.position` (and the `position` sugar below) has **no
223
+ * visual effect** on rain/snow: the shell's `RainField`/`SnowField` always run `followCamera` and
224
+ * never apply the mesh's transform, only `camera.position`. Keep `w`/`d`/`h` near camera scale
225
+ * (roughly 50-120 per axis) so flakes stay a visible size at normal view distance — sizing the
226
+ * volume to a world region (e.g. matching a district's footprint) spreads the same flake count
227
+ * across that much more space until they're sub-pixel and the storm reads as empty sky, even
228
+ * though `summarizeEnvironment` shows the layer exists. Reach for `density`, `flakeSize`, and
229
+ * `opacity` to make a storm read heavier instead of enlarging `area`.
230
+ */
148
231
  area?: EnvironmentArea;
149
- /** World-space center `[x, z]` of the band, matching `building()`/`ocean()` — sugar for `area.position`, letting a biome zone site its own weather away from the origin. */
232
+ /** World-space center `[x, z]` of the band, matching `building()`/`ocean()` — sugar for `area.position`. No visual effect on rain/snow (see `area`); kept for API symmetry with other weather-adjacent features. */
150
233
  position?: EnvironmentVec2;
151
234
  density?: number;
152
235
  speed?: number;
@@ -154,6 +237,8 @@ export interface SnowEnvironmentConfig {
154
237
  drift?: number;
155
238
  wind?: EnvironmentVec2;
156
239
  color?: string;
240
+ /** Flake opacity, 0-1. Default 0.86 — raise for a denser-reading storm without enlarging `area`. */
241
+ opacity?: number;
157
242
  }
158
243
  export interface GrassEnvironmentConfig {
159
244
  area?: EnvironmentArea;
@@ -192,11 +277,19 @@ export interface SkyEnvironmentConfig {
192
277
  zenithColor?: string;
193
278
  sunIntensity?: number;
194
279
  ambientIntensity?: number;
280
+ /** Sky-dome sphere radius in world units. Enlarge for a playfield sited far from the origin so the viewer never exits the dome. Default 260. */
281
+ radius?: number;
282
+ /** Horizon haze-band strength: 0 removes the dusty band, ~1 makes it heavy. Default 0.5. */
283
+ hazeStrength?: number;
284
+ /** Sun-glow brightness multiplier around the sun disc. Default 1. */
285
+ sunGlowStrength?: number;
195
286
  fog?: {
196
287
  color?: string;
197
288
  near?: number;
198
289
  far?: number;
199
290
  };
291
+ /** Raymarched volumetric cloud layer over the sky dome. Off by default — omit for no clouds. */
292
+ volumetricClouds?: VolumetricCloudsConfig;
200
293
  }
201
294
  export interface BuildingEnvironmentConfig {
202
295
  count?: number;
@@ -239,10 +332,10 @@ export type TerrainIslandDescriptor = Omit<TerrainEnvironmentDescriptor, "kind">
239
332
  };
240
333
  export type RainEnvironmentDescriptor = {
241
334
  kind: "rain";
242
- } & Required<Pick<RainEnvironmentConfig, "area" | "density" | "speed" | "dropLength" | "wind" | "color">>;
335
+ } & Required<Pick<RainEnvironmentConfig, "area" | "density" | "speed" | "dropLength" | "wind" | "color" | "width" | "opacity">>;
243
336
  export type SnowEnvironmentDescriptor = {
244
337
  kind: "snow";
245
- } & Required<Pick<SnowEnvironmentConfig, "area" | "density" | "speed" | "flakeSize" | "drift" | "wind" | "color">>;
338
+ } & Required<Pick<SnowEnvironmentConfig, "area" | "density" | "speed" | "flakeSize" | "drift" | "wind" | "color" | "opacity">>;
246
339
  export type GrassEnvironmentDescriptor = {
247
340
  kind: "grass";
248
341
  } & Required<Pick<GrassEnvironmentConfig, "area" | "density" | "bladeHeight" | "bladeWidth" | "windStrength" | "colors">> & Pick<GrassEnvironmentConfig, "seed">;
@@ -306,6 +399,18 @@ export interface EnvironmentWorldConfig {
306
399
  roads?: EnvironmentDescriptorList<RoadEnvironmentDescriptor>;
307
400
  /** Ground pads, e.g. platforms or paved patches; each implicitly flattens the terrain beneath it. */
308
401
  pads?: readonly PadEnvironmentDescriptor[];
402
+ /**
403
+ * An authored editor {@link TerraformSnapshot} whose offsets layer over the base terrain — the
404
+ * editor-to-runtime ground seam. The same snapshot in a game's `editorLayers.terrain` renders and
405
+ * collides identically at runtime.
406
+ */
407
+ sculpt?: TerraformSnapshot;
408
+ /**
409
+ * Clearance discs flattened into the ground (spawns, plots, paths) — the terrain half of a
410
+ * clearance zone whose foliage half is scatter's `avoid`. Derive them from a document with
411
+ * `clearanceZonesFrom`.
412
+ */
413
+ clearings?: readonly AvoidZone[];
309
414
  }
310
415
  export interface EnvironmentWorldFeature {
311
416
  kind: "environment";
@@ -318,6 +423,10 @@ export interface EnvironmentWorldFeature {
318
423
  structures?: readonly StructureEnvironmentDescriptor[];
319
424
  roads?: readonly RoadEnvironmentDescriptor[];
320
425
  pads?: readonly PadEnvironmentDescriptor[];
426
+ /** Authored sculpt snapshot layered over the base terrain — see {@link EnvironmentWorldConfig.sculpt}. */
427
+ sculpt?: TerraformSnapshot;
428
+ /** Clearance discs flattened into the ground — see {@link EnvironmentWorldConfig.clearings}. */
429
+ clearings?: readonly AvoidZone[];
321
430
  }
322
431
  export interface WorldGridCell {
323
432
  x: number;
@@ -356,8 +465,13 @@ export interface PlotsWorldConfig extends WorldGridConfig {
356
465
  export interface TilemapWorldConfig extends WorldGridConfig {
357
466
  map: string;
358
467
  }
359
- /** A declared world shape — biomes, voxel grid, plots, tilemap, environment, or flat — passed to `defineGame`. */
360
- export type WorldFeature = ({
468
+ /**
469
+ * A declared world shape passed to `defineGame`. The preferred model is the place feature from
470
+ * `world()` (`@jgengine/core/world/place`): substrate + laws, with all dressing authored in the
471
+ * editor. The remaining members — biomes, voxel grid, plots, tilemap, environment, flat — are the
472
+ * legacy code-declared shapes kept for existing games.
473
+ */
474
+ export type WorldFeature = PlaceWorldFeature | ({
361
475
  kind: "biomes";
362
476
  } & BiomesWorldConfig) | ({
363
477
  kind: "voxel";
@@ -370,14 +484,23 @@ export type WorldFeature = ({
370
484
  };
371
485
  /** Derives implicit `TerrainFlattenMask`s carving each pad's footprint into the terrain beneath it. Elevated pads (absolute `elevation`) float free and carve nothing. */
372
486
  export declare function padFlattenMasks(pads: readonly PadEnvironmentDescriptor[]): readonly TerrainFlattenMask[];
373
- /** Composes an `environment()` world feature from terrain, sky, weather, vegetation, water, structures, roads, and pads. */
487
+ /** Composes an `environment()` feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
488
+ *
489
+ * Legacy dressing-in-code path — not how a world is defined. A world is the place you play in
490
+ * (`world()` from `world/place`: ground + laws); sky look, foliage scatter, props, and sculpt are
491
+ * scene content authored in the editor. Reach for `environment()` only when consuming
492
+ * editor/preset-written scene data (`environmentContentFromDocument`) or maintaining an existing
493
+ * game; never scaffold new worlds from it.
494
+ *
495
+ * @capability world-environment compose editor/preset-derived outdoor dressing — terrain, weather, water, structures — into a legacy environment feature
496
+ */
374
497
  export declare function environment(config?: EnvironmentWorldConfig): EnvironmentWorldFeature;
375
498
  /** Declares a heightfield terrain patch for `environment()` — bounds, noise, materials, and flatten masks. */
376
499
  export declare function terrain(config?: TerrainEnvironmentConfig): TerrainEnvironmentDescriptor;
377
500
  export declare function sky(config?: SkyEnvironmentConfig): SkyEnvironmentDescriptor;
378
- /** Declares a rainfall weather effect for `environment()` — area, density, speed, and wind. */
501
+ /** Declares a rainfall weather effect for `environment()` — area, density, speed, wind, and drop width/opacity. */
379
502
  export declare function rain(config?: RainEnvironmentConfig): RainEnvironmentDescriptor;
380
- /** Declares a snowfall weather effect for `environment()` — area, density, drift, and wind. */
503
+ /** Declares a snowfall weather effect for `environment()` — area, density, drift, wind, and flake opacity. */
381
504
  export declare function snow(config?: SnowEnvironmentConfig): SnowEnvironmentDescriptor;
382
505
  /** Declares a grass vegetation patch for `environment()` — area, blade sizing, density, and colors. */
383
506
  export declare function grass(config?: GrassEnvironmentConfig): GrassEnvironmentDescriptor;
@@ -27,9 +27,37 @@ function withPadFlatten(terrainDescriptor, pads) {
27
27
  flatten: [...(terrainDescriptor.flatten ?? []), ...padFlattenMasks(pads)],
28
28
  };
29
29
  }
30
- /** Composes an `environment()` world feature from terrain, sky, weather, vegetation, water, structures, roads, and pads. */
30
+ /** Expands each `biomeBand.weather` into a full-width precipitation strip centered on the band's z, `fade`-deep. */
31
+ function bandWeatherDescriptors(terrainDescriptor) {
32
+ const bands = terrainDescriptor?.biomeBands;
33
+ if (bands === undefined || bands.length === 0)
34
+ return [];
35
+ const width = terrainDescriptor.bounds.w;
36
+ const out = [];
37
+ for (const band of bands) {
38
+ if (band.weather === undefined)
39
+ continue;
40
+ const area = { w: width, d: band.fade ?? 64, h: 80 };
41
+ const position = [0, band.z];
42
+ out.push(band.weather === "rain" ? rain({ area, position }) : snow({ area, position }));
43
+ }
44
+ return out;
45
+ }
46
+ /** Composes an `environment()` feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
47
+ *
48
+ * Legacy dressing-in-code path — not how a world is defined. A world is the place you play in
49
+ * (`world()` from `world/place`: ground + laws); sky look, foliage scatter, props, and sculpt are
50
+ * scene content authored in the editor. Reach for `environment()` only when consuming
51
+ * editor/preset-written scene data (`environmentContentFromDocument`) or maintaining an existing
52
+ * game; never scaffold new worlds from it.
53
+ *
54
+ * @capability world-environment compose editor/preset-derived outdoor dressing — terrain, weather, water, structures — into a legacy environment feature
55
+ */
31
56
  export function environment(config = {}) {
32
- const weather = list(config.weather);
57
+ const explicitWeather = list(config.weather);
58
+ const bandWeather = bandWeatherDescriptors(config.terrain);
59
+ const weatherAll = [...(explicitWeather ?? []), ...bandWeather];
60
+ const weather = weatherAll.length === 0 ? undefined : weatherAll;
33
61
  const vegetation = list(config.vegetation);
34
62
  const water = list(config.water);
35
63
  const structures = list(config.structures);
@@ -46,6 +74,8 @@ export function environment(config = {}) {
46
74
  ...(structures === undefined ? {} : { structures }),
47
75
  ...(roads === undefined ? {} : { roads }),
48
76
  ...(config.pads === undefined ? {} : { pads: config.pads }),
77
+ ...(config.sculpt === undefined ? {} : { sculpt: config.sculpt }),
78
+ ...(config.clearings === undefined || config.clearings.length === 0 ? {} : { clearings: config.clearings }),
49
79
  };
50
80
  }
51
81
  /** Declares a heightfield terrain patch for `environment()` — bounds, noise, materials, and flatten masks. */
@@ -75,6 +105,7 @@ export function terrain(config = {}) {
75
105
  ...(config.baseHeight === undefined ? {} : { baseHeight: config.baseHeight }),
76
106
  ...(config.waterLevel === undefined ? {} : { waterLevel: config.waterLevel }),
77
107
  ...(config.flatten === undefined ? {} : { flatten: config.flatten }),
108
+ ...(config.pathProfiles === undefined ? {} : { pathProfiles: config.pathProfiles }),
78
109
  ...(config.detail === undefined ? {} : { detail: config.detail }),
79
110
  });
80
111
  }
@@ -88,35 +119,64 @@ export function sky(config = {}) {
88
119
  ...(config.zenithColor === undefined ? {} : { zenithColor: config.zenithColor }),
89
120
  ...(config.sunIntensity === undefined ? {} : { sunIntensity: config.sunIntensity }),
90
121
  ...(config.ambientIntensity === undefined ? {} : { ambientIntensity: config.ambientIntensity }),
122
+ ...(config.radius === undefined ? {} : { radius: config.radius }),
123
+ ...(config.hazeStrength === undefined ? {} : { hazeStrength: config.hazeStrength }),
124
+ ...(config.sunGlowStrength === undefined ? {} : { sunGlowStrength: config.sunGlowStrength }),
91
125
  ...(config.fog === undefined ? {} : { fog: config.fog }),
126
+ ...(config.volumetricClouds === undefined ? {} : { volumetricClouds: config.volumetricClouds }),
92
127
  });
93
128
  }
94
129
  function withAreaPosition(area, position) {
95
130
  return position !== undefined && area.position === undefined ? { ...area, position } : area;
96
131
  }
97
- /** Declares a rainfall weather effect for `environment()` — area, density, speed, and wind. */
132
+ /**
133
+ * Practical ceiling (world units per axis) past which an author-specified rain/snow `area` is almost
134
+ * certainly a world-region size mistakenly handed to the camera-anchored wrap-volume — see the
135
+ * `area` doc on `RainEnvironmentConfig`/`SnowEnvironmentConfig`.
136
+ */
137
+ const WEATHER_AREA_CAMERA_SCALE_HINT = 120;
138
+ function warnIfOversizedWeatherArea(kind, area) {
139
+ if (typeof console === "undefined")
140
+ return;
141
+ if (area.w <= WEATHER_AREA_CAMERA_SCALE_HINT &&
142
+ area.d <= WEATHER_AREA_CAMERA_SCALE_HINT &&
143
+ (area.h ?? 0) <= WEATHER_AREA_CAMERA_SCALE_HINT) {
144
+ return;
145
+ }
146
+ console.warn(`[jgengine:${kind}] area ${area.w}x${area.d}x${area.h ?? "default"} is far larger than the camera-anchored wrap-volume ${kind}() actually renders — area.position is ignored, and an oversized area.w/d/h just spreads drops/flakes thinner until they're sub-pixel at normal view distance, not wider visible coverage. Keep area near camera scale (~50-120 per axis); use density/width/opacity (or flakeSize for snow) to make a storm read heavier instead.`);
147
+ }
148
+ /** Declares a rainfall weather effect for `environment()` — area, density, speed, wind, and drop width/opacity. */
98
149
  export function rain(config = {}) {
150
+ const area = withAreaPosition(config.area ?? { w: 256, d: 256, h: 80 }, config.position);
151
+ if (config.area !== undefined)
152
+ warnIfOversizedWeatherArea("rain", area);
99
153
  return {
100
154
  kind: "rain",
101
- area: withAreaPosition(config.area ?? { w: 256, d: 256, h: 80 }, config.position),
155
+ area,
102
156
  density: config.density ?? 0.65,
103
157
  speed: config.speed ?? 18,
104
158
  dropLength: config.dropLength ?? 0.8,
105
159
  wind: config.wind ?? [0, 0],
106
160
  color: config.color ?? "#9ec8ff",
161
+ width: config.width ?? 0.018,
162
+ opacity: config.opacity ?? 0.48,
107
163
  };
108
164
  }
109
- /** Declares a snowfall weather effect for `environment()` — area, density, drift, and wind. */
165
+ /** Declares a snowfall weather effect for `environment()` — area, density, drift, wind, and flake opacity. */
110
166
  export function snow(config = {}) {
167
+ const area = withAreaPosition(config.area ?? { w: 256, d: 256, h: 80 }, config.position);
168
+ if (config.area !== undefined)
169
+ warnIfOversizedWeatherArea("snow", area);
111
170
  return {
112
171
  kind: "snow",
113
- area: withAreaPosition(config.area ?? { w: 256, d: 256, h: 80 }, config.position),
172
+ area,
114
173
  density: config.density ?? 0.35,
115
174
  speed: config.speed ?? 2.4,
116
175
  flakeSize: config.flakeSize ?? 0.08,
117
176
  drift: config.drift ?? 0.4,
118
177
  wind: config.wind ?? [0, 0],
119
178
  color: config.color ?? "#ffffff",
179
+ opacity: config.opacity ?? 0.86,
120
180
  };
121
181
  }
122
182
  /** Declares a grass vegetation patch for `environment()` — area, blade sizing, density, and colors. */
@@ -0,0 +1,59 @@
1
+ import type { Footprint, Vec2 } from "./geometry.js";
2
+ import type { PlacementObstacle } from "./placement.js";
3
+ /** One integer cell address on a {@link FootprintGrid}. */
4
+ export interface GridCell {
5
+ col: number;
6
+ row: number;
7
+ }
8
+ /** Config for {@link createFootprintGrid}. */
9
+ export interface FootprintGridOptions {
10
+ /** World units per cell. Default 1. */
11
+ cellSize?: number;
12
+ }
13
+ /** A live claim on a {@link FootprintGrid}: which cells `id` (a `kind` tag for adjacency checks) holds. */
14
+ export interface FootprintReservation {
15
+ id: string;
16
+ kind: string;
17
+ cells: readonly GridCell[];
18
+ }
19
+ /** Handle returned by {@link createFootprintGrid}. */
20
+ export interface FootprintGrid {
21
+ readonly cellSize: number;
22
+ /** The cells a `footprint` centered on `origin` (world units) covers, honoring `quarterTurns` — feed straight into `reserve`/`isFree`. */
23
+ cellsFor(origin: Vec2, footprint: Footprint, quarterTurns?: number): GridCell[];
24
+ isFree(cells: readonly GridCell[]): boolean;
25
+ /** Claims every cell for `id`/`kind`; fails (no partial reservation) if `id` already holds a reservation or any cell is occupied. */
26
+ reserve(id: string, kind: string, cells: readonly GridCell[]): boolean;
27
+ release(id: string): boolean;
28
+ occupantAt(cell: GridCell): string | null;
29
+ kindAt(cell: GridCell): string | null;
30
+ reservationOf(id: string): FootprintReservation | null;
31
+ list(): readonly FootprintReservation[];
32
+ clear(): void;
33
+ }
34
+ /**
35
+ * Multi-cell footprint occupancy/reservation on a shared build grid — `world/placementController`
36
+ * only owns the ghost preview; this is the persistent claim a committed placement holds so the next
37
+ * hover's `isFree` check (or another player's, in a shared world) sees it. Bridge into
38
+ * `world/placement`'s `PlacementRules.obstacles` with {@link footprintObstacles} instead of
39
+ * hand-rolling an occupancy map per game.
40
+ *
41
+ * @capability footprint-grid multi-cell footprint occupancy/reservation on a shared build grid
42
+ */
43
+ export declare function createFootprintGrid(options?: FootprintGridOptions): FootprintGrid;
44
+ /** One occupied neighbor cell reported by {@link boundaryNeighbors}. */
45
+ export interface AdjacentCell {
46
+ cell: GridCell;
47
+ kind: string;
48
+ }
49
+ /** Every occupied cell orthogonally touching `cells` but outside them — the connective-piece neighbor set. */
50
+ export declare function boundaryNeighbors(grid: FootprintGrid, cells: readonly GridCell[]): AdjacentCell[];
51
+ /**
52
+ * Connective-piece adjacency validity: every occupied neighbor of `cells` must satisfy `accepts`
53
+ * (no incompatible piece touching), and when `requireConnection` is true at least one neighbor must
54
+ * (a road/pipe/belt segment placed with nothing to connect to is invalid). An empty-bordered footprint
55
+ * (no occupied neighbors at all) passes unless `requireConnection` demands one.
56
+ */
57
+ export declare function hasValidAdjacency(grid: FootprintGrid, cells: readonly GridCell[], accepts: (neighborKind: string) => boolean, requireConnection?: boolean): boolean;
58
+ /** Bridges live reservations into `world/placement`'s `PlacementRules.obstacles` so `validatePlacement`/`createPlacementController` see the grid's committed footprints unchanged. */
59
+ export declare function footprintObstacles(grid: FootprintGrid): PlacementObstacle[];
@@ -0,0 +1,141 @@
1
+ function cellKey(cell) {
2
+ return `${cell.col}:${cell.row}`;
3
+ }
4
+ /**
5
+ * Multi-cell footprint occupancy/reservation on a shared build grid — `world/placementController`
6
+ * only owns the ghost preview; this is the persistent claim a committed placement holds so the next
7
+ * hover's `isFree` check (or another player's, in a shared world) sees it. Bridge into
8
+ * `world/placement`'s `PlacementRules.obstacles` with {@link footprintObstacles} instead of
9
+ * hand-rolling an occupancy map per game.
10
+ *
11
+ * @capability footprint-grid multi-cell footprint occupancy/reservation on a shared build grid
12
+ */
13
+ export function createFootprintGrid(options = {}) {
14
+ const cellSize = options.cellSize ?? 1;
15
+ const occupied = new Map();
16
+ const reservations = new Map();
17
+ return {
18
+ cellSize,
19
+ cellsFor(origin, footprint, quarterTurns = 0) {
20
+ const turned = ((quarterTurns % 2) + 2) % 2 === 1;
21
+ const cols = Math.max(1, Math.round((turned ? footprint.d : footprint.w) / cellSize));
22
+ const rows = Math.max(1, Math.round((turned ? footprint.w : footprint.d) / cellSize));
23
+ const originCol = Math.round(origin[0] / cellSize - cols / 2);
24
+ const originRow = Math.round(origin[1] / cellSize - rows / 2);
25
+ const cells = [];
26
+ for (let row = 0; row < rows; row += 1) {
27
+ for (let col = 0; col < cols; col += 1)
28
+ cells.push({ col: originCol + col, row: originRow + row });
29
+ }
30
+ return cells;
31
+ },
32
+ isFree(cells) {
33
+ return cells.every((cell) => !occupied.has(cellKey(cell)));
34
+ },
35
+ reserve(id, kind, cells) {
36
+ if (reservations.has(id))
37
+ return false;
38
+ if (!cells.every((cell) => !occupied.has(cellKey(cell))))
39
+ return false;
40
+ for (const cell of cells)
41
+ occupied.set(cellKey(cell), id);
42
+ reservations.set(id, { id, kind, cells: cells.slice() });
43
+ return true;
44
+ },
45
+ release(id) {
46
+ const reservation = reservations.get(id);
47
+ if (reservation === undefined)
48
+ return false;
49
+ for (const cell of reservation.cells)
50
+ occupied.delete(cellKey(cell));
51
+ reservations.delete(id);
52
+ return true;
53
+ },
54
+ occupantAt(cell) {
55
+ return occupied.get(cellKey(cell)) ?? null;
56
+ },
57
+ kindAt(cell) {
58
+ const id = occupied.get(cellKey(cell));
59
+ if (id === undefined)
60
+ return null;
61
+ return reservations.get(id)?.kind ?? null;
62
+ },
63
+ reservationOf(id) {
64
+ return reservations.get(id) ?? null;
65
+ },
66
+ list() {
67
+ return Array.from(reservations.values());
68
+ },
69
+ clear() {
70
+ occupied.clear();
71
+ reservations.clear();
72
+ },
73
+ };
74
+ }
75
+ const CARDINAL_OFFSETS = [
76
+ { col: 0, row: -1 },
77
+ { col: 1, row: 0 },
78
+ { col: 0, row: 1 },
79
+ { col: -1, row: 0 },
80
+ ];
81
+ /** Every occupied cell orthogonally touching `cells` but outside them — the connective-piece neighbor set. */
82
+ export function boundaryNeighbors(grid, cells) {
83
+ const own = new Set(cells.map(cellKey));
84
+ const seen = new Set();
85
+ const out = [];
86
+ for (const cell of cells) {
87
+ for (const offset of CARDINAL_OFFSETS) {
88
+ const neighbor = { col: cell.col + offset.col, row: cell.row + offset.row };
89
+ const key = cellKey(neighbor);
90
+ if (own.has(key) || seen.has(key))
91
+ continue;
92
+ seen.add(key);
93
+ const kind = grid.kindAt(neighbor);
94
+ if (kind !== null)
95
+ out.push({ cell: neighbor, kind });
96
+ }
97
+ }
98
+ return out;
99
+ }
100
+ /**
101
+ * Connective-piece adjacency validity: every occupied neighbor of `cells` must satisfy `accepts`
102
+ * (no incompatible piece touching), and when `requireConnection` is true at least one neighbor must
103
+ * (a road/pipe/belt segment placed with nothing to connect to is invalid). An empty-bordered footprint
104
+ * (no occupied neighbors at all) passes unless `requireConnection` demands one.
105
+ */
106
+ export function hasValidAdjacency(grid, cells, accepts, requireConnection = false) {
107
+ const neighbors = boundaryNeighbors(grid, cells);
108
+ if (requireConnection && neighbors.length === 0)
109
+ return false;
110
+ if (!neighbors.every((neighbor) => accepts(neighbor.kind)))
111
+ return false;
112
+ return !requireConnection || neighbors.some((neighbor) => accepts(neighbor.kind));
113
+ }
114
+ /** Bridges live reservations into `world/placement`'s `PlacementRules.obstacles` so `validatePlacement`/`createPlacementController` see the grid's committed footprints unchanged. */
115
+ export function footprintObstacles(grid) {
116
+ return grid.list().map((reservation) => {
117
+ let minCol = Infinity;
118
+ let minRow = Infinity;
119
+ let maxCol = -Infinity;
120
+ let maxRow = -Infinity;
121
+ for (const cell of reservation.cells) {
122
+ if (cell.col < minCol)
123
+ minCol = cell.col;
124
+ if (cell.col > maxCol)
125
+ maxCol = cell.col;
126
+ if (cell.row < minRow)
127
+ minRow = cell.row;
128
+ if (cell.row > maxRow)
129
+ maxRow = cell.row;
130
+ }
131
+ return {
132
+ id: reservation.id,
133
+ aabb: {
134
+ minX: minCol * grid.cellSize,
135
+ maxX: (maxCol + 1) * grid.cellSize,
136
+ minZ: minRow * grid.cellSize,
137
+ maxZ: (maxRow + 1) * grid.cellSize,
138
+ },
139
+ };
140
+ });
141
+ }
@@ -1,4 +1,6 @@
1
1
  export type Vec2 = readonly [number, number];
2
+ /** A 3D point/vector as an `[x, y, z]` tuple — the engine's zero-allocation spatial primitive. */
3
+ export type Vec3 = readonly [number, number, number];
2
4
  export interface Footprint {
3
5
  w: number;
4
6
  d: number;
@@ -13,11 +15,73 @@ export interface MoveOptions {
13
15
  bounds?: Aabb;
14
16
  radius?: number;
15
17
  }
18
+ /**
19
+ * A circular clearance around a gameplay spot (spawn, plot, path point, POI): scatter is repelled
20
+ * from it and terrain is flattened toward its center. `feather` (meters) is the soft outer band —
21
+ * full effect within `radius - feather`, ramping to zero at `radius`.
22
+ */
23
+ export interface AvoidZone {
24
+ x: number;
25
+ z: number;
26
+ radius: number;
27
+ feather?: number;
28
+ }
29
+ /**
30
+ * A clearance *corridor* along a polyline (a path/road): scatter is repelled within `halfWidth` of
31
+ * the centerline, feathered over the outer band. Clean straight edges — unlike approximating a
32
+ * corridor with a scalloped chain of discs.
33
+ */
34
+ export interface AvoidCorridor {
35
+ points: readonly Vec2[];
36
+ halfWidth: number;
37
+ feather?: number;
38
+ }
39
+ /** A clearance region: point discs (spawns/plots) plus centerline corridors (paths). */
40
+ export interface AvoidMasks {
41
+ discs: readonly AvoidZone[];
42
+ corridors: readonly AvoidCorridor[];
43
+ }
44
+ /**
45
+ * How strongly a point falls inside a clearance zone: 1 at/inside the solid core, ramping to 0 at
46
+ * the zone's outer `radius` across its `feather` band, 0 outside. The max over all zones.
47
+ * @internal — the falloff math behind scatter avoid and terrain flatten.
48
+ */
49
+ export declare function zoneInfluence(x: number, z: number, zones: readonly AvoidZone[]): number;
50
+ /** Clearance influence of a corridor: nearest-segment distance vs `halfWidth`, feathered. @internal */
51
+ export declare function corridorInfluence(x: number, z: number, corridor: AvoidCorridor): number;
52
+ /** Combined clearance influence of discs + corridors — the max over every mask. @internal */
53
+ export declare function masksInfluence(x: number, z: number, masks: AvoidMasks): number;
54
+ /** @internal */
16
55
  export declare function snapToGrid(point: Vec2, size: number): Vec2;
56
+ /** @internal */
17
57
  export declare function footprintAabb(center: Vec2, footprint: Footprint, quarterTurns?: number): Aabb;
58
+ /** @internal */
18
59
  export declare function expandAabb(aabb: Aabb, margin: number): Aabb;
60
+ /** @internal */
19
61
  export declare function aabbOverlap(a: Aabb, b: Aabb): boolean;
62
+ /** @internal */
20
63
  export declare function aabbContains(outer: Aabb, inner: Aabb): boolean;
64
+ /** @internal */
21
65
  export declare function pointInAabb(point: Vec2, aabb: Aabb): boolean;
66
+ /** @internal */
22
67
  export declare function clampToAabb(point: Vec2, aabb: Aabb): Vec2;
68
+ /** @internal */
23
69
  export declare function resolveMove(from: Vec2, delta: Vec2, blockers: readonly Aabb[], options?: MoveOptions): Vec2;
70
+ /** An axis-aligned ellipse: `center` with semi-axes `radiusX` and `radiusY`. */
71
+ export interface Ellipse {
72
+ center: Vec2;
73
+ radiusX: number;
74
+ radiusY: number;
75
+ }
76
+ /** True when `point` sits inside (or on) the ellipse — the oval-arena containment test.
77
+ * @internal
78
+ */
79
+ export declare function pointInEllipse(point: Vec2, ellipse: Ellipse): boolean;
80
+ /** Clamp `point` to the ellipse boundary when it strays outside, else return it unchanged.
81
+ * @internal
82
+ */
83
+ export declare function clampToEllipse(point: Vec2, ellipse: Ellipse): Vec2;
84
+ /** Outward unit normal of the ellipse at the point nearest `point` — the boundary bounce direction.
85
+ * @internal
86
+ */
87
+ export declare function ellipseNormal(point: Vec2, ellipse: Ellipse): Vec2;