@jgengine/core 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (727) hide show
  1. package/CHANGELOG.md +39 -2
  2. package/LICENSE +203 -661
  3. package/README.md +1 -1
  4. package/dist/ai/crowd.d.ts +55 -0
  5. package/dist/ai/crowd.js +114 -0
  6. package/dist/ai/flock.d.ts +5 -2
  7. package/dist/ai/flock.js +5 -2
  8. package/dist/ai/groupAssist.d.ts +1 -0
  9. package/dist/ai/groupAssist.js +1 -0
  10. package/dist/ai/heatSystem.d.ts +76 -0
  11. package/dist/ai/heatSystem.js +97 -0
  12. package/dist/ai/interestScheduler.d.ts +107 -0
  13. package/dist/ai/interestScheduler.js +118 -0
  14. package/dist/ai/jobBoard.d.ts +1 -0
  15. package/dist/ai/jobBoard.js +1 -0
  16. package/dist/ai/laneSelect.d.ts +5 -2
  17. package/dist/ai/laneSelect.js +5 -2
  18. package/dist/ai/mobBrain.d.ts +1 -0
  19. package/dist/ai/mobBrain.js +1 -0
  20. package/dist/ai/populationDirector.d.ts +103 -0
  21. package/dist/ai/populationDirector.js +190 -0
  22. package/dist/ai/pursuit.d.ts +56 -0
  23. package/dist/ai/pursuit.js +53 -0
  24. package/dist/ai/spawnDirector.d.ts +7 -2
  25. package/dist/ai/spawnDirector.js +18 -15
  26. package/dist/ai/spawnPoint.d.ts +3 -1
  27. package/dist/ai/spawnPoint.js +3 -1
  28. package/dist/ai/targetAcquisition.d.ts +84 -0
  29. package/dist/ai/targetAcquisition.js +92 -0
  30. package/dist/anim/easing.d.ts +19 -0
  31. package/dist/anim/easing.js +19 -0
  32. package/dist/anim/oscillator.d.ts +12 -0
  33. package/dist/anim/oscillator.js +25 -0
  34. package/dist/area/areaEffectField.d.ts +127 -0
  35. package/dist/area/areaEffectField.js +175 -0
  36. package/dist/area/stackPolicy.d.ts +47 -0
  37. package/dist/area/stackPolicy.js +99 -0
  38. package/dist/authoring.d.ts +2 -1
  39. package/dist/authoring.js +2 -1
  40. package/dist/board/laneBoard.d.ts +13 -0
  41. package/dist/board/laneBoard.js +13 -0
  42. package/dist/board/timelineBoard.d.ts +10 -0
  43. package/dist/board/timelineBoard.js +10 -0
  44. package/dist/combat/abilityKit.d.ts +18 -0
  45. package/dist/combat/abilityKit.js +24 -9
  46. package/dist/combat/animationState.d.ts +5 -0
  47. package/dist/combat/animationState.js +5 -0
  48. package/dist/combat/breakMeters.d.ts +10 -0
  49. package/dist/combat/breakMeters.js +10 -0
  50. package/dist/combat/castRunner.d.ts +5 -0
  51. package/dist/combat/castRunner.js +5 -0
  52. package/dist/combat/comboPoints.d.ts +5 -0
  53. package/dist/combat/comboPoints.js +5 -0
  54. package/dist/combat/comboString.d.ts +5 -0
  55. package/dist/combat/comboString.js +5 -0
  56. package/dist/combat/damageInterceptors.d.ts +192 -0
  57. package/dist/combat/damageInterceptors.js +251 -0
  58. package/dist/combat/damageMatchup.d.ts +68 -0
  59. package/dist/combat/damageMatchup.js +42 -0
  60. package/dist/combat/damageResolution.d.ts +63 -0
  61. package/dist/combat/damageResolution.js +50 -0
  62. package/dist/combat/death.d.ts +7 -1
  63. package/dist/combat/death.js +5 -0
  64. package/dist/combat/deathReason.d.ts +14 -0
  65. package/dist/combat/deathReason.js +1 -0
  66. package/dist/combat/defensiveWindow.d.ts +5 -0
  67. package/dist/combat/defensiveWindow.js +5 -0
  68. package/dist/combat/dotField.d.ts +5 -1
  69. package/dist/combat/dotField.js +5 -1
  70. package/dist/combat/downed.d.ts +5 -0
  71. package/dist/combat/downed.js +5 -0
  72. package/dist/combat/effects.d.ts +5 -0
  73. package/dist/combat/effects.js +5 -0
  74. package/dist/combat/encounterSequence.d.ts +258 -0
  75. package/dist/combat/encounterSequence.js +426 -0
  76. package/dist/combat/hitReaction.d.ts +57 -1
  77. package/dist/combat/hitReaction.js +45 -5
  78. package/dist/combat/magazine.d.ts +54 -0
  79. package/dist/combat/magazine.js +96 -0
  80. package/dist/combat/projectiles.d.ts +5 -0
  81. package/dist/combat/projectiles.js +32 -14
  82. package/dist/combat/receivedDamage.d.ts +117 -0
  83. package/dist/combat/receivedDamage.js +92 -0
  84. package/dist/combat/regenShield.d.ts +5 -1
  85. package/dist/combat/regenShield.js +5 -1
  86. package/dist/combat/renderCues.d.ts +51 -0
  87. package/dist/combat/renderCues.js +44 -0
  88. package/dist/combat/resourcePool.d.ts +5 -0
  89. package/dist/combat/resourcePool.js +5 -0
  90. package/dist/combat/rewardAllocation.d.ts +121 -0
  91. package/dist/combat/rewardAllocation.js +251 -0
  92. package/dist/combat/shotOrigin.d.ts +18 -1
  93. package/dist/combat/shotOrigin.js +39 -0
  94. package/dist/combat/statusApplication.d.ts +96 -0
  95. package/dist/combat/statusApplication.js +81 -0
  96. package/dist/combat/telegraph.d.ts +11 -2
  97. package/dist/combat/telegraph.js +11 -2
  98. package/dist/combat/thresholdCrossings.d.ts +85 -0
  99. package/dist/combat/thresholdCrossings.js +116 -0
  100. package/dist/combat.d.ts +35 -0
  101. package/dist/combat.js +35 -0
  102. package/dist/commands/commandRegistry.d.ts +11 -0
  103. package/dist/commands/commandRegistry.js +9 -2
  104. package/dist/crafting/crop.d.ts +18 -0
  105. package/dist/crafting/crop.js +18 -0
  106. package/dist/crafting/production.d.ts +5 -0
  107. package/dist/crafting/production.js +5 -0
  108. package/dist/devtools/controls.d.ts +38 -0
  109. package/dist/devtools/controls.js +181 -0
  110. package/dist/devtools/devtools.d.ts +5 -197
  111. package/dist/devtools/devtools.js +38 -774
  112. package/dist/devtools/discover.d.ts +32 -0
  113. package/dist/devtools/discover.js +240 -0
  114. package/dist/devtools/fallbackSeams.d.ts +50 -0
  115. package/dist/devtools/fallbackSeams.js +111 -0
  116. package/dist/devtools/frame.d.ts +15 -0
  117. package/dist/devtools/frame.js +247 -0
  118. package/dist/devtools/logs.d.ts +15 -0
  119. package/dist/devtools/logs.js +86 -0
  120. package/dist/devtools/overrides.d.ts +16 -0
  121. package/dist/devtools/overrides.js +66 -0
  122. package/dist/devtools/rewriteTunables.d.ts +17 -0
  123. package/dist/devtools/rewriteTunables.js +276 -0
  124. package/dist/devtools/saveEndpoint.d.ts +46 -0
  125. package/dist/devtools/saveEndpoint.js +48 -0
  126. package/dist/devtools/transformTunables.d.ts +3 -0
  127. package/dist/devtools/transformTunables.js +3 -0
  128. package/dist/devtools/tunableSchema.d.ts +31 -0
  129. package/dist/devtools/tunableSchema.js +31 -0
  130. package/dist/devtools/types.d.ts +212 -0
  131. package/dist/devtools/types.js +1 -0
  132. package/dist/economy/auctionBook.d.ts +122 -0
  133. package/dist/economy/auctionBook.js +213 -0
  134. package/dist/economy/currency.d.ts +12 -1
  135. package/dist/economy/currency.js +12 -1
  136. package/dist/economy/listingBook.d.ts +91 -0
  137. package/dist/economy/listingBook.js +144 -0
  138. package/dist/economy/priceHistory.d.ts +44 -0
  139. package/dist/economy/priceHistory.js +89 -0
  140. package/dist/economy/resourceLedger.d.ts +222 -0
  141. package/dist/economy/resourceLedger.js +353 -0
  142. package/dist/economy/sharedWallet.d.ts +14 -0
  143. package/dist/economy/sharedWallet.js +14 -0
  144. package/dist/economy/techTree.d.ts +12 -0
  145. package/dist/economy/techTree.js +12 -0
  146. package/dist/economy/unlockPoints.d.ts +92 -0
  147. package/dist/economy/unlockPoints.js +103 -0
  148. package/dist/economy/wallet.d.ts +26 -2
  149. package/dist/economy/wallet.js +35 -6
  150. package/dist/editor/commandApply.d.ts +5 -0
  151. package/dist/editor/commandApply.js +755 -0
  152. package/dist/editor/commands.d.ts +235 -7
  153. package/dist/editor/commands.js +82 -124
  154. package/dist/editor/directives.d.ts +94 -0
  155. package/dist/editor/directives.js +206 -0
  156. package/dist/editor/document.d.ts +194 -13
  157. package/dist/editor/document.js +1166 -19
  158. package/dist/editor/entityCatalog.d.ts +42 -0
  159. package/dist/editor/entityCatalog.js +101 -0
  160. package/dist/editor/environment.d.ts +74 -0
  161. package/dist/editor/environment.js +169 -0
  162. package/dist/editor/grid.d.ts +229 -0
  163. package/dist/editor/grid.js +366 -0
  164. package/dist/editor/gridAdapters.d.ts +80 -0
  165. package/dist/editor/gridAdapters.js +134 -0
  166. package/dist/editor/index.d.ts +98 -6
  167. package/dist/editor/index.js +13 -2
  168. package/dist/editor/liveSync.d.ts +127 -0
  169. package/dist/editor/liveSync.js +249 -0
  170. package/dist/editor/minimap.d.ts +31 -0
  171. package/dist/editor/minimap.js +73 -0
  172. package/dist/editor/runtimeInspector.d.ts +88 -0
  173. package/dist/editor/runtimeInspector.js +239 -0
  174. package/dist/editor/streamer.d.ts +66 -0
  175. package/dist/editor/streamer.js +68 -0
  176. package/dist/editor/types.d.ts +250 -1
  177. package/dist/editor/world.d.ts +136 -0
  178. package/dist/editor/world.js +303 -0
  179. package/dist/faction/reputation.d.ts +5 -0
  180. package/dist/faction/reputation.js +5 -0
  181. package/dist/format/distance.d.ts +17 -0
  182. package/dist/format/distance.js +18 -0
  183. package/dist/format/duration.d.ts +27 -0
  184. package/dist/format/duration.js +45 -0
  185. package/dist/format/speed.d.ts +17 -0
  186. package/dist/format/speed.js +25 -0
  187. package/dist/game/breeding.d.ts +161 -0
  188. package/dist/game/breeding.js +181 -0
  189. package/dist/game/cameraConfig.d.ts +451 -0
  190. package/dist/game/cameraConfig.js +1 -0
  191. package/dist/game/connectedPlayers.d.ts +6 -4
  192. package/dist/game/connectedPlayers.js +2 -2
  193. package/dist/game/cosmetics.d.ts +9 -0
  194. package/dist/game/cosmetics.js +16 -0
  195. package/dist/game/defineGame.d.ts +110 -5
  196. package/dist/game/defineGame.js +49 -4
  197. package/dist/game/defineSystem.d.ts +90 -0
  198. package/dist/game/defineSystem.js +47 -0
  199. package/dist/game/dialogue.d.ts +33 -0
  200. package/dist/game/dialogue.js +21 -0
  201. package/dist/game/events.d.ts +63 -13
  202. package/dist/game/events.js +5 -0
  203. package/dist/game/feed.d.ts +33 -0
  204. package/dist/game/feed.js +35 -2
  205. package/dist/game/gamePhase.d.ts +11 -0
  206. package/dist/game/gamePhase.js +16 -0
  207. package/dist/game/leaderboard.d.ts +5 -0
  208. package/dist/game/leaderboard.js +5 -0
  209. package/dist/game/loadout.d.ts +5 -0
  210. package/dist/game/loadout.js +5 -0
  211. package/dist/game/lootFilter.d.ts +2 -0
  212. package/dist/game/lootFilter.js +2 -0
  213. package/dist/game/lootPipeline.d.ts +164 -0
  214. package/dist/game/lootPipeline.js +216 -0
  215. package/dist/game/lootTable.d.ts +19 -2
  216. package/dist/game/lootTable.js +15 -5
  217. package/dist/game/objectives.d.ts +43 -0
  218. package/dist/game/objectives.js +36 -0
  219. package/dist/game/paramLayers.d.ts +148 -0
  220. package/dist/game/paramLayers.js +185 -0
  221. package/dist/game/ping.d.ts +5 -0
  222. package/dist/game/ping.js +5 -0
  223. package/dist/game/playableGame.d.ts +116 -432
  224. package/dist/game/playableGame.js +1 -1
  225. package/dist/game/progression.d.ts +35 -0
  226. package/dist/game/progression.js +19 -0
  227. package/dist/game/quest.d.ts +8 -0
  228. package/dist/game/quest.js +30 -3
  229. package/dist/game/race.d.ts +141 -0
  230. package/dist/game/race.js +169 -0
  231. package/dist/game/recordBook.d.ts +3 -1
  232. package/dist/game/recordBook.js +4 -1
  233. package/dist/game/ruleSelection.d.ts +75 -0
  234. package/dist/game/ruleSelection.js +127 -0
  235. package/dist/game/runDraft.d.ts +5 -0
  236. package/dist/game/runDraft.js +5 -0
  237. package/dist/game/saveStore.d.ts +111 -0
  238. package/dist/game/saveStore.js +312 -0
  239. package/dist/game/snapshotHistory.d.ts +67 -0
  240. package/dist/game/snapshotHistory.js +95 -0
  241. package/dist/game/social.d.ts +38 -1
  242. package/dist/game/social.js +71 -0
  243. package/dist/game/spawnPoints.d.ts +5 -0
  244. package/dist/game/spawnPoints.js +5 -0
  245. package/dist/game/systemRuntime.d.ts +50 -0
  246. package/dist/game/systemRuntime.js +157 -0
  247. package/dist/game/systemSchedule.d.ts +72 -0
  248. package/dist/game/systemSchedule.js +242 -0
  249. package/dist/game/toasts.d.ts +43 -0
  250. package/dist/game/toasts.js +44 -0
  251. package/dist/game/trade.d.ts +10 -0
  252. package/dist/game/trade.js +10 -0
  253. package/dist/game/tribe.d.ts +184 -0
  254. package/dist/game/tribe.js +432 -0
  255. package/dist/game/unlocks.d.ts +8 -0
  256. package/dist/game/unlocks.js +16 -0
  257. package/dist/game/vfxInstance.d.ts +138 -0
  258. package/dist/game/vfxInstance.js +96 -0
  259. package/dist/game/worldItem.d.ts +17 -4
  260. package/dist/game/worldItem.js +17 -4
  261. package/dist/gameplay.d.ts +93 -0
  262. package/dist/gameplay.js +93 -0
  263. package/dist/index.d.ts +5 -14
  264. package/dist/index.js +5 -14
  265. package/dist/input/actionBindings.d.ts +23 -6
  266. package/dist/input/actionBindings.js +23 -6
  267. package/dist/input/axisInput.d.ts +7 -2
  268. package/dist/input/axisInput.js +7 -2
  269. package/dist/input/controlGroups.d.ts +67 -0
  270. package/dist/input/controlGroups.js +41 -0
  271. package/dist/input/touchScheme.d.ts +82 -6
  272. package/dist/input/touchScheme.js +123 -10
  273. package/dist/interaction/lockpick.d.ts +61 -0
  274. package/dist/interaction/lockpick.js +168 -0
  275. package/dist/interaction/proximityPrompt.d.ts +2 -0
  276. package/dist/interaction/proximityPrompt.js +2 -0
  277. package/dist/interaction/qte.d.ts +5 -0
  278. package/dist/interaction/qte.js +5 -0
  279. package/dist/interaction/skillCheck.d.ts +5 -0
  280. package/dist/interaction/skillCheck.js +5 -0
  281. package/dist/inventory/encumbrance.d.ts +69 -0
  282. package/dist/inventory/encumbrance.js +68 -0
  283. package/dist/inventory/inventoryModel.d.ts +12 -0
  284. package/dist/inventory/inventoryModel.js +12 -0
  285. package/dist/inventory/shapedGrid.d.ts +16 -0
  286. package/dist/inventory/shapedGrid.js +16 -0
  287. package/dist/inventory/slotModel.d.ts +10 -0
  288. package/dist/inventory/slotModel.js +10 -0
  289. package/dist/item/durability.d.ts +5 -0
  290. package/dist/item/durability.js +6 -3
  291. package/dist/item/itemIdentity.d.ts +171 -0
  292. package/dist/item/itemIdentity.js +138 -0
  293. package/dist/item/itemInstanceRegistry.d.ts +32 -0
  294. package/dist/item/itemInstanceRegistry.js +34 -0
  295. package/dist/item/itemgen.d.ts +163 -0
  296. package/dist/item/itemgen.js +151 -0
  297. package/dist/item/modularItem.d.ts +5 -0
  298. package/dist/item/modularItem.js +5 -0
  299. package/dist/item/use.d.ts +5 -0
  300. package/dist/item/use.js +5 -0
  301. package/dist/item/useBehavior.d.ts +142 -0
  302. package/dist/item/useBehavior.js +105 -0
  303. package/dist/item/weapon.d.ts +5 -0
  304. package/dist/item/weapon.js +5 -0
  305. package/dist/math/scalar.d.ts +25 -0
  306. package/dist/math/scalar.js +47 -0
  307. package/dist/meta/changelog.d.ts +4 -1
  308. package/dist/meta/changelog.js +39 -2
  309. package/dist/movement/avoidance.d.ts +45 -0
  310. package/dist/movement/avoidance.js +123 -0
  311. package/dist/movement/cameraRig.d.ts +8 -0
  312. package/dist/movement/cameraRig.js +8 -0
  313. package/dist/movement/dash.d.ts +11 -0
  314. package/dist/movement/dash.js +11 -0
  315. package/dist/movement/formation.d.ts +135 -0
  316. package/dist/movement/formation.js +194 -0
  317. package/dist/movement/glideModel.d.ts +5 -0
  318. package/dist/movement/glideModel.js +5 -0
  319. package/dist/movement/grappleSwing.d.ts +5 -0
  320. package/dist/movement/grappleSwing.js +5 -0
  321. package/dist/movement/leaderTrail.d.ts +5 -0
  322. package/dist/movement/leaderTrail.js +5 -0
  323. package/dist/movement/movementModel.d.ts +50 -9
  324. package/dist/movement/movementModel.js +75 -29
  325. package/dist/movement/playerMovement.js +167 -12
  326. package/dist/movement/poseState.d.ts +13 -0
  327. package/dist/movement/poseState.js +16 -0
  328. package/dist/movement/steering.d.ts +8 -0
  329. package/dist/movement/steering.js +18 -0
  330. package/dist/multiplayer/combatSnapshot.d.ts +3 -0
  331. package/dist/multiplayer/combatSnapshot.js +16 -8
  332. package/dist/multiplayer/lagCompensation.d.ts +5 -0
  333. package/dist/multiplayer/lagCompensation.js +5 -0
  334. package/dist/multiplayer/presenceModel.d.ts +11 -1
  335. package/dist/multiplayer/presenceModel.js +17 -1
  336. package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
  337. package/dist/multiplayer/simultaneousCommit.js +3 -0
  338. package/dist/multiplayer.d.ts +11 -0
  339. package/dist/multiplayer.js +11 -0
  340. package/dist/nav/pathFollow.d.ts +57 -0
  341. package/dist/nav/pathFollow.js +109 -0
  342. package/dist/orders/orderKinds.d.ts +156 -0
  343. package/dist/orders/orderKinds.js +197 -0
  344. package/dist/orders/orderQueue.d.ts +208 -0
  345. package/dist/orders/orderQueue.js +211 -0
  346. package/dist/physics/drivableVehicle.d.ts +31 -0
  347. package/dist/physics/drivableVehicle.js +16 -0
  348. package/dist/physics/flightDynamics.d.ts +82 -0
  349. package/dist/physics/flightDynamics.js +165 -0
  350. package/dist/physics/gravityField.d.ts +25 -0
  351. package/dist/physics/gravityField.js +41 -0
  352. package/dist/physics/kinematicVehicle.d.ts +108 -1
  353. package/dist/physics/kinematicVehicle.js +212 -15
  354. package/dist/physics/physicsWorld.d.ts +50 -12
  355. package/dist/physics/physicsWorld.js +120 -122
  356. package/dist/physics/radialImpulse.d.ts +25 -0
  357. package/dist/physics/radialImpulse.js +27 -0
  358. package/dist/physics/vehicleObstacles.d.ts +44 -0
  359. package/dist/physics/vehicleObstacles.js +115 -0
  360. package/dist/procedural.d.ts +3 -0
  361. package/dist/procedural.js +3 -0
  362. package/dist/progression/statGraph.d.ts +116 -0
  363. package/dist/progression/statGraph.js +318 -0
  364. package/dist/puzzle/cellGrid.d.ts +9 -0
  365. package/dist/puzzle/cellGrid.js +9 -0
  366. package/dist/puzzle/fallingPiece.d.ts +9 -0
  367. package/dist/puzzle/fallingPiece.js +9 -0
  368. package/dist/puzzle/nonogram.d.ts +39 -0
  369. package/dist/puzzle/nonogram.js +136 -0
  370. package/dist/random/nameGen.d.ts +5 -0
  371. package/dist/random/nameGen.js +5 -0
  372. package/dist/random/pick.d.ts +8 -0
  373. package/dist/random/pick.js +31 -0
  374. package/dist/random/rng.d.ts +26 -1
  375. package/dist/random/rng.js +32 -9
  376. package/dist/random/seedLink.d.ts +4 -0
  377. package/dist/random/seedLink.js +4 -0
  378. package/dist/relation/keyedValues.d.ts +54 -0
  379. package/dist/relation/keyedValues.js +115 -0
  380. package/dist/relation/thresholds.d.ts +62 -0
  381. package/dist/relation/thresholds.js +62 -0
  382. package/dist/render/color.d.ts +12 -0
  383. package/dist/render/color.js +26 -0
  384. package/dist/render/lookPreset.d.ts +41 -0
  385. package/dist/render/lookPreset.js +29 -0
  386. package/dist/render/postProcessing.d.ts +20 -0
  387. package/dist/render/postProcessing.js +21 -1
  388. package/dist/rules/predicate.d.ts +53 -0
  389. package/dist/rules/predicate.js +64 -0
  390. package/dist/rules/ruleEffects.d.ts +38 -0
  391. package/dist/rules/ruleEffects.js +37 -0
  392. package/dist/rules/triggeredRules.d.ts +160 -0
  393. package/dist/rules/triggeredRules.js +241 -0
  394. package/dist/runtime/adapter.d.ts +55 -3
  395. package/dist/runtime/adapter.js +57 -1
  396. package/dist/runtime/cameraDirector.d.ts +1 -0
  397. package/dist/runtime/cameraDirector.js +1 -0
  398. package/dist/runtime/commandRunner.d.ts +1 -0
  399. package/dist/runtime/commandRunner.js +1 -0
  400. package/dist/runtime/context/combat.d.ts +51 -0
  401. package/dist/runtime/context/combat.js +130 -0
  402. package/dist/runtime/context/combatFx.d.ts +23 -0
  403. package/dist/runtime/context/combatFx.js +161 -0
  404. package/dist/runtime/context/deathLoot.d.ts +30 -0
  405. package/dist/runtime/context/deathLoot.js +39 -0
  406. package/dist/runtime/context/player.d.ts +48 -0
  407. package/dist/runtime/context/player.js +125 -0
  408. package/dist/runtime/context/registries.d.ts +13 -0
  409. package/dist/runtime/context/registries.js +84 -0
  410. package/dist/runtime/context/scene.d.ts +59 -0
  411. package/dist/runtime/context/scene.js +291 -0
  412. package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
  413. package/dist/runtime/context/snapshotCodecs.js +26 -0
  414. package/dist/runtime/context/worldItems.d.ts +21 -0
  415. package/dist/runtime/context/worldItems.js +37 -0
  416. package/dist/runtime/descriptors/baseline.d.ts +48 -0
  417. package/dist/runtime/descriptors/baseline.js +157 -0
  418. package/dist/runtime/descriptors/features.d.ts +79 -0
  419. package/dist/runtime/descriptors/features.js +299 -0
  420. package/dist/runtime/gameContext.d.ts +2 -327
  421. package/dist/runtime/gameContext.js +273 -778
  422. package/dist/runtime/gameContextTypes.d.ts +467 -0
  423. package/dist/runtime/gameContextTypes.js +1 -0
  424. package/dist/runtime/gameRuntime.d.ts +1 -0
  425. package/dist/runtime/gameRuntime.js +1 -0
  426. package/dist/runtime/headlessRunner.d.ts +62 -0
  427. package/dist/runtime/headlessRunner.js +45 -0
  428. package/dist/runtime/hostPersistence.d.ts +12 -0
  429. package/dist/runtime/hostPersistence.js +12 -0
  430. package/dist/runtime/hostPolicy.d.ts +51 -0
  431. package/dist/runtime/hostPolicy.js +68 -0
  432. package/dist/runtime/hostedGameRunner.d.ts +11 -4
  433. package/dist/runtime/hostedGameRunner.js +27 -3
  434. package/dist/runtime/hostedWorldSession.d.ts +15 -5
  435. package/dist/runtime/hostedWorldSession.js +12 -4
  436. package/dist/runtime/inputSnapshot.d.ts +8 -3
  437. package/dist/runtime/inputSnapshot.js +6 -2
  438. package/dist/runtime/motionIntents.d.ts +11 -2
  439. package/dist/runtime/motionIntents.js +16 -2
  440. package/dist/runtime/perContext.d.ts +15 -0
  441. package/dist/runtime/perContext.js +21 -0
  442. package/dist/runtime/runtimeSave.d.ts +79 -0
  443. package/dist/runtime/runtimeSave.js +105 -0
  444. package/dist/runtime/save.d.ts +4 -0
  445. package/dist/runtime/save.js +4 -0
  446. package/dist/runtime/snapshot.d.ts +7 -0
  447. package/dist/runtime/snapshot.js +7 -0
  448. package/dist/runtime/visibility.d.ts +2 -1
  449. package/dist/runtime/visibility.js +2 -1
  450. package/dist/runtime/worldChannel.d.ts +7 -3
  451. package/dist/runtime/worldChannel.js +51 -6
  452. package/dist/runtime/worldMirror.d.ts +14 -2
  453. package/dist/runtime/worldMirror.js +15 -2
  454. package/dist/runtime/worldProjection.d.ts +47 -0
  455. package/dist/runtime/worldProjection.js +52 -0
  456. package/dist/runtime/worldReplication.d.ts +30 -7
  457. package/dist/runtime/worldReplication.js +41 -9
  458. package/dist/runtime/worldSnapshot.d.ts +42 -3
  459. package/dist/runtime/worldSnapshot.js +34 -7
  460. package/dist/scene/assetCatalog.d.ts +26 -0
  461. package/dist/scene/assetCatalog.js +4 -0
  462. package/dist/scene/assetDiagnostics.d.ts +69 -0
  463. package/dist/scene/assetDiagnostics.js +110 -0
  464. package/dist/scene/assetGenerator.d.ts +65 -0
  465. package/dist/scene/assetGenerator.js +64 -0
  466. package/dist/scene/assetSpace.d.ts +137 -0
  467. package/dist/scene/assetSpace.js +257 -0
  468. package/dist/scene/authoredTriggers.d.ts +219 -0
  469. package/dist/scene/authoredTriggers.js +454 -0
  470. package/dist/scene/behaviorRuntime.d.ts +75 -0
  471. package/dist/scene/behaviorRuntime.js +217 -0
  472. package/dist/scene/behaviors.d.ts +14 -2
  473. package/dist/scene/behaviors.js +7 -2
  474. package/dist/scene/bodyBind.d.ts +60 -0
  475. package/dist/scene/bodyBind.js +51 -0
  476. package/dist/scene/builtinSceneKinds.d.ts +5 -0
  477. package/dist/scene/builtinSceneKinds.js +67 -0
  478. package/dist/scene/colliders.d.ts +71 -1
  479. package/dist/scene/colliders.js +145 -1
  480. package/dist/scene/collisionMesh.d.ts +94 -0
  481. package/dist/scene/collisionMesh.js +699 -0
  482. package/dist/scene/companion.d.ts +147 -0
  483. package/dist/scene/companion.js +193 -0
  484. package/dist/scene/entityStats.d.ts +18 -11
  485. package/dist/scene/entityStats.js +21 -16
  486. package/dist/scene/entityStore.d.ts +12 -1
  487. package/dist/scene/entityStore.js +15 -0
  488. package/dist/scene/facing.d.ts +18 -0
  489. package/dist/scene/facing.js +26 -0
  490. package/dist/scene/modelSockets.d.ts +33 -0
  491. package/dist/scene/modelSockets.js +29 -0
  492. package/dist/scene/objectQuery.d.ts +2 -0
  493. package/dist/scene/objectQuery.js +2 -0
  494. package/dist/scene/objectStore.d.ts +4 -0
  495. package/dist/scene/objectStore.js +6 -0
  496. package/dist/scene/possession.d.ts +8 -0
  497. package/dist/scene/possession.js +14 -0
  498. package/dist/scene/roster.d.ts +3 -0
  499. package/dist/scene/roster.js +12 -0
  500. package/dist/scene/sceneKinds.d.ts +256 -0
  501. package/dist/scene/sceneKinds.js +218 -0
  502. package/dist/scene/sceneOwnership.d.ts +169 -0
  503. package/dist/scene/sceneOwnership.js +179 -0
  504. package/dist/scene/sceneRaycast.js +15 -0
  505. package/dist/scene/selectionBookmarks.d.ts +93 -0
  506. package/dist/scene/selectionBookmarks.js +122 -0
  507. package/dist/scene/vehicleSeat.d.ts +68 -0
  508. package/dist/scene/vehicleSeat.js +59 -0
  509. package/dist/sensor/concealment.d.ts +3 -0
  510. package/dist/sensor/concealment.js +3 -0
  511. package/dist/sensor/freezeMonitor.d.ts +1 -0
  512. package/dist/sensor/freezeMonitor.js +1 -0
  513. package/dist/sensor/frustumSensor.d.ts +7 -3
  514. package/dist/sensor/frustumSensor.js +7 -3
  515. package/dist/sensor/hiddenStateProbe.d.ts +5 -2
  516. package/dist/sensor/hiddenStateProbe.js +5 -2
  517. package/dist/sensor/recordingBuffer.d.ts +2 -1
  518. package/dist/sensor/recordingBuffer.js +2 -1
  519. package/dist/sensor/replayLoop.d.ts +6 -2
  520. package/dist/sensor/replayLoop.js +6 -2
  521. package/dist/sensor/revealQuery.d.ts +2 -1
  522. package/dist/sensor/revealQuery.js +2 -1
  523. package/dist/sensor/visionCone.d.ts +10 -3
  524. package/dist/sensor/visionCone.js +10 -3
  525. package/dist/session/contestedChannel.d.ts +1 -0
  526. package/dist/session/contestedChannel.js +1 -0
  527. package/dist/session/extraction.d.ts +1 -0
  528. package/dist/session/extraction.js +1 -0
  529. package/dist/session/roles.d.ts +6 -0
  530. package/dist/session/roles.js +6 -0
  531. package/dist/session/roundState.d.ts +8 -0
  532. package/dist/session/roundState.js +2 -0
  533. package/dist/settings/settingsModel.d.ts +1 -0
  534. package/dist/settings/settingsModel.js +1 -0
  535. package/dist/stats/accumulatorMeter.d.ts +6 -0
  536. package/dist/stats/accumulatorMeter.js +6 -0
  537. package/dist/stats/eventMeter.d.ts +5 -0
  538. package/dist/stats/eventMeter.js +5 -0
  539. package/dist/stats/rollCheck.d.ts +5 -0
  540. package/dist/stats/rollCheck.js +5 -0
  541. package/dist/stats/spawnLevelStats.d.ts +110 -0
  542. package/dist/stats/spawnLevelStats.js +140 -0
  543. package/dist/stats/statModifiers.d.ts +5 -0
  544. package/dist/stats/statModifiers.js +5 -0
  545. package/dist/stats/statPool.d.ts +70 -0
  546. package/dist/stats/statPool.js +59 -0
  547. package/dist/store/changeSignal.d.ts +3 -0
  548. package/dist/store/changeSignal.js +2 -0
  549. package/dist/store/defineKeyedStore.d.ts +38 -0
  550. package/dist/store/defineKeyedStore.js +42 -0
  551. package/dist/store/defineStore.d.ts +33 -0
  552. package/dist/store/defineStore.js +35 -0
  553. package/dist/store/observableKeyedStore.d.ts +7 -0
  554. package/dist/store/observableKeyedStore.js +35 -2
  555. package/dist/survival/decayMeter.d.ts +55 -0
  556. package/dist/survival/decayMeter.js +130 -57
  557. package/dist/survival/moodle.d.ts +2 -0
  558. package/dist/survival/regionHealth.d.ts +6 -0
  559. package/dist/survival/regionHealth.js +6 -3
  560. package/dist/tactics/fallingGrid.d.ts +4 -2
  561. package/dist/tactics/fallingGrid.js +4 -2
  562. package/dist/tactics/predictiveQuery.d.ts +3 -0
  563. package/dist/tactics/predictiveQuery.js +3 -0
  564. package/dist/tactics/snapshot.d.ts +2 -0
  565. package/dist/tactics/snapshot.js +2 -0
  566. package/dist/tactics/surface.d.ts +1 -0
  567. package/dist/tactics/surface.js +1 -0
  568. package/dist/tactics/tacticalGrid.d.ts +1 -0
  569. package/dist/tactics/tacticalGrid.js +1 -0
  570. package/dist/time/beatClock.d.ts +14 -4
  571. package/dist/time/beatClock.js +14 -4
  572. package/dist/time/calendarClock.d.ts +3 -0
  573. package/dist/time/calendarClock.js +3 -0
  574. package/dist/time/idleProgress.d.ts +4 -0
  575. package/dist/time/idleProgress.js +4 -0
  576. package/dist/time/simClock.d.ts +2 -0
  577. package/dist/time/simClock.js +20 -5
  578. package/dist/ui/actionModel.d.ts +110 -0
  579. package/dist/ui/actionModel.js +159 -0
  580. package/dist/ui/gameLayout.d.ts +30 -11
  581. package/dist/ui/gameLayout.js +30 -11
  582. package/dist/ui/hudDocument.d.ts +114 -0
  583. package/dist/ui/hudDocument.js +220 -0
  584. package/dist/ui/hudLayout.d.ts +38 -1
  585. package/dist/ui/hudLayout.js +220 -17
  586. package/dist/ui/selectionModel.d.ts +92 -0
  587. package/dist/ui/selectionModel.js +88 -0
  588. package/dist/ui/tooltipModel.d.ts +63 -0
  589. package/dist/ui/tooltipModel.js +82 -0
  590. package/dist/ui.d.ts +15 -0
  591. package/dist/ui.js +15 -0
  592. package/dist/visibility/bounds.d.ts +8 -1
  593. package/dist/visibility/bounds.js +8 -1
  594. package/dist/visibility/frustum.d.ts +12 -3
  595. package/dist/visibility/frustum.js +12 -3
  596. package/dist/work/jobQueue.d.ts +201 -0
  597. package/dist/work/jobQueue.js +253 -0
  598. package/dist/work/unitTraining.d.ts +58 -0
  599. package/dist/work/unitTraining.js +52 -0
  600. package/dist/world/authoredEntities.d.ts +29 -0
  601. package/dist/world/authoredEntities.js +29 -0
  602. package/dist/world/authoredObjects.d.ts +72 -0
  603. package/dist/world/authoredObjects.js +81 -0
  604. package/dist/world/authoredSpawn.d.ts +39 -0
  605. package/dist/world/authoredSpawn.js +37 -0
  606. package/dist/world/buildSockets.d.ts +152 -0
  607. package/dist/world/buildSockets.js +188 -0
  608. package/dist/world/buildingGenerator.d.ts +18 -0
  609. package/dist/world/buildingGenerator.js +62 -0
  610. package/dist/world/buildings.d.ts +5 -0
  611. package/dist/world/buildings.js +5 -0
  612. package/dist/world/catenary.d.ts +22 -0
  613. package/dist/world/catenary.js +69 -0
  614. package/dist/world/cityBlocks.d.ts +152 -0
  615. package/dist/world/cityBlocks.js +670 -0
  616. package/dist/world/cityContent.d.ts +77 -0
  617. package/dist/world/cityContent.js +261 -0
  618. package/dist/world/cityGeometry.d.ts +114 -0
  619. package/dist/world/cityGeometry.js +573 -0
  620. package/dist/world/cityKind.d.ts +314 -0
  621. package/dist/world/cityKind.js +1578 -0
  622. package/dist/world/features.d.ts +133 -10
  623. package/dist/world/features.js +66 -6
  624. package/dist/world/footprintGrid.d.ts +59 -0
  625. package/dist/world/footprintGrid.js +141 -0
  626. package/dist/world/geometry.d.ts +64 -0
  627. package/dist/world/geometry.js +94 -0
  628. package/dist/world/grassKind.d.ts +51 -0
  629. package/dist/world/grassKind.js +101 -0
  630. package/dist/world/markers.d.ts +50 -4
  631. package/dist/world/markers.js +49 -0
  632. package/dist/world/massing.js +1 -1
  633. package/dist/world/minimapBake.d.ts +78 -0
  634. package/dist/world/minimapBake.js +208 -0
  635. package/dist/world/minimapTrack.d.ts +17 -0
  636. package/dist/world/minimapTrack.js +22 -0
  637. package/dist/world/pathInstances.d.ts +27 -0
  638. package/dist/world/pathInstances.js +27 -0
  639. package/dist/world/pathNetwork.d.ts +159 -0
  640. package/dist/world/pathNetwork.js +684 -0
  641. package/dist/world/pathTerrain.d.ts +80 -0
  642. package/dist/world/pathTerrain.js +142 -0
  643. package/dist/world/place.d.ts +166 -0
  644. package/dist/world/place.js +96 -0
  645. package/dist/world/placeAsset.d.ts +81 -0
  646. package/dist/world/placeAsset.js +79 -0
  647. package/dist/world/placement.d.ts +4 -0
  648. package/dist/world/placement.js +4 -0
  649. package/dist/world/placementController.d.ts +6 -0
  650. package/dist/world/placementController.js +6 -0
  651. package/dist/world/poleLineKind.d.ts +40 -0
  652. package/dist/world/poleLineKind.js +97 -0
  653. package/dist/world/polyline.d.ts +34 -0
  654. package/dist/world/polyline.js +88 -0
  655. package/dist/world/resourceNode.d.ts +109 -0
  656. package/dist/world/resourceNode.js +140 -0
  657. package/dist/world/roads.d.ts +8 -0
  658. package/dist/world/roads.js +38 -0
  659. package/dist/world/scatter.js +2 -20
  660. package/dist/world/scatterRegion.d.ts +164 -0
  661. package/dist/world/scatterRegion.js +409 -0
  662. package/dist/world/sceneShapes.d.ts +43 -0
  663. package/dist/world/sceneShapes.js +1 -0
  664. package/dist/world/segment.d.ts +27 -0
  665. package/dist/world/segment.js +43 -0
  666. package/dist/world/soilKind.d.ts +48 -0
  667. package/dist/world/soilKind.js +92 -0
  668. package/dist/world/spatialSample.d.ts +241 -0
  669. package/dist/world/spatialSample.js +465 -0
  670. package/dist/world/streets.d.ts +29 -0
  671. package/dist/world/streets.js +55 -0
  672. package/dist/world/terraform.d.ts +213 -1
  673. package/dist/world/terraform.js +627 -22
  674. package/dist/world/terrain.d.ts +164 -20
  675. package/dist/world/terrain.js +325 -41
  676. package/dist/world/terrainGuides.d.ts +182 -0
  677. package/dist/world/terrainGuides.js +343 -0
  678. package/dist/world/vec2.d.ts +81 -0
  679. package/dist/world/vec2.js +128 -0
  680. package/dist/world/vec3.d.ts +49 -0
  681. package/dist/world/vec3.js +76 -0
  682. package/dist/world/vegetation.d.ts +71 -0
  683. package/dist/world/vegetation.js +151 -0
  684. package/dist/world/visibilityField.d.ts +154 -0
  685. package/dist/world/visibilityField.js +271 -0
  686. package/dist/world/volumetricClouds.d.ts +52 -0
  687. package/dist/world/volumetricClouds.js +43 -0
  688. package/dist/world/walls.d.ts +9 -0
  689. package/dist/world/walls.js +9 -0
  690. package/dist/world/waterKind.d.ts +55 -0
  691. package/dist/world/waterKind.js +99 -0
  692. package/dist/world.d.ts +141 -0
  693. package/dist/world.js +141 -0
  694. package/package.json +32 -8
  695. package/skills/game-design/SKILL.md +28 -0
  696. package/skills/game-design/agents/openai.yaml +4 -0
  697. package/skills/game-design/references/application-playbook.md +170 -0
  698. package/skills/game-design/references/field-guide.md +288 -0
  699. package/skills/jgengine/SKILL.md +54 -0
  700. package/skills/jgengine/api.md +527 -0
  701. package/skills/jgengine/capabilities.md +131 -0
  702. package/skills/jgengine/recipes/minimal-game.md +88 -0
  703. package/skills/jgengine-combat/SKILL.md +38 -0
  704. package/skills/jgengine-combat/api.md +585 -0
  705. package/skills/jgengine-combat/capabilities.md +213 -0
  706. package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
  707. package/skills/jgengine-combat/reference.md +108 -0
  708. package/skills/jgengine-gameplay/SKILL.md +39 -0
  709. package/skills/jgengine-gameplay/api.md +1920 -0
  710. package/skills/jgengine-gameplay/capabilities.md +454 -0
  711. package/skills/jgengine-gameplay/reference-systems.md +56 -0
  712. package/skills/jgengine-world/SKILL.md +51 -0
  713. package/skills/jgengine-world/api.md +3056 -0
  714. package/skills/jgengine-world/capabilities.md +476 -0
  715. package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
  716. package/skills/jgengine-world/reference.md +261 -0
  717. package/dist/cartridge/runtime.d.ts +0 -15
  718. package/dist/cartridge/runtime.js +0 -556
  719. package/dist/cartridge/spec.d.ts +0 -188
  720. package/dist/cartridge/spec.js +0 -19
  721. package/dist/cartridge/validate.d.ts +0 -2
  722. package/dist/cartridge/validate.js +0 -78
  723. package/dist/store/engineStore.d.ts +0 -22
  724. package/dist/store/engineStore.js +0 -50
  725. package/dist/store/features.d.ts +0 -10
  726. package/dist/store/features.js +0 -23
  727. package/llms.txt +0 -5389
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Path-driven terrain modifiers: one authored centerline reshapes a heightfield across a corridor —
3
+ * flatten a roadbed, grade a constant-slope ramp, carve a river/trench, and hold retaining walls where
4
+ * the corridor cuts or fills into the surrounding ground. Genre-agnostic: roads, rails, rivers,
5
+ * trenches, runways, and accessibility ramps are all the same profile with different numbers, so no game
6
+ * hand-rolls its own flatten-mask generator. Pure XZ math over a polyline — deterministic, bounded
7
+ * (O(points) per sample), and serializable; it composes onto any height sampler and pairs with
8
+ * `resolveTerrainField` so the same authored path drives both the rendered mesh and player collision.
9
+ * @capability path-terrain flatten / grade / carve a heightfield from an authored path with retaining profiles
10
+ * @consumer packages/core/src/world/terrain.ts (resolveTerrainField), Games/the-robots roads
11
+ */
12
+ import type { Vec2 } from "./geometry.js";
13
+ /**
14
+ * Where a path corridor drives its centerline height:
15
+ * - `sample` — follow the base terrain under the centerline, so the corridor drapes level across its
16
+ * width while still tracking the hills the path crosses (the natural policy for a road or trail).
17
+ * - `fixed` — hold one constant height for the whole corridor (a level causeway, runway, or dam crest).
18
+ * - `grade` — interpolate linearly from `start` to `end` height along the path's arc length, a
19
+ * constant-slope ramp between two anchors (a switchback, a graded rail bed, an accessibility ramp).
20
+ */
21
+ export type PathHeightPolicy = {
22
+ readonly kind: "sample";
23
+ } | {
24
+ readonly kind: "fixed";
25
+ readonly height: number;
26
+ } | {
27
+ readonly kind: "grade";
28
+ readonly start: number;
29
+ readonly end: number;
30
+ };
31
+ /**
32
+ * Retaining behavior for a path corridor's shoulders. A wall rises only where the corridor already cuts or
33
+ * fills into the surrounding ground by at least `threshold` — gentle stretches stay open — so a road
34
+ * through a canyon gets held banks while the same profile on flat ground does not. The wall fades in
35
+ * smoothly across `taper` above the threshold so it never steps on or off between adjacent samples.
36
+ */
37
+ export interface PathRetaining {
38
+ /** Crest height raised above the corridor edge on both shoulders (canyon walls, road berms, levee banks). */
39
+ readonly wallHeight: number;
40
+ /** Minimum cut/fill (world units) between corridor and surrounding ground before a wall rises. Default 0 (wall the whole path). */
41
+ readonly threshold?: number;
42
+ /** Cut/fill band above `threshold` over which the wall fades from none to full height. Default equal to `threshold`. */
43
+ readonly taper?: number;
44
+ }
45
+ /**
46
+ * A serializable path-driven terrain modifier. The `points` centerline reshapes the heightfield across a
47
+ * corridor of `width`, feathering back to the surrounding ground across `shoulder`. `height` sets the
48
+ * centerline target (sample / fixed / grade); `depth` carves a channel below it (deepest at the
49
+ * centerline, easing to zero at the core edge — rivers and trenches); `retaining` raises walls where the
50
+ * cut/fill exceeds a threshold; `maxCut`/`maxFill` cap how far the ground may move from its base height.
51
+ * All fields are plain data (numbers, string enums, point arrays) so a profile round-trips through the
52
+ * scene document and evaluates identically at author time and runtime.
53
+ */
54
+ export interface TerrainPathProfile {
55
+ /** Centerline vertices in world XZ; needs at least two points. Repeat the first point as the last for a closed loop. */
56
+ readonly points: readonly Vec2[];
57
+ /** Full corridor width; the reshaped core extends `width / 2` either side of the centerline. */
58
+ readonly width: number;
59
+ /** Blend-ring width outside the core where the corridor height smoothsteps back to the surrounding ground. Default `width * 0.5`. */
60
+ readonly shoulder?: number;
61
+ /** Centerline target-height policy. Default `{ kind: "sample" }` (drape level across the base terrain). */
62
+ readonly height?: PathHeightPolicy;
63
+ /** Carve depth below the target height, deepest at the centerline and easing to zero at the core edge (0 = flat corridor). Default 0. */
64
+ readonly depth?: number;
65
+ /** Never cut the ground more than this far below its base height. Omit for unlimited cut. */
66
+ readonly maxCut?: number;
67
+ /** Never fill the ground more than this far above its base height. Omit for unlimited fill. */
68
+ readonly maxFill?: number;
69
+ /** Raise retaining walls along the shoulders where the corridor cuts/fills into the surrounding ground. */
70
+ readonly retaining?: PathRetaining;
71
+ }
72
+ /**
73
+ * Wraps a height sampler so each authored `TerrainPathProfile` reshapes it. Profiles apply in list order
74
+ * (later profiles compose over earlier ones, so an intersection's last profile wins its core); each reads
75
+ * the running height as its surrounding ground and the original `base` for `sample` centerline heights.
76
+ * The returned sampler is pure and deterministic. Degenerate profiles (fewer than two points, non-positive
77
+ * width or length) are skipped; with no usable profile the original `base` is returned unchanged.
78
+ * @capability path-terrain compose flatten/grade/carve/retaining path profiles onto a height sampler
79
+ */
80
+ export declare function withPathProfiles(base: (x: number, z: number) => number, profiles: readonly TerrainPathProfile[]): (x: number, z: number) => number;
@@ -0,0 +1,142 @@
1
+ function clamp01(value) {
2
+ return value < 0 ? 0 : value > 1 ? 1 : value;
3
+ }
4
+ function lerp(a, b, t) {
5
+ return a + (b - a) * t;
6
+ }
7
+ function smoothstep01(t) {
8
+ const clamped = clamp01(t);
9
+ return clamped * clamped * (3 - 2 * clamped);
10
+ }
11
+ function buildCorridor(points) {
12
+ const cumulative = [0];
13
+ for (let i = 1; i < points.length; i += 1) {
14
+ const a = points[i - 1];
15
+ const b = points[i];
16
+ cumulative.push(cumulative[i - 1] + Math.hypot(b[0] - a[0], b[1] - a[1]));
17
+ }
18
+ return { points, cumulative, total: cumulative[cumulative.length - 1] ?? 0 };
19
+ }
20
+ /**
21
+ * Closest point on the corridor to `(x, z)`: unsigned lateral distance and arc-length position. Self-
22
+ * contained (each segment projects independently and the minimum lateral wins) so a vertex always reports
23
+ * a near-zero lateral, regardless of which side of the line the neighbours fall.
24
+ */
25
+ function nearestOnCorridor(corridor, x, z) {
26
+ let bestLateral = Number.POSITIVE_INFINITY;
27
+ let bestAlong = 0;
28
+ let bestPoint = corridor.points[0] ?? [x, z];
29
+ for (let i = 1; i < corridor.points.length; i += 1) {
30
+ const a = corridor.points[i - 1];
31
+ const b = corridor.points[i];
32
+ const abx = b[0] - a[0];
33
+ const abz = b[1] - a[1];
34
+ const segLenSq = abx * abx + abz * abz;
35
+ const t = segLenSq <= 0 ? 0 : Math.max(0, Math.min(1, ((x - a[0]) * abx + (z - a[1]) * abz) / segLenSq));
36
+ const px = a[0] + abx * t;
37
+ const pz = a[1] + abz * t;
38
+ const lateral = Math.hypot(x - px, z - pz);
39
+ if (lateral < bestLateral) {
40
+ bestLateral = lateral;
41
+ bestAlong = corridor.cumulative[i - 1] + t * Math.sqrt(segLenSq);
42
+ bestPoint = [px, pz];
43
+ }
44
+ }
45
+ return { lateral: bestLateral, along: bestAlong, point: bestPoint };
46
+ }
47
+ function resolveProfile(profile) {
48
+ if (profile.points.length < 2 || profile.width <= 0)
49
+ return null;
50
+ const corridor = buildCorridor(profile.points.map((point) => [point[0], point[1]]));
51
+ if (corridor.total <= 0)
52
+ return null;
53
+ const shoulder = Math.max(0, profile.shoulder ?? profile.width * 0.5);
54
+ return {
55
+ corridor,
56
+ half: profile.width / 2,
57
+ shoulder,
58
+ reach: profile.width / 2 + shoulder,
59
+ height: profile.height ?? { kind: "sample" },
60
+ depth: Math.max(0, profile.depth ?? 0),
61
+ ...(profile.maxCut === undefined ? {} : { maxCut: Math.max(0, profile.maxCut) }),
62
+ ...(profile.maxFill === undefined ? {} : { maxFill: Math.max(0, profile.maxFill) }),
63
+ wallHeight: Math.max(0, profile.retaining?.wallHeight ?? 0),
64
+ threshold: Math.max(0, profile.retaining?.threshold ?? 0),
65
+ taper: Math.max(0, profile.retaining?.taper ?? profile.retaining?.threshold ?? 0),
66
+ };
67
+ }
68
+ /** Wall strength 0..1: full above `threshold + taper`, none below `threshold`, smooth between. */
69
+ function wallStrength(profile, cutFill) {
70
+ if (profile.wallHeight <= 0)
71
+ return 0;
72
+ if (cutFill < profile.threshold)
73
+ return 0;
74
+ if (profile.taper <= 0)
75
+ return 1;
76
+ return smoothstep01((cutFill - profile.threshold) / profile.taper);
77
+ }
78
+ function clampCutFill(height, base, maxCut, maxFill) {
79
+ let out = height;
80
+ if (maxFill !== undefined && out > base + maxFill)
81
+ out = base + maxFill;
82
+ if (maxCut !== undefined && out < base - maxCut)
83
+ out = base - maxCut;
84
+ return out;
85
+ }
86
+ function centerlineTarget(profile, along, point, base) {
87
+ const policy = profile.height;
88
+ if (policy.kind === "fixed")
89
+ return policy.height;
90
+ if (policy.kind === "grade") {
91
+ const fraction = profile.corridor.total <= 0 ? 0 : clamp01(along / profile.corridor.total);
92
+ return policy.start + (policy.end - policy.start) * fraction;
93
+ }
94
+ return base(point[0], point[1]);
95
+ }
96
+ function applyProfileAt(profile, x, z, surrounding, base) {
97
+ const hit = nearestOnCorridor(profile.corridor, x, z);
98
+ const lateral = hit.lateral;
99
+ if (lateral > profile.reach)
100
+ return surrounding;
101
+ const target = clampCutFill(centerlineTarget(profile, hit.along, hit.point, base), surrounding, profile.maxCut, profile.maxFill);
102
+ // Inside the core: carve a channel below the target, deepest at the centerline, level at the edge.
103
+ if (lateral <= profile.half) {
104
+ const edgeT = profile.half <= 0 ? 0 : lateral / profile.half;
105
+ const carved = target - profile.depth * (1 - edgeT * edgeT);
106
+ return clampCutFill(carved, surrounding, profile.maxCut, profile.maxFill);
107
+ }
108
+ // Shoulder: feather the corridor edge (target) back to the surrounding ground, or hold a retaining wall.
109
+ const shoulderT = clamp01((lateral - profile.half) / profile.shoulder);
110
+ const feathered = lerp(target, surrounding, smoothstep01(shoulderT));
111
+ const strength = wallStrength(profile, Math.abs(target - surrounding));
112
+ if (strength <= 0)
113
+ return feathered;
114
+ const crest = target + profile.wallHeight;
115
+ const walled = shoulderT <= 0.5 ? lerp(target, crest, smoothstep01(shoulderT / 0.5)) : lerp(crest, surrounding, smoothstep01((shoulderT - 0.5) / 0.5));
116
+ return lerp(feathered, walled, strength);
117
+ }
118
+ /**
119
+ * Wraps a height sampler so each authored `TerrainPathProfile` reshapes it. Profiles apply in list order
120
+ * (later profiles compose over earlier ones, so an intersection's last profile wins its core); each reads
121
+ * the running height as its surrounding ground and the original `base` for `sample` centerline heights.
122
+ * The returned sampler is pure and deterministic. Degenerate profiles (fewer than two points, non-positive
123
+ * width or length) are skipped; with no usable profile the original `base` is returned unchanged.
124
+ * @capability path-terrain compose flatten/grade/carve/retaining path profiles onto a height sampler
125
+ */
126
+ export function withPathProfiles(base, profiles) {
127
+ const resolved = [];
128
+ for (const profile of profiles) {
129
+ const prepared = resolveProfile(profile);
130
+ if (prepared !== null)
131
+ resolved.push(prepared);
132
+ }
133
+ if (resolved.length === 0)
134
+ return base;
135
+ return (x, z) => {
136
+ let height = base(x, z);
137
+ for (const profile of resolved) {
138
+ height = applyProfileAt(profile, x, z, height, base);
139
+ }
140
+ return height;
141
+ };
142
+ }
@@ -0,0 +1,166 @@
1
+ import type { PhysicsConfig } from "../game/defineGame.js";
2
+ /**
3
+ * The place model: a world is the place you play in — substrate (ground) plus laws (physics,
4
+ * surface) — never a dressed diorama. Sky look, foliage scatter, props, and sculpt are content:
5
+ * they are authored in the editor (or by a content preset that writes into the scene document)
6
+ * and consumed through the authored-scene seams, not declared on the world.
7
+ *
8
+ * Hard rules the API enforces:
9
+ * - No `seed` anywhere in a world definition. Determinism comes from the runtime: the engine
10
+ * derives generator/scatter seeds from the world `id` plus the save/run seed (see
11
+ * {@link seedForPlace}), so the same place replays identically without the author owning RNG.
12
+ * - No sky, vegetation, or theme fields. A world with no authored sky renders the engine
13
+ * default sky; "void"/"space" is content, not a world knob.
14
+ * - No genre or franchise presets. `generator` carries algorithm parameters only.
15
+ */
16
+ /**
17
+ * Matter/feel laws of a place's ground that systems, physics, and audio read — restitution for a
18
+ * metal chamber the pieces ping off, stickiness for a slime pit, a soft felt mat. The same rule
19
+ * systems play on any surface; swapping the surface (plus content audio) changes the feel without
20
+ * forking the rules. This is place law, not a theme kit: visual/audio dressing stays in content.
21
+ */
22
+ export interface SurfaceLaws {
23
+ /** Named matter of the ground ("metal", "slime", "felt", …) — a label systems and audio cues key off. */
24
+ matter?: string;
25
+ /** Sliding friction scalar, 0 (ice) … 1+ (grippy). Interpreted by movement/physics systems. */
26
+ friction?: number;
27
+ /** Bounce energy retention, 0 (dead stop) … 1 (perfect bounce). Interpreted by physics/board systems. */
28
+ restitution?: number;
29
+ /** Free-form serializable place-law traits game systems read (e.g. `{ stuckTurns: 1 }` for slime). */
30
+ traits?: Readonly<Record<string, number | string | boolean>>;
31
+ }
32
+ /** Serializable algorithm parameters for a procedural ground generator. Never a genre kit. */
33
+ export interface GroundGenerator {
34
+ /** Algorithm identifier the game's generation system resolves (e.g. "fbm", "caves", "layers"). */
35
+ algorithm: string;
36
+ /**
37
+ * Algorithm tuning only — amplitudes, frequencies, thresholds, palettes of ids. Never a `seed`
38
+ * (the engine injects one from world id + save/run) and never a genre/franchise preset name.
39
+ */
40
+ params?: Readonly<Record<string, number | string | boolean>>;
41
+ }
42
+ /**
43
+ * Size of a `flat` ground: extents in world units. `Infinity` on an axis means unbounded — an
44
+ * endless plain needs no bounds number invented for it. `y` optionally bounds vertical play space.
45
+ */
46
+ export interface FlatGroundSize {
47
+ x: number;
48
+ /** Optional vertical bound of the play volume; omit for open sky. */
49
+ y?: number;
50
+ z: number;
51
+ radius?: never;
52
+ }
53
+ /** Size of a `round` ground: the planet/sphere radius in world units. Nothing else. */
54
+ export interface RoundGroundSize {
55
+ radius: number;
56
+ x?: never;
57
+ y?: never;
58
+ z?: never;
59
+ }
60
+ /** Size of a `voxel` ground: the generator's domain per axis; axes may be `Infinity` for streaming volumes. */
61
+ export interface VoxelGroundSize {
62
+ x: number;
63
+ y: number;
64
+ z: number;
65
+ radius?: never;
66
+ }
67
+ /** Size of a `board` ground: a 2D surface you look at, in cells or layout units. */
68
+ export interface BoardGroundSize {
69
+ x: number;
70
+ y: number;
71
+ z?: never;
72
+ radius?: never;
73
+ }
74
+ /** A 3D walkable plane/slab. `Infinity` axes are unbounded; no separate "infinite" mode exists. */
75
+ export interface FlatGround {
76
+ mode: "flat";
77
+ size: FlatGroundSize;
78
+ surface?: SurfaceLaws;
79
+ generator?: GroundGenerator;
80
+ }
81
+ /** A planet/sphere you play on the outside of. Sized by `radius` only. */
82
+ export interface RoundGround {
83
+ mode: "round";
84
+ size: RoundGroundSize;
85
+ surface?: SurfaceLaws;
86
+ generator?: GroundGenerator;
87
+ }
88
+ /** A procedural volume of blocks. `size` is the generator domain; `generator` is algorithm params only. */
89
+ export interface VoxelGround {
90
+ mode: "voxel";
91
+ size: VoxelGroundSize;
92
+ surface?: SurfaceLaws;
93
+ generator?: GroundGenerator;
94
+ }
95
+ /**
96
+ * A 2D surface you look at — grid games, solitaire, tabletop. Physics is often zero-gravity or
97
+ * omitted; the game owns the face it draws on the board.
98
+ */
99
+ export interface BoardGround {
100
+ /** `"stage"` is accepted as an alias and normalized to `"board"`. */
101
+ mode: "board" | "stage";
102
+ size: BoardGroundSize;
103
+ surface?: SurfaceLaws;
104
+ }
105
+ /** The substrate of a place, discriminated by `mode` — TS rejects a `radius` on `flat` and `x`/`z` on `round`. */
106
+ export type GroundConfig = FlatGround | RoundGround | VoxelGround | BoardGround;
107
+ /** Canonical ground modes after normalization (`stage` → `board`). */
108
+ export type GroundMode = "flat" | "round" | "voxel" | "board";
109
+ /** {@link BoardGround} with the `stage` alias resolved away. */
110
+ export type ResolvedBoardGround = Omit<BoardGround, "mode"> & {
111
+ mode: "board";
112
+ };
113
+ /** A place's ground after `world()` normalization. */
114
+ export type ResolvedGround = FlatGround | RoundGround | VoxelGround | ResolvedBoardGround;
115
+ /** Input to {@link world}: place identity, substrate, and the laws of this place. */
116
+ export interface PlaceConfig {
117
+ /** Place identity — names the world for saves, seeds, and world switching. */
118
+ id: string;
119
+ /** The substrate: what you stand on / look at, discriminated by `mode`. */
120
+ ground: GroundConfig;
121
+ /**
122
+ * Laws of THIS place (gravity, jump). Each world carries its own physics, so a game with several
123
+ * places (a station and a moon) gives each different laws; `defineGameDefinition` resolves the
124
+ * active world's physics over the game-level default. The engine owns simulation.
125
+ */
126
+ physics?: PhysicsConfig;
127
+ }
128
+ /** A declared place — the `world()` result carried on `GameDefinition.world`. */
129
+ export interface PlaceWorldFeature {
130
+ kind: "place";
131
+ id: string;
132
+ ground: ResolvedGround;
133
+ physics?: PhysicsConfig;
134
+ }
135
+ /**
136
+ * Declares the place a game is played in: substrate (`ground`) + laws (`physics`, `ground.surface`).
137
+ * The thin default start — `flat` with `Infinity` axes and default physics, `board` for 2D — is a
138
+ * complete world; dressing it (sky, foliage, props, sculpt) is editor-authored scene content.
139
+ * Multiple worlds per game are first-class: declare one `world()` per place, each with its own id,
140
+ * ground, and physics. Games that are not a spatial place (pure UI/rules) omit `world` entirely.
141
+ *
142
+ * @capability world-place declare the place a game happens in — flat/round/voxel/board ground, surface laws, per-place physics
143
+ */
144
+ export declare function world(config: PlaceConfig): PlaceWorldFeature;
145
+ /**
146
+ * The engine-side seed derivation for a place: a stable string from the world `id` plus the
147
+ * save/run seed. Generators and scatter receive this — never a `seed` field in the world
148
+ * definition — so a save replays its world deterministically and a fresh run can vary by
149
+ * `runSeed` alone.
150
+ *
151
+ * @capability world-seed derive a deterministic generator/scatter seed from world id + save/run seed
152
+ */
153
+ export declare function seedForPlace(worldId: string, runSeed?: string): string;
154
+ /**
155
+ * Resolves the physics laws in effect for the active world: a place world's own `physics` wins
156
+ * field-by-field over the game-level default. Non-place worlds (and games with no world) keep the
157
+ * game-level config unchanged.
158
+ */
159
+ export declare function resolveWorldPhysics(worldFeature: {
160
+ kind: string;
161
+ physics?: PhysicsConfig;
162
+ } | undefined, base: PhysicsConfig | undefined): PhysicsConfig | undefined;
163
+ /** Type guard for the place-model world feature. */
164
+ export declare function isPlaceWorld(worldFeature: {
165
+ kind: string;
166
+ } | undefined): worldFeature is PlaceWorldFeature;
@@ -0,0 +1,96 @@
1
+ const BANNED_WORLD_KEYS = ["sky", "vegetation", "terrain", "environment", "weather", "seed"];
2
+ function assertNoDressing(config) {
3
+ const record = config;
4
+ for (const key of BANNED_WORLD_KEYS) {
5
+ if (record[key] !== undefined) {
6
+ throw new Error(key === "seed"
7
+ ? "world: seed does not belong in a world definition — the engine derives seeds from the world id and the save/run seed (seedForPlace)."
8
+ : `world: "${key}" does not belong in a world definition — a world is substrate + laws. Author sky, foliage, and dressing in the editor (or a content preset that writes scene data).`);
9
+ }
10
+ }
11
+ }
12
+ function assertAxis(mode, axis, value, allowInfinite) {
13
+ const ok = value > 0 && (allowInfinite ? true : Number.isFinite(value));
14
+ if (!ok) {
15
+ throw new Error(`world: ground.size.${axis} for mode "${mode}" must be a positive${allowInfinite ? "" : " finite"} number, got ${value}`);
16
+ }
17
+ }
18
+ function resolveGround(ground) {
19
+ if (ground["seed"] !== undefined) {
20
+ throw new Error("world: seed does not belong on ground — the engine injects seeds into generators (seedForPlace).");
21
+ }
22
+ if ("generator" in ground && ground.generator?.params !== undefined && "seed" in ground.generator.params) {
23
+ throw new Error("world: generator.params.seed is not allowed — the engine injects the seed from world id + save/run (seedForPlace).");
24
+ }
25
+ switch (ground.mode) {
26
+ case "flat": {
27
+ assertAxis("flat", "x", ground.size.x, true);
28
+ assertAxis("flat", "z", ground.size.z, true);
29
+ if (ground.size.y !== undefined)
30
+ assertAxis("flat", "y", ground.size.y, true);
31
+ return ground;
32
+ }
33
+ case "round": {
34
+ assertAxis("round", "radius", ground.size.radius, false);
35
+ return ground;
36
+ }
37
+ case "voxel": {
38
+ assertAxis("voxel", "x", ground.size.x, true);
39
+ assertAxis("voxel", "y", ground.size.y, true);
40
+ assertAxis("voxel", "z", ground.size.z, true);
41
+ return ground;
42
+ }
43
+ case "board":
44
+ case "stage": {
45
+ assertAxis("board", "x", ground.size.x, false);
46
+ assertAxis("board", "y", ground.size.y, false);
47
+ return ground.mode === "board" ? ground : { ...ground, mode: "board" };
48
+ }
49
+ }
50
+ }
51
+ /**
52
+ * Declares the place a game is played in: substrate (`ground`) + laws (`physics`, `ground.surface`).
53
+ * The thin default start — `flat` with `Infinity` axes and default physics, `board` for 2D — is a
54
+ * complete world; dressing it (sky, foliage, props, sculpt) is editor-authored scene content.
55
+ * Multiple worlds per game are first-class: declare one `world()` per place, each with its own id,
56
+ * ground, and physics. Games that are not a spatial place (pure UI/rules) omit `world` entirely.
57
+ *
58
+ * @capability world-place declare the place a game happens in — flat/round/voxel/board ground, surface laws, per-place physics
59
+ */
60
+ export function world(config) {
61
+ if (config.id.trim().length === 0) {
62
+ throw new Error("world: id must be non-empty — it names the place for saves, seeds, and world switching");
63
+ }
64
+ assertNoDressing(config);
65
+ return {
66
+ kind: "place",
67
+ id: config.id,
68
+ ground: resolveGround(config.ground),
69
+ ...(config.physics === undefined ? {} : { physics: config.physics }),
70
+ };
71
+ }
72
+ /**
73
+ * The engine-side seed derivation for a place: a stable string from the world `id` plus the
74
+ * save/run seed. Generators and scatter receive this — never a `seed` field in the world
75
+ * definition — so a save replays its world deterministically and a fresh run can vary by
76
+ * `runSeed` alone.
77
+ *
78
+ * @capability world-seed derive a deterministic generator/scatter seed from world id + save/run seed
79
+ */
80
+ export function seedForPlace(worldId, runSeed = "") {
81
+ return runSeed.length === 0 ? worldId : `${worldId}:${runSeed}`;
82
+ }
83
+ /**
84
+ * Resolves the physics laws in effect for the active world: a place world's own `physics` wins
85
+ * field-by-field over the game-level default. Non-place worlds (and games with no world) keep the
86
+ * game-level config unchanged.
87
+ */
88
+ export function resolveWorldPhysics(worldFeature, base) {
89
+ if (worldFeature === undefined || worldFeature.kind !== "place" || worldFeature.physics === undefined)
90
+ return base;
91
+ return base === undefined ? worldFeature.physics : { ...base, ...worldFeature.physics };
92
+ }
93
+ /** Type guard for the place-model world feature. */
94
+ export function isPlaceWorld(worldFeature) {
95
+ return worldFeature?.kind === "place";
96
+ }
@@ -0,0 +1,81 @@
1
+ import { type AssetSpace } from "../scene/assetSpace.js";
2
+ import type { PlacementCommit } from "./placementController.js";
3
+ import type { AddStructureInput, StructureVec3 } from "./placedStructureStore.js";
4
+ /** World-space point shared by structure stores and editor markers. */
5
+ export type PlaceAssetVec3 = {
6
+ x: number;
7
+ y: number;
8
+ z: number;
9
+ };
10
+ /**
11
+ * Shared place-asset verb: one resolved payload for editor `place_asset` and in-game
12
+ * build-mode commits. Convert with {@link toStructureInput} / {@link toEditorMarker}.
13
+ * @capability place-asset resolve a placement commit into a shared asset placement payload
14
+ */
15
+ export interface PlaceAssetResult {
16
+ id: string;
17
+ assetId: string;
18
+ kind: string;
19
+ label: string;
20
+ position: PlaceAssetVec3;
21
+ rotationY: number;
22
+ color: string;
23
+ meta: Readonly<Record<string, unknown>>;
24
+ }
25
+ /** Inputs to {@link resolvePlaceAsset}: asset id, pose, and optional catalog/known fields. */
26
+ export interface ResolvePlaceAssetInput {
27
+ assetId: string;
28
+ position: PlaceAssetVec3 | StructureVec3;
29
+ kind?: string;
30
+ label?: string;
31
+ rotationY?: number;
32
+ /**
33
+ * Placement heading in degrees (engine north = `0`, clockwise). When set it takes precedence over
34
+ * `rotationY`: the resolved `rotationY` runs through `space.rotation` (the asset's rotation policy)
35
+ * and `space.forwardDegrees` (canonical facing), so the catalog owns the correction instead of games.
36
+ */
37
+ headingDegrees?: number;
38
+ /** Asset-space metadata driving the heading resolution when `headingDegrees` is set. */
39
+ space?: AssetSpace;
40
+ id?: string;
41
+ color?: string;
42
+ meta?: Readonly<Record<string, unknown>>;
43
+ url?: string;
44
+ knownKind?: string;
45
+ knownLabel?: string;
46
+ knownUrl?: string;
47
+ }
48
+ /** Optional catalog/label overrides for {@link placeAssetFromCommit}. */
49
+ export interface PlaceAssetFromCommitOptions {
50
+ kind?: string;
51
+ label?: string;
52
+ id?: string;
53
+ color?: string;
54
+ meta?: Readonly<Record<string, unknown>>;
55
+ url?: string;
56
+ knownKind?: string;
57
+ knownLabel?: string;
58
+ knownUrl?: string;
59
+ }
60
+ /**
61
+ * Resolve a place-asset intent into a shared payload (editor + games, one verb).
62
+ * @capability place-asset resolve a placement commit into a shared asset placement payload
63
+ */
64
+ export declare function resolvePlaceAsset(input: ResolvePlaceAssetInput): PlaceAssetResult;
65
+ /**
66
+ * Bridge a {@link PlacementCommit} into the shared place-asset verb.
67
+ * @capability place-asset resolve a placement commit into a shared asset placement payload
68
+ */
69
+ export declare function placeAssetFromCommit(commit: PlacementCommit, assetId: string, options?: PlaceAssetFromCommitOptions): PlaceAssetResult;
70
+ /** Game-state form: feed {@link createPlacedStructureStore}.add. */
71
+ export declare function toStructureInput(result: PlaceAssetResult): AddStructureInput;
72
+ /** Scene-document form: feed editor `addMarker` / `place_asset` path. */
73
+ export declare function toEditorMarker(result: PlaceAssetResult): {
74
+ id: string;
75
+ kind: string;
76
+ position: PlaceAssetVec3;
77
+ rotationY: number;
78
+ label: string;
79
+ color: string;
80
+ meta: Record<string, unknown>;
81
+ };
@@ -0,0 +1,79 @@
1
+ import { applyRotationPolicy, resolveFacingRotationY } from "../scene/assetSpace.js";
2
+ function normalizePosition(position) {
3
+ if (typeof position.x === "number") {
4
+ const p = position;
5
+ return { x: p.x, y: p.y, z: p.z };
6
+ }
7
+ const t = position;
8
+ return { x: t[0], y: t[1], z: t[2] };
9
+ }
10
+ let placementSequence = 0;
11
+ function placementId(assetId, explicit) {
12
+ if (explicit !== undefined && explicit.length > 0)
13
+ return explicit;
14
+ placementSequence += 1;
15
+ return `placed_${assetId}_${Date.now().toString(36)}_${placementSequence.toString(36)}`;
16
+ }
17
+ /**
18
+ * Resolve a place-asset intent into a shared payload (editor + games, one verb).
19
+ * @capability place-asset resolve a placement commit into a shared asset placement payload
20
+ */
21
+ export function resolvePlaceAsset(input) {
22
+ const position = normalizePosition(input.position);
23
+ const assetId = input.assetId;
24
+ const kind = input.kind ?? input.knownKind ?? "prop";
25
+ const label = input.label ?? input.knownLabel ?? assetId;
26
+ const url = input.url ?? input.knownUrl;
27
+ const meta = {
28
+ assetId,
29
+ ...(url === undefined ? {} : { url }),
30
+ ...(input.meta ?? {}),
31
+ };
32
+ const rotationY = input.headingDegrees === undefined
33
+ ? (input.rotationY ?? 0)
34
+ : resolveFacingRotationY(applyRotationPolicy(input.headingDegrees, input.space?.rotation), input.space);
35
+ return {
36
+ id: placementId(assetId, input.id),
37
+ assetId,
38
+ kind,
39
+ label,
40
+ position,
41
+ rotationY,
42
+ color: input.color ?? "#e2e8f0",
43
+ meta,
44
+ };
45
+ }
46
+ /**
47
+ * Bridge a {@link PlacementCommit} into the shared place-asset verb.
48
+ * @capability place-asset resolve a placement commit into a shared asset placement payload
49
+ */
50
+ export function placeAssetFromCommit(commit, assetId, options = {}) {
51
+ return resolvePlaceAsset({
52
+ assetId,
53
+ position: [commit.center[0], commit.y, commit.center[1]],
54
+ rotationY: commit.rotationY,
55
+ ...options,
56
+ });
57
+ }
58
+ /** Game-state form: feed {@link createPlacedStructureStore}.add. */
59
+ export function toStructureInput(result) {
60
+ return {
61
+ id: result.id,
62
+ catalogId: result.assetId,
63
+ position: [result.position.x, result.position.y, result.position.z],
64
+ rotationY: result.rotationY,
65
+ data: { ...result.meta, kind: result.kind, label: result.label, color: result.color },
66
+ };
67
+ }
68
+ /** Scene-document form: feed editor `addMarker` / `place_asset` path. */
69
+ export function toEditorMarker(result) {
70
+ return {
71
+ id: result.id,
72
+ kind: result.kind,
73
+ position: result.position,
74
+ rotationY: result.rotationY,
75
+ label: result.label,
76
+ color: result.color,
77
+ meta: { ...result.meta },
78
+ };
79
+ }
@@ -26,5 +26,9 @@ export type PlacementResult = {
26
26
  obstacle: PlacementObstacle;
27
27
  index: number;
28
28
  };
29
+ /**
30
+ * Footprint validity: bounds + obstacle overlap after optional grid snap.
31
+ * @capability placement-math grid/surface footprint validity for build mode
32
+ */
29
33
  export declare function validatePlacement(request: PlacementRequest, rules?: PlacementRules): PlacementResult;
30
34
  export declare function footprintObstacle(request: PlacementRequest, id?: string): PlacementObstacle;
@@ -1,4 +1,8 @@
1
1
  import { aabbContains, aabbOverlap, footprintAabb, snapToGrid, } from "./geometry.js";
2
+ /**
3
+ * Footprint validity: bounds + obstacle overlap after optional grid snap.
4
+ * @capability placement-math grid/surface footprint validity for build mode
5
+ */
2
6
  export function validatePlacement(request, rules = {}) {
3
7
  const center = rules.snap === undefined ? request.center : snapToGrid(request.center, rules.snap);
4
8
  const aabb = footprintAabb(center, request.footprint, request.quarterTurns ?? 0);