@jgengine/core 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (607) hide show
  1. package/CHANGELOG.md +13 -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/spawnDirector.d.ts +7 -2
  21. package/dist/ai/spawnDirector.js +18 -15
  22. package/dist/ai/spawnPoint.d.ts +3 -1
  23. package/dist/ai/spawnPoint.js +3 -1
  24. package/dist/ai/targetAcquisition.d.ts +84 -0
  25. package/dist/ai/targetAcquisition.js +92 -0
  26. package/dist/anim/easing.d.ts +19 -0
  27. package/dist/anim/easing.js +19 -0
  28. package/dist/anim/oscillator.d.ts +12 -0
  29. package/dist/anim/oscillator.js +25 -0
  30. package/dist/area/areaEffectField.d.ts +127 -0
  31. package/dist/area/areaEffectField.js +175 -0
  32. package/dist/area/stackPolicy.d.ts +47 -0
  33. package/dist/area/stackPolicy.js +99 -0
  34. package/dist/authoring.d.ts +1 -0
  35. package/dist/authoring.js +1 -0
  36. package/dist/board/laneBoard.d.ts +13 -0
  37. package/dist/board/laneBoard.js +13 -0
  38. package/dist/board/timelineBoard.d.ts +10 -0
  39. package/dist/board/timelineBoard.js +10 -0
  40. package/dist/combat/abilityKit.d.ts +18 -0
  41. package/dist/combat/abilityKit.js +24 -9
  42. package/dist/combat/animationState.d.ts +5 -0
  43. package/dist/combat/animationState.js +5 -0
  44. package/dist/combat/breakMeters.d.ts +10 -0
  45. package/dist/combat/breakMeters.js +10 -0
  46. package/dist/combat/castRunner.d.ts +5 -0
  47. package/dist/combat/castRunner.js +5 -0
  48. package/dist/combat/comboPoints.d.ts +5 -0
  49. package/dist/combat/comboPoints.js +5 -0
  50. package/dist/combat/comboString.d.ts +5 -0
  51. package/dist/combat/comboString.js +5 -0
  52. package/dist/combat/damageInterceptors.d.ts +192 -0
  53. package/dist/combat/damageInterceptors.js +251 -0
  54. package/dist/combat/damageMatchup.d.ts +68 -0
  55. package/dist/combat/damageMatchup.js +42 -0
  56. package/dist/combat/damageResolution.d.ts +63 -0
  57. package/dist/combat/damageResolution.js +50 -0
  58. package/dist/combat/death.d.ts +7 -1
  59. package/dist/combat/death.js +5 -0
  60. package/dist/combat/deathReason.d.ts +14 -0
  61. package/dist/combat/deathReason.js +1 -0
  62. package/dist/combat/defensiveWindow.d.ts +5 -0
  63. package/dist/combat/defensiveWindow.js +5 -0
  64. package/dist/combat/dotField.d.ts +5 -1
  65. package/dist/combat/dotField.js +5 -1
  66. package/dist/combat/downed.d.ts +5 -0
  67. package/dist/combat/downed.js +5 -0
  68. package/dist/combat/effects.d.ts +5 -0
  69. package/dist/combat/effects.js +5 -0
  70. package/dist/combat/encounterSequence.d.ts +258 -0
  71. package/dist/combat/encounterSequence.js +426 -0
  72. package/dist/combat/hitReaction.d.ts +57 -1
  73. package/dist/combat/hitReaction.js +45 -5
  74. package/dist/combat/magazine.d.ts +54 -0
  75. package/dist/combat/magazine.js +96 -0
  76. package/dist/combat/projectiles.d.ts +5 -0
  77. package/dist/combat/projectiles.js +32 -14
  78. package/dist/combat/receivedDamage.d.ts +117 -0
  79. package/dist/combat/receivedDamage.js +92 -0
  80. package/dist/combat/regenShield.d.ts +5 -1
  81. package/dist/combat/regenShield.js +5 -1
  82. package/dist/combat/renderCues.d.ts +51 -0
  83. package/dist/combat/renderCues.js +44 -0
  84. package/dist/combat/resourcePool.d.ts +5 -0
  85. package/dist/combat/resourcePool.js +5 -0
  86. package/dist/combat/rewardAllocation.d.ts +121 -0
  87. package/dist/combat/rewardAllocation.js +251 -0
  88. package/dist/combat/shotOrigin.d.ts +18 -1
  89. package/dist/combat/shotOrigin.js +39 -0
  90. package/dist/combat/statusApplication.d.ts +96 -0
  91. package/dist/combat/statusApplication.js +81 -0
  92. package/dist/combat/telegraph.d.ts +11 -2
  93. package/dist/combat/telegraph.js +11 -2
  94. package/dist/combat/thresholdCrossings.d.ts +85 -0
  95. package/dist/combat/thresholdCrossings.js +116 -0
  96. package/dist/combat.d.ts +34 -0
  97. package/dist/combat.js +34 -0
  98. package/dist/commands/commandRegistry.d.ts +11 -0
  99. package/dist/commands/commandRegistry.js +9 -2
  100. package/dist/crafting/crop.d.ts +18 -0
  101. package/dist/crafting/crop.js +18 -0
  102. package/dist/crafting/production.d.ts +5 -0
  103. package/dist/crafting/production.js +5 -0
  104. package/dist/devtools/rewriteTunables.d.ts +17 -0
  105. package/dist/devtools/rewriteTunables.js +276 -0
  106. package/dist/devtools/saveEndpoint.d.ts +46 -0
  107. package/dist/devtools/saveEndpoint.js +48 -0
  108. package/dist/devtools/transformTunables.d.ts +3 -0
  109. package/dist/devtools/transformTunables.js +3 -0
  110. package/dist/devtools/tunableSchema.d.ts +31 -0
  111. package/dist/devtools/tunableSchema.js +31 -0
  112. package/dist/economy/currency.d.ts +12 -1
  113. package/dist/economy/currency.js +12 -1
  114. package/dist/economy/listingBook.d.ts +91 -0
  115. package/dist/economy/listingBook.js +144 -0
  116. package/dist/economy/resourceLedger.d.ts +222 -0
  117. package/dist/economy/resourceLedger.js +353 -0
  118. package/dist/economy/sharedWallet.d.ts +14 -0
  119. package/dist/economy/sharedWallet.js +14 -0
  120. package/dist/economy/techTree.d.ts +12 -0
  121. package/dist/economy/techTree.js +12 -0
  122. package/dist/economy/wallet.d.ts +26 -2
  123. package/dist/economy/wallet.js +35 -6
  124. package/dist/editor/commands.d.ts +190 -7
  125. package/dist/editor/commands.js +727 -55
  126. package/dist/editor/document.d.ts +159 -13
  127. package/dist/editor/document.js +750 -19
  128. package/dist/editor/grid.d.ts +229 -0
  129. package/dist/editor/grid.js +366 -0
  130. package/dist/editor/gridAdapters.d.ts +80 -0
  131. package/dist/editor/gridAdapters.js +134 -0
  132. package/dist/editor/index.d.ts +73 -6
  133. package/dist/editor/index.js +6 -2
  134. package/dist/editor/liveSync.d.ts +127 -0
  135. package/dist/editor/liveSync.js +249 -0
  136. package/dist/editor/runtimeInspector.d.ts +88 -0
  137. package/dist/editor/runtimeInspector.js +239 -0
  138. package/dist/editor/types.d.ts +107 -1
  139. package/dist/faction/reputation.d.ts +5 -0
  140. package/dist/faction/reputation.js +5 -0
  141. package/dist/format/distance.d.ts +17 -0
  142. package/dist/format/distance.js +18 -0
  143. package/dist/format/duration.d.ts +27 -0
  144. package/dist/format/duration.js +45 -0
  145. package/dist/format/speed.d.ts +17 -0
  146. package/dist/format/speed.js +25 -0
  147. package/dist/game/connectedPlayers.d.ts +6 -4
  148. package/dist/game/connectedPlayers.js +2 -2
  149. package/dist/game/cosmetics.d.ts +9 -0
  150. package/dist/game/cosmetics.js +16 -0
  151. package/dist/game/defineGame.d.ts +100 -2
  152. package/dist/game/defineGame.js +39 -2
  153. package/dist/game/defineSystem.d.ts +88 -0
  154. package/dist/game/defineSystem.js +45 -0
  155. package/dist/game/dialogue.d.ts +33 -0
  156. package/dist/game/dialogue.js +21 -0
  157. package/dist/game/events.d.ts +35 -13
  158. package/dist/game/events.js +5 -0
  159. package/dist/game/feed.d.ts +33 -0
  160. package/dist/game/feed.js +35 -2
  161. package/dist/game/gamePhase.d.ts +11 -0
  162. package/dist/game/gamePhase.js +16 -0
  163. package/dist/game/leaderboard.d.ts +5 -0
  164. package/dist/game/leaderboard.js +5 -0
  165. package/dist/game/loadout.d.ts +5 -0
  166. package/dist/game/loadout.js +5 -0
  167. package/dist/game/lootFilter.d.ts +2 -0
  168. package/dist/game/lootFilter.js +2 -0
  169. package/dist/game/lootPipeline.d.ts +164 -0
  170. package/dist/game/lootPipeline.js +216 -0
  171. package/dist/game/lootTable.d.ts +19 -2
  172. package/dist/game/lootTable.js +15 -5
  173. package/dist/game/objectives.d.ts +43 -0
  174. package/dist/game/objectives.js +36 -0
  175. package/dist/game/paramLayers.d.ts +148 -0
  176. package/dist/game/paramLayers.js +185 -0
  177. package/dist/game/ping.d.ts +5 -0
  178. package/dist/game/ping.js +5 -0
  179. package/dist/game/playableGame.d.ts +92 -7
  180. package/dist/game/quest.d.ts +8 -0
  181. package/dist/game/quest.js +29 -0
  182. package/dist/game/race.d.ts +141 -0
  183. package/dist/game/race.js +169 -0
  184. package/dist/game/recordBook.d.ts +3 -1
  185. package/dist/game/recordBook.js +4 -1
  186. package/dist/game/ruleSelection.d.ts +75 -0
  187. package/dist/game/ruleSelection.js +127 -0
  188. package/dist/game/runDraft.d.ts +5 -0
  189. package/dist/game/runDraft.js +5 -0
  190. package/dist/game/saveStore.d.ts +111 -0
  191. package/dist/game/saveStore.js +312 -0
  192. package/dist/game/snapshotHistory.d.ts +67 -0
  193. package/dist/game/snapshotHistory.js +95 -0
  194. package/dist/game/social.d.ts +38 -1
  195. package/dist/game/social.js +71 -0
  196. package/dist/game/spawnPoints.d.ts +5 -0
  197. package/dist/game/spawnPoints.js +5 -0
  198. package/dist/game/systemRuntime.d.ts +50 -0
  199. package/dist/game/systemRuntime.js +157 -0
  200. package/dist/game/systemSchedule.d.ts +72 -0
  201. package/dist/game/systemSchedule.js +242 -0
  202. package/dist/game/toasts.d.ts +43 -0
  203. package/dist/game/toasts.js +44 -0
  204. package/dist/game/trade.d.ts +10 -0
  205. package/dist/game/trade.js +10 -0
  206. package/dist/game/unlocks.d.ts +8 -0
  207. package/dist/game/unlocks.js +16 -0
  208. package/dist/game/vfxInstance.d.ts +138 -0
  209. package/dist/game/vfxInstance.js +96 -0
  210. package/dist/game/worldItem.d.ts +17 -4
  211. package/dist/game/worldItem.js +17 -4
  212. package/dist/gameplay.d.ts +91 -0
  213. package/dist/gameplay.js +91 -0
  214. package/dist/index.d.ts +5 -14
  215. package/dist/index.js +5 -14
  216. package/dist/input/actionBindings.d.ts +23 -6
  217. package/dist/input/actionBindings.js +23 -6
  218. package/dist/input/axisInput.d.ts +7 -2
  219. package/dist/input/axisInput.js +7 -2
  220. package/dist/input/controlGroups.d.ts +67 -0
  221. package/dist/input/controlGroups.js +41 -0
  222. package/dist/input/touchScheme.d.ts +82 -6
  223. package/dist/input/touchScheme.js +123 -10
  224. package/dist/interaction/lockpick.d.ts +61 -0
  225. package/dist/interaction/lockpick.js +168 -0
  226. package/dist/interaction/proximityPrompt.d.ts +2 -0
  227. package/dist/interaction/proximityPrompt.js +2 -0
  228. package/dist/interaction/qte.d.ts +5 -0
  229. package/dist/interaction/qte.js +5 -0
  230. package/dist/interaction/skillCheck.d.ts +5 -0
  231. package/dist/interaction/skillCheck.js +5 -0
  232. package/dist/inventory/inventoryModel.d.ts +12 -0
  233. package/dist/inventory/inventoryModel.js +12 -0
  234. package/dist/inventory/shapedGrid.d.ts +16 -0
  235. package/dist/inventory/shapedGrid.js +16 -0
  236. package/dist/inventory/slotModel.d.ts +10 -0
  237. package/dist/inventory/slotModel.js +10 -0
  238. package/dist/item/durability.d.ts +5 -0
  239. package/dist/item/durability.js +5 -0
  240. package/dist/item/itemIdentity.d.ts +171 -0
  241. package/dist/item/itemIdentity.js +138 -0
  242. package/dist/item/itemInstanceRegistry.d.ts +32 -0
  243. package/dist/item/itemInstanceRegistry.js +34 -0
  244. package/dist/item/itemgen.d.ts +163 -0
  245. package/dist/item/itemgen.js +151 -0
  246. package/dist/item/modularItem.d.ts +5 -0
  247. package/dist/item/modularItem.js +5 -0
  248. package/dist/item/use.d.ts +5 -0
  249. package/dist/item/use.js +5 -0
  250. package/dist/item/useBehavior.d.ts +142 -0
  251. package/dist/item/useBehavior.js +105 -0
  252. package/dist/item/weapon.d.ts +5 -0
  253. package/dist/item/weapon.js +5 -0
  254. package/dist/math/scalar.d.ts +25 -0
  255. package/dist/math/scalar.js +47 -0
  256. package/dist/meta/changelog.d.ts +4 -1
  257. package/dist/meta/changelog.js +16 -2
  258. package/dist/movement/avoidance.d.ts +45 -0
  259. package/dist/movement/avoidance.js +123 -0
  260. package/dist/movement/cameraRig.d.ts +8 -0
  261. package/dist/movement/cameraRig.js +8 -0
  262. package/dist/movement/dash.d.ts +11 -0
  263. package/dist/movement/dash.js +11 -0
  264. package/dist/movement/formation.d.ts +135 -0
  265. package/dist/movement/formation.js +194 -0
  266. package/dist/movement/glideModel.d.ts +5 -0
  267. package/dist/movement/glideModel.js +5 -0
  268. package/dist/movement/grappleSwing.d.ts +5 -0
  269. package/dist/movement/grappleSwing.js +5 -0
  270. package/dist/movement/leaderTrail.d.ts +5 -0
  271. package/dist/movement/leaderTrail.js +5 -0
  272. package/dist/movement/movementModel.d.ts +35 -8
  273. package/dist/movement/movementModel.js +42 -14
  274. package/dist/movement/playerMovement.js +65 -10
  275. package/dist/movement/poseState.d.ts +13 -0
  276. package/dist/movement/poseState.js +16 -0
  277. package/dist/movement/steering.d.ts +8 -0
  278. package/dist/movement/steering.js +18 -0
  279. package/dist/multiplayer/combatSnapshot.d.ts +3 -0
  280. package/dist/multiplayer/combatSnapshot.js +3 -0
  281. package/dist/multiplayer/lagCompensation.d.ts +5 -0
  282. package/dist/multiplayer/lagCompensation.js +5 -0
  283. package/dist/multiplayer/presenceModel.d.ts +9 -1
  284. package/dist/multiplayer/presenceModel.js +9 -1
  285. package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
  286. package/dist/multiplayer/simultaneousCommit.js +3 -0
  287. package/dist/multiplayer.d.ts +11 -0
  288. package/dist/multiplayer.js +11 -0
  289. package/dist/nav/pathFollow.d.ts +57 -0
  290. package/dist/nav/pathFollow.js +109 -0
  291. package/dist/orders/orderKinds.d.ts +156 -0
  292. package/dist/orders/orderKinds.js +197 -0
  293. package/dist/orders/orderQueue.d.ts +208 -0
  294. package/dist/orders/orderQueue.js +211 -0
  295. package/dist/physics/drivableVehicle.d.ts +29 -0
  296. package/dist/physics/drivableVehicle.js +16 -0
  297. package/dist/physics/kinematicVehicle.d.ts +21 -1
  298. package/dist/physics/kinematicVehicle.js +23 -8
  299. package/dist/physics/physicsWorld.d.ts +24 -12
  300. package/dist/physics/physicsWorld.js +11 -5
  301. package/dist/physics/radialImpulse.d.ts +25 -0
  302. package/dist/physics/radialImpulse.js +27 -0
  303. package/dist/procedural.d.ts +3 -0
  304. package/dist/procedural.js +3 -0
  305. package/dist/progression/statGraph.d.ts +116 -0
  306. package/dist/progression/statGraph.js +318 -0
  307. package/dist/puzzle/cellGrid.d.ts +9 -0
  308. package/dist/puzzle/cellGrid.js +9 -0
  309. package/dist/puzzle/fallingPiece.d.ts +9 -0
  310. package/dist/puzzle/fallingPiece.js +9 -0
  311. package/dist/puzzle/nonogram.d.ts +39 -0
  312. package/dist/puzzle/nonogram.js +136 -0
  313. package/dist/random/nameGen.d.ts +5 -0
  314. package/dist/random/nameGen.js +5 -0
  315. package/dist/random/pick.d.ts +8 -0
  316. package/dist/random/pick.js +31 -0
  317. package/dist/random/rng.d.ts +22 -0
  318. package/dist/random/rng.js +28 -8
  319. package/dist/random/seedLink.d.ts +4 -0
  320. package/dist/random/seedLink.js +4 -0
  321. package/dist/relation/keyedValues.d.ts +54 -0
  322. package/dist/relation/keyedValues.js +115 -0
  323. package/dist/relation/thresholds.d.ts +62 -0
  324. package/dist/relation/thresholds.js +62 -0
  325. package/dist/render/color.d.ts +12 -0
  326. package/dist/render/color.js +26 -0
  327. package/dist/render/lookPreset.d.ts +41 -0
  328. package/dist/render/lookPreset.js +29 -0
  329. package/dist/render/postProcessing.d.ts +20 -0
  330. package/dist/render/postProcessing.js +21 -1
  331. package/dist/rules/predicate.d.ts +53 -0
  332. package/dist/rules/predicate.js +64 -0
  333. package/dist/rules/ruleEffects.d.ts +38 -0
  334. package/dist/rules/ruleEffects.js +37 -0
  335. package/dist/rules/triggeredRules.d.ts +160 -0
  336. package/dist/rules/triggeredRules.js +241 -0
  337. package/dist/runtime/adapter.d.ts +42 -3
  338. package/dist/runtime/adapter.js +44 -1
  339. package/dist/runtime/cameraDirector.d.ts +1 -0
  340. package/dist/runtime/cameraDirector.js +1 -0
  341. package/dist/runtime/commandRunner.d.ts +1 -0
  342. package/dist/runtime/commandRunner.js +1 -0
  343. package/dist/runtime/context/combatFx.d.ts +23 -0
  344. package/dist/runtime/context/combatFx.js +161 -0
  345. package/dist/runtime/context/registries.d.ts +13 -0
  346. package/dist/runtime/context/registries.js +84 -0
  347. package/dist/runtime/context/worldItems.d.ts +21 -0
  348. package/dist/runtime/context/worldItems.js +37 -0
  349. package/dist/runtime/descriptors/baseline.d.ts +48 -0
  350. package/dist/runtime/descriptors/baseline.js +134 -0
  351. package/dist/runtime/descriptors/features.d.ts +74 -0
  352. package/dist/runtime/descriptors/features.js +281 -0
  353. package/dist/runtime/gameContext.d.ts +114 -13
  354. package/dist/runtime/gameContext.js +303 -395
  355. package/dist/runtime/gameRuntime.d.ts +1 -0
  356. package/dist/runtime/gameRuntime.js +1 -0
  357. package/dist/runtime/headlessRunner.d.ts +60 -0
  358. package/dist/runtime/headlessRunner.js +44 -0
  359. package/dist/runtime/hostPersistence.d.ts +12 -0
  360. package/dist/runtime/hostPersistence.js +12 -0
  361. package/dist/runtime/hostedGameRunner.d.ts +8 -3
  362. package/dist/runtime/hostedGameRunner.js +26 -3
  363. package/dist/runtime/hostedWorldSession.d.ts +12 -4
  364. package/dist/runtime/hostedWorldSession.js +11 -4
  365. package/dist/runtime/inputSnapshot.d.ts +8 -3
  366. package/dist/runtime/inputSnapshot.js +6 -2
  367. package/dist/runtime/motionIntents.d.ts +11 -2
  368. package/dist/runtime/motionIntents.js +16 -2
  369. package/dist/runtime/perContext.d.ts +15 -0
  370. package/dist/runtime/perContext.js +21 -0
  371. package/dist/runtime/runtimeSave.d.ts +79 -0
  372. package/dist/runtime/runtimeSave.js +105 -0
  373. package/dist/runtime/save.d.ts +4 -0
  374. package/dist/runtime/save.js +4 -0
  375. package/dist/runtime/snapshot.d.ts +7 -0
  376. package/dist/runtime/snapshot.js +7 -0
  377. package/dist/runtime/visibility.d.ts +2 -1
  378. package/dist/runtime/visibility.js +2 -1
  379. package/dist/runtime/worldChannel.d.ts +7 -3
  380. package/dist/runtime/worldChannel.js +51 -6
  381. package/dist/runtime/worldMirror.d.ts +14 -2
  382. package/dist/runtime/worldMirror.js +15 -2
  383. package/dist/runtime/worldProjection.d.ts +47 -0
  384. package/dist/runtime/worldProjection.js +52 -0
  385. package/dist/runtime/worldReplication.d.ts +30 -7
  386. package/dist/runtime/worldReplication.js +41 -9
  387. package/dist/runtime/worldSnapshot.d.ts +30 -3
  388. package/dist/runtime/worldSnapshot.js +20 -5
  389. package/dist/scene/assetCatalog.d.ts +21 -0
  390. package/dist/scene/assetCatalog.js +4 -0
  391. package/dist/scene/assetDiagnostics.d.ts +69 -0
  392. package/dist/scene/assetDiagnostics.js +110 -0
  393. package/dist/scene/assetGenerator.d.ts +65 -0
  394. package/dist/scene/assetGenerator.js +64 -0
  395. package/dist/scene/assetSpace.d.ts +137 -0
  396. package/dist/scene/assetSpace.js +259 -0
  397. package/dist/scene/authoredTriggers.d.ts +169 -0
  398. package/dist/scene/authoredTriggers.js +340 -0
  399. package/dist/scene/behaviorRuntime.d.ts +75 -0
  400. package/dist/scene/behaviorRuntime.js +217 -0
  401. package/dist/scene/behaviors.d.ts +14 -2
  402. package/dist/scene/behaviors.js +7 -2
  403. package/dist/scene/bodyBind.d.ts +60 -0
  404. package/dist/scene/bodyBind.js +51 -0
  405. package/dist/scene/builtinSceneKinds.d.ts +5 -0
  406. package/dist/scene/builtinSceneKinds.js +62 -0
  407. package/dist/scene/colliders.d.ts +13 -1
  408. package/dist/scene/colliders.js +37 -1
  409. package/dist/scene/entityStats.d.ts +11 -2
  410. package/dist/scene/entityStats.js +11 -2
  411. package/dist/scene/entityStore.d.ts +12 -1
  412. package/dist/scene/entityStore.js +15 -0
  413. package/dist/scene/facing.d.ts +18 -0
  414. package/dist/scene/facing.js +26 -0
  415. package/dist/scene/modelSockets.d.ts +33 -0
  416. package/dist/scene/modelSockets.js +29 -0
  417. package/dist/scene/objectQuery.d.ts +2 -0
  418. package/dist/scene/objectQuery.js +2 -0
  419. package/dist/scene/objectStore.d.ts +4 -0
  420. package/dist/scene/objectStore.js +6 -0
  421. package/dist/scene/possession.d.ts +8 -0
  422. package/dist/scene/possession.js +14 -0
  423. package/dist/scene/roster.d.ts +3 -0
  424. package/dist/scene/roster.js +12 -0
  425. package/dist/scene/sceneKinds.d.ts +240 -0
  426. package/dist/scene/sceneKinds.js +214 -0
  427. package/dist/scene/sceneOwnership.d.ts +169 -0
  428. package/dist/scene/sceneOwnership.js +179 -0
  429. package/dist/scene/selectionBookmarks.d.ts +93 -0
  430. package/dist/scene/selectionBookmarks.js +122 -0
  431. package/dist/scene/vehicleSeat.d.ts +68 -0
  432. package/dist/scene/vehicleSeat.js +59 -0
  433. package/dist/sensor/concealment.d.ts +3 -0
  434. package/dist/sensor/concealment.js +3 -0
  435. package/dist/sensor/freezeMonitor.d.ts +1 -0
  436. package/dist/sensor/freezeMonitor.js +1 -0
  437. package/dist/sensor/frustumSensor.d.ts +7 -3
  438. package/dist/sensor/frustumSensor.js +7 -3
  439. package/dist/sensor/hiddenStateProbe.d.ts +5 -2
  440. package/dist/sensor/hiddenStateProbe.js +5 -2
  441. package/dist/sensor/recordingBuffer.d.ts +2 -1
  442. package/dist/sensor/recordingBuffer.js +2 -1
  443. package/dist/sensor/replayLoop.d.ts +6 -2
  444. package/dist/sensor/replayLoop.js +6 -2
  445. package/dist/sensor/revealQuery.d.ts +2 -1
  446. package/dist/sensor/revealQuery.js +2 -1
  447. package/dist/sensor/visionCone.d.ts +10 -3
  448. package/dist/sensor/visionCone.js +10 -3
  449. package/dist/session/contestedChannel.d.ts +1 -0
  450. package/dist/session/contestedChannel.js +1 -0
  451. package/dist/session/extraction.d.ts +1 -0
  452. package/dist/session/extraction.js +1 -0
  453. package/dist/session/roles.d.ts +6 -0
  454. package/dist/session/roles.js +6 -0
  455. package/dist/session/roundState.d.ts +8 -0
  456. package/dist/session/roundState.js +2 -0
  457. package/dist/settings/settingsModel.d.ts +1 -0
  458. package/dist/settings/settingsModel.js +1 -0
  459. package/dist/stats/accumulatorMeter.d.ts +6 -0
  460. package/dist/stats/accumulatorMeter.js +6 -0
  461. package/dist/stats/eventMeter.d.ts +5 -0
  462. package/dist/stats/eventMeter.js +5 -0
  463. package/dist/stats/rollCheck.d.ts +5 -0
  464. package/dist/stats/rollCheck.js +5 -0
  465. package/dist/stats/statModifiers.d.ts +5 -0
  466. package/dist/stats/statModifiers.js +5 -0
  467. package/dist/store/defineKeyedStore.d.ts +38 -0
  468. package/dist/store/defineKeyedStore.js +42 -0
  469. package/dist/store/defineStore.d.ts +33 -0
  470. package/dist/store/defineStore.js +35 -0
  471. package/dist/store/observableKeyedStore.d.ts +5 -0
  472. package/dist/store/observableKeyedStore.js +34 -2
  473. package/dist/survival/decayMeter.d.ts +55 -0
  474. package/dist/survival/decayMeter.js +130 -55
  475. package/dist/survival/moodle.d.ts +2 -0
  476. package/dist/survival/regionHealth.d.ts +6 -0
  477. package/dist/survival/regionHealth.js +5 -0
  478. package/dist/tactics/fallingGrid.d.ts +4 -2
  479. package/dist/tactics/fallingGrid.js +4 -2
  480. package/dist/tactics/predictiveQuery.d.ts +3 -0
  481. package/dist/tactics/predictiveQuery.js +3 -0
  482. package/dist/tactics/snapshot.d.ts +2 -0
  483. package/dist/tactics/snapshot.js +2 -0
  484. package/dist/tactics/surface.d.ts +1 -0
  485. package/dist/tactics/surface.js +1 -0
  486. package/dist/tactics/tacticalGrid.d.ts +1 -0
  487. package/dist/tactics/tacticalGrid.js +1 -0
  488. package/dist/time/beatClock.d.ts +14 -4
  489. package/dist/time/beatClock.js +14 -4
  490. package/dist/time/calendarClock.d.ts +3 -0
  491. package/dist/time/calendarClock.js +3 -0
  492. package/dist/time/idleProgress.d.ts +4 -0
  493. package/dist/time/idleProgress.js +4 -0
  494. package/dist/time/simClock.d.ts +2 -0
  495. package/dist/time/simClock.js +20 -5
  496. package/dist/ui/actionModel.d.ts +110 -0
  497. package/dist/ui/actionModel.js +159 -0
  498. package/dist/ui/gameLayout.d.ts +30 -11
  499. package/dist/ui/gameLayout.js +30 -11
  500. package/dist/ui/hudDocument.d.ts +114 -0
  501. package/dist/ui/hudDocument.js +220 -0
  502. package/dist/ui/hudLayout.d.ts +33 -1
  503. package/dist/ui/hudLayout.js +204 -17
  504. package/dist/ui/selectionModel.d.ts +92 -0
  505. package/dist/ui/selectionModel.js +88 -0
  506. package/dist/ui/tooltipModel.d.ts +63 -0
  507. package/dist/ui/tooltipModel.js +82 -0
  508. package/dist/ui.d.ts +15 -0
  509. package/dist/ui.js +15 -0
  510. package/dist/visibility/bounds.d.ts +8 -1
  511. package/dist/visibility/bounds.js +8 -1
  512. package/dist/visibility/frustum.d.ts +12 -3
  513. package/dist/visibility/frustum.js +12 -3
  514. package/dist/work/jobQueue.d.ts +201 -0
  515. package/dist/work/jobQueue.js +253 -0
  516. package/dist/work/unitTraining.d.ts +58 -0
  517. package/dist/work/unitTraining.js +52 -0
  518. package/dist/world/authoredObjects.d.ts +58 -0
  519. package/dist/world/authoredObjects.js +69 -0
  520. package/dist/world/buildingGenerator.d.ts +18 -0
  521. package/dist/world/buildingGenerator.js +62 -0
  522. package/dist/world/buildings.d.ts +5 -0
  523. package/dist/world/buildings.js +5 -0
  524. package/dist/world/catenary.d.ts +22 -0
  525. package/dist/world/catenary.js +69 -0
  526. package/dist/world/features.d.ts +115 -7
  527. package/dist/world/features.js +56 -5
  528. package/dist/world/footprintGrid.d.ts +59 -0
  529. package/dist/world/footprintGrid.js +141 -0
  530. package/dist/world/geometry.d.ts +64 -0
  531. package/dist/world/geometry.js +94 -0
  532. package/dist/world/grassKind.d.ts +51 -0
  533. package/dist/world/grassKind.js +101 -0
  534. package/dist/world/pathInstances.d.ts +27 -0
  535. package/dist/world/pathInstances.js +27 -0
  536. package/dist/world/pathTerrain.d.ts +80 -0
  537. package/dist/world/pathTerrain.js +142 -0
  538. package/dist/world/placeAsset.d.ts +81 -0
  539. package/dist/world/placeAsset.js +77 -0
  540. package/dist/world/placement.d.ts +4 -0
  541. package/dist/world/placement.js +4 -0
  542. package/dist/world/placementController.d.ts +6 -0
  543. package/dist/world/placementController.js +6 -0
  544. package/dist/world/polyline.d.ts +34 -0
  545. package/dist/world/polyline.js +81 -0
  546. package/dist/world/roads.d.ts +8 -0
  547. package/dist/world/roads.js +38 -0
  548. package/dist/world/scatterRegion.d.ts +164 -0
  549. package/dist/world/scatterRegion.js +409 -0
  550. package/dist/world/sceneShapes.d.ts +43 -0
  551. package/dist/world/sceneShapes.js +1 -0
  552. package/dist/world/segment.d.ts +27 -0
  553. package/dist/world/segment.js +43 -0
  554. package/dist/world/soilKind.d.ts +48 -0
  555. package/dist/world/soilKind.js +92 -0
  556. package/dist/world/spatialSample.d.ts +241 -0
  557. package/dist/world/spatialSample.js +465 -0
  558. package/dist/world/terraform.d.ts +213 -1
  559. package/dist/world/terraform.js +655 -20
  560. package/dist/world/terrain.d.ts +119 -20
  561. package/dist/world/terrain.js +247 -41
  562. package/dist/world/terrainGuides.d.ts +182 -0
  563. package/dist/world/terrainGuides.js +343 -0
  564. package/dist/world/vec2.d.ts +81 -0
  565. package/dist/world/vec2.js +128 -0
  566. package/dist/world/vec3.d.ts +49 -0
  567. package/dist/world/vec3.js +76 -0
  568. package/dist/world/vegetation.d.ts +71 -0
  569. package/dist/world/vegetation.js +151 -0
  570. package/dist/world/visibilityField.d.ts +154 -0
  571. package/dist/world/visibilityField.js +271 -0
  572. package/dist/world/volumetricClouds.d.ts +52 -0
  573. package/dist/world/volumetricClouds.js +43 -0
  574. package/dist/world/walls.d.ts +9 -0
  575. package/dist/world/walls.js +9 -0
  576. package/dist/world/waterKind.d.ts +55 -0
  577. package/dist/world/waterKind.js +99 -0
  578. package/dist/world.d.ts +132 -0
  579. package/dist/world.js +132 -0
  580. package/package.json +32 -8
  581. package/skills/jgengine/SKILL.md +51 -0
  582. package/skills/jgengine/api.md +434 -0
  583. package/skills/jgengine/capabilities.md +29 -0
  584. package/skills/jgengine/reference-cartridge.md +72 -0
  585. package/skills/jgengine-combat/SKILL.md +34 -0
  586. package/skills/jgengine-combat/api.md +549 -0
  587. package/skills/jgengine-combat/capabilities.md +169 -0
  588. package/skills/jgengine-combat/reference.md +98 -0
  589. package/skills/jgengine-gameplay/SKILL.md +39 -0
  590. package/skills/jgengine-gameplay/api.md +1794 -0
  591. package/skills/jgengine-gameplay/capabilities.md +378 -0
  592. package/skills/jgengine-gameplay/reference-systems.md +60 -0
  593. package/skills/jgengine-world/SKILL.md +38 -0
  594. package/skills/jgengine-world/api.md +2652 -0
  595. package/skills/jgengine-world/capabilities.md +370 -0
  596. package/skills/jgengine-world/reference.md +222 -0
  597. package/dist/cartridge/runtime.d.ts +0 -15
  598. package/dist/cartridge/runtime.js +0 -556
  599. package/dist/cartridge/spec.d.ts +0 -188
  600. package/dist/cartridge/spec.js +0 -19
  601. package/dist/cartridge/validate.d.ts +0 -2
  602. package/dist/cartridge/validate.js +0 -78
  603. package/dist/store/engineStore.d.ts +0 -22
  604. package/dist/store/engineStore.js +0 -50
  605. package/dist/store/features.d.ts +0 -10
  606. package/dist/store/features.js +0 -23
  607. package/llms.txt +0 -5389
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Authored behavior triggers on editor volumes and markers — a small `on`/`action` meta vocabulary
3
+ * so "when player enters this volume, spawn wave 2" is scene data, not game code. Games declare
4
+ * actions (typed via ParamSchema); the editor inspector renders their fields; a pure runtime
5
+ * watches membership and dispatches to handlers.
6
+ */
7
+ import { parseParams } from "./sceneKinds.js";
8
+ /** Reserved meta keys for the trigger vocabulary — action params use every other schema field. @internal */
9
+ export const TRIGGER_ON_KEY = "on";
10
+ /** @internal */
11
+ export const TRIGGER_ACTION_KEY = "action";
12
+ /** @internal */
13
+ export const TRIGGER_RADIUS_KEY = "triggerRadius";
14
+ /** @internal */
15
+ export const TRIGGER_LIST_KEY = "triggers";
16
+ const TRIGGER_EVENTS = ["enter", "exit", "interact"];
17
+ /** Default proximity radius (m) for marker enter/exit/interact when neither triggerRadius nor radius is set. @internal */
18
+ export const DEFAULT_TRIGGER_RADIUS = 2.5;
19
+ const actionRegistry = new Map();
20
+ /**
21
+ * Declare a game action the editor can assign to volume/marker triggers. Idempotent per `id`
22
+ * (last registration wins). Call at module load next to catalogs.
23
+ *
24
+ * @capability authored-triggers schema'd on/action vocabulary on volumes and markers with runtime dispatch
25
+ */
26
+ export function registerTriggerAction(definition) {
27
+ actionRegistry.set(definition.id, definition);
28
+ }
29
+ /** Registered definition for an action id, or undefined when the game never declared it. */
30
+ export function getTriggerAction(id) {
31
+ return actionRegistry.get(id);
32
+ }
33
+ /** Every registered action, optionally filtered by target collection. */
34
+ export function listTriggerActions(target) {
35
+ const all = [...actionRegistry.values()];
36
+ if (target === undefined)
37
+ return all;
38
+ return all.filter((definition) => definition.targets === undefined || definition.targets.includes(target));
39
+ }
40
+ /** Clears the action registry — tests only. @internal */
41
+ export function clearTriggerActions() {
42
+ actionRegistry.clear();
43
+ }
44
+ function isTriggerEvent(value) {
45
+ return typeof value === "string" && TRIGGER_EVENTS.includes(value);
46
+ }
47
+ function metaNumber(meta, key) {
48
+ const value = meta?.[key];
49
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
50
+ }
51
+ /** Resolve the proximity radius for a marker trigger from meta. @internal */
52
+ export function triggerRadiusOf(meta, fallback = DEFAULT_TRIGGER_RADIUS) {
53
+ const explicit = metaNumber(meta, TRIGGER_RADIUS_KEY) ?? metaNumber(meta, "radius");
54
+ if (explicit === undefined)
55
+ return fallback;
56
+ return Math.max(0, explicit);
57
+ }
58
+ function specsFromMeta(meta) {
59
+ if (meta === undefined)
60
+ return [];
61
+ const list = meta[TRIGGER_LIST_KEY];
62
+ if (Array.isArray(list)) {
63
+ if (list.length === 0) {
64
+ // Empty multi-list is the inspector's "cleared" sentinel — fall through to flat on/action.
65
+ }
66
+ else {
67
+ const out = [];
68
+ for (const entry of list) {
69
+ if (typeof entry !== "object" || entry === null)
70
+ continue;
71
+ const row = entry;
72
+ if (!isTriggerEvent(row[TRIGGER_ON_KEY]))
73
+ continue;
74
+ const action = row[TRIGGER_ACTION_KEY];
75
+ if (typeof action !== "string" || action.length === 0)
76
+ continue;
77
+ out.push({ on: row[TRIGGER_ON_KEY], action, paramsMeta: row });
78
+ }
79
+ return out;
80
+ }
81
+ }
82
+ if (!isTriggerEvent(meta[TRIGGER_ON_KEY]))
83
+ return [];
84
+ const action = meta[TRIGGER_ACTION_KEY];
85
+ if (typeof action !== "string" || action.length === 0)
86
+ return [];
87
+ return [{ on: meta[TRIGGER_ON_KEY], action, paramsMeta: meta }];
88
+ }
89
+ function resolveParams(actionId, paramsMeta) {
90
+ const definition = actionRegistry.get(actionId);
91
+ if (definition === undefined)
92
+ return {};
93
+ return parseParams(definition.schema, paramsMeta);
94
+ }
95
+ /**
96
+ * Read every valid `on`/`action` binding off a raw meta bag. Unknown events/actions are dropped;
97
+ * params are schema-parsed when the action is registered, else empty.
98
+ * @internal
99
+ */
100
+ export function readTriggerSpecs(meta) {
101
+ return specsFromMeta(meta).map((spec) => ({
102
+ on: spec.on,
103
+ action: spec.action,
104
+ params: resolveParams(spec.action, spec.paramsMeta),
105
+ }));
106
+ }
107
+ /**
108
+ * Collect every authored trigger on a document's markers and volumes. Pure — no runtime state.
109
+ * Action params use the live {@link registerTriggerAction} registry when present.
110
+ *
111
+ * @capability authored-triggers schema'd on/action vocabulary on volumes and markers with runtime dispatch
112
+ */
113
+ export function collectAuthoredTriggers(document) {
114
+ const out = [];
115
+ for (const marker of document.markers) {
116
+ const radius = triggerRadiusOf(marker.meta);
117
+ for (const spec of readTriggerSpecs(marker.meta)) {
118
+ out.push({
119
+ sourceId: marker.id,
120
+ sourceKind: "marker",
121
+ objectKind: marker.kind,
122
+ on: spec.on,
123
+ action: spec.action,
124
+ params: spec.params,
125
+ radius,
126
+ });
127
+ }
128
+ }
129
+ for (const volume of document.volumes) {
130
+ for (const spec of readTriggerSpecs(volume.meta)) {
131
+ out.push({
132
+ sourceId: volume.id,
133
+ sourceKind: "volume",
134
+ objectKind: volume.kind,
135
+ on: spec.on,
136
+ action: spec.action,
137
+ params: spec.params,
138
+ radius: 0,
139
+ });
140
+ }
141
+ }
142
+ return out;
143
+ }
144
+ /**
145
+ * True when `point` is inside an editor volume (sphere / cylinder / box). Cylinder height defaults
146
+ * to diameter when omitted; sphere ignores y for the common ground-plane case only when the volume
147
+ * radius covers the full vertical span — here y is tested for sphere and box too.
148
+ */
149
+ export function pointInVolume(volume, point) {
150
+ const dx = point.x - volume.center.x;
151
+ const dy = point.y - volume.center.y;
152
+ const dz = point.z - volume.center.z;
153
+ if (volume.shape === "box") {
154
+ const hx = volume.halfExtents?.x ?? 5;
155
+ const hy = volume.halfExtents?.y ?? 5;
156
+ const hz = volume.halfExtents?.z ?? 5;
157
+ return Math.abs(dx) <= hx && Math.abs(dy) <= hy && Math.abs(dz) <= hz;
158
+ }
159
+ const radius = volume.radius ?? 5;
160
+ if (volume.shape === "cylinder") {
161
+ const height = volume.height ?? radius * 2;
162
+ if (Math.hypot(dx, dz) > radius)
163
+ return false;
164
+ return Math.abs(dy) <= height / 2;
165
+ }
166
+ return Math.hypot(dx, dy, dz) <= radius;
167
+ }
168
+ /** True when `point` is within `radius` of a marker's position (sphere for enter/exit/interact). @internal */
169
+ export function pointNearMarker(marker, point, radius) {
170
+ const dx = point.x - marker.position.x;
171
+ const dy = point.y - marker.position.y;
172
+ const dz = point.z - marker.position.z;
173
+ return Math.hypot(dx, dy, dz) <= radius;
174
+ }
175
+ function membershipKey(sourceId, actorId) {
176
+ return `${sourceId}\0${actorId}`;
177
+ }
178
+ function actorPoint(actor) {
179
+ const p = actor.position;
180
+ if (Array.isArray(p))
181
+ return { x: p[0], y: p[1], z: p[2] };
182
+ return p;
183
+ }
184
+ function insideSource(document, trigger, point) {
185
+ if (trigger.sourceKind === "volume") {
186
+ const volume = document.volumes.find((entry) => entry.id === trigger.sourceId);
187
+ return volume !== undefined && pointInVolume(volume, point);
188
+ }
189
+ const marker = document.markers.find((entry) => entry.id === trigger.sourceId);
190
+ return marker !== undefined && pointNearMarker(marker, point, trigger.radius);
191
+ }
192
+ /**
193
+ * Build a runtime that watches a document's authored triggers against moving actors and dispatches
194
+ * to per-action handlers (and optional catch-all). Pure membership math; the game supplies actors
195
+ * each tick from its own player/entity poses.
196
+ *
197
+ * @capability authored-triggers schema'd on/action vocabulary on volumes and markers with runtime dispatch
198
+ */
199
+ export function createAuthoredTriggerRuntime(options) {
200
+ const document = options.document;
201
+ const triggers = options.triggers ?? collectAuthoredTriggers(document);
202
+ let members = new Set();
203
+ const sourceIds = new Map();
204
+ for (const trigger of triggers) {
205
+ const list = sourceIds.get(trigger.sourceId) ?? [];
206
+ list.push(trigger);
207
+ sourceIds.set(trigger.sourceId, list);
208
+ }
209
+ function emit(events) {
210
+ for (const event of events) {
211
+ options.handlers?.[event.action]?.(event);
212
+ options.onDispatch?.(event);
213
+ }
214
+ }
215
+ return {
216
+ triggers: () => triggers,
217
+ reset() {
218
+ members = new Set();
219
+ },
220
+ step(input) {
221
+ const next = new Set();
222
+ const insideNow = new Map();
223
+ for (const actor of input.actors) {
224
+ const point = actorPoint(actor);
225
+ for (const [sourceId, sourceTriggers] of sourceIds) {
226
+ const probe = sourceTriggers[0];
227
+ if (!insideSource(document, probe, point))
228
+ continue;
229
+ const key = membershipKey(sourceId, actor.id);
230
+ next.add(key);
231
+ let set = insideNow.get(sourceId);
232
+ if (set === undefined) {
233
+ set = new Set();
234
+ insideNow.set(sourceId, set);
235
+ }
236
+ set.add(actor.id);
237
+ }
238
+ }
239
+ const events = [];
240
+ for (const [sourceId, actorsInside] of insideNow) {
241
+ const sourceTriggers = sourceIds.get(sourceId) ?? [];
242
+ for (const actorId of actorsInside) {
243
+ const key = membershipKey(sourceId, actorId);
244
+ const wasInside = members.has(key);
245
+ if (!wasInside) {
246
+ for (const trigger of sourceTriggers) {
247
+ if (trigger.on !== "enter")
248
+ continue;
249
+ events.push({
250
+ on: "enter",
251
+ action: trigger.action,
252
+ sourceId: trigger.sourceId,
253
+ sourceKind: trigger.sourceKind,
254
+ objectKind: trigger.objectKind,
255
+ actorId,
256
+ params: trigger.params,
257
+ });
258
+ }
259
+ }
260
+ }
261
+ }
262
+ for (const key of members) {
263
+ if (next.has(key))
264
+ continue;
265
+ const sep = key.indexOf("\0");
266
+ const sourceId = key.slice(0, sep);
267
+ const actorId = key.slice(sep + 1);
268
+ for (const trigger of sourceIds.get(sourceId) ?? []) {
269
+ if (trigger.on !== "exit")
270
+ continue;
271
+ events.push({
272
+ on: "exit",
273
+ action: trigger.action,
274
+ sourceId: trigger.sourceId,
275
+ sourceKind: trigger.sourceKind,
276
+ objectKind: trigger.objectKind,
277
+ actorId,
278
+ params: trigger.params,
279
+ });
280
+ }
281
+ }
282
+ const interactActors = new Set(input.interact ?? []);
283
+ if (interactActors.size > 0) {
284
+ for (const actor of input.actors) {
285
+ if (!interactActors.has(actor.id))
286
+ continue;
287
+ const point = actorPoint(actor);
288
+ for (const sourceTriggers of sourceIds.values()) {
289
+ const probe = sourceTriggers[0];
290
+ if (!insideSource(document, probe, point))
291
+ continue;
292
+ for (const trigger of sourceTriggers) {
293
+ if (trigger.on !== "interact")
294
+ continue;
295
+ events.push({
296
+ on: "interact",
297
+ action: trigger.action,
298
+ sourceId: trigger.sourceId,
299
+ sourceKind: trigger.sourceKind,
300
+ objectKind: trigger.objectKind,
301
+ actorId: actor.id,
302
+ params: trigger.params,
303
+ });
304
+ }
305
+ }
306
+ }
307
+ }
308
+ members = next;
309
+ emit(events);
310
+ return events;
311
+ },
312
+ };
313
+ }
314
+ /**
315
+ * Build a meta patch that sets a single flat trigger (`on` + `action` + optional param fields) and
316
+ * clears a multi-trigger list if present. Used by the editor inspector.
317
+ * @internal
318
+ */
319
+ export function triggerMetaPatch(on, action, params = {}) {
320
+ if (on === "" || action.length === 0) {
321
+ return { [TRIGGER_ON_KEY]: undefined, [TRIGGER_ACTION_KEY]: undefined, [TRIGGER_LIST_KEY]: undefined };
322
+ }
323
+ return {
324
+ [TRIGGER_ON_KEY]: on,
325
+ [TRIGGER_ACTION_KEY]: action,
326
+ [TRIGGER_LIST_KEY]: undefined,
327
+ ...params,
328
+ };
329
+ }
330
+ /** Read the single flat trigger (`on`/`action`) from meta for the inspector, ignoring non-empty multi-lists. @internal */
331
+ export function readFlatTrigger(meta) {
332
+ if (meta === undefined)
333
+ return { on: "", action: "" };
334
+ const list = meta[TRIGGER_LIST_KEY];
335
+ if (Array.isArray(list) && list.length > 0)
336
+ return { on: "", action: "" };
337
+ const on = isTriggerEvent(meta[TRIGGER_ON_KEY]) ? meta[TRIGGER_ON_KEY] : "";
338
+ const action = typeof meta[TRIGGER_ACTION_KEY] === "string" ? meta[TRIGGER_ACTION_KEY] : "";
339
+ return { on, action };
340
+ }
@@ -0,0 +1,75 @@
1
+ import { type PathFollowState, type PathProgress, type Waypoint } from "../nav/pathFollow.js";
2
+ import type { GameContext } from "../runtime/gameContext.js";
3
+ /** Whether a behavior instance advances and writes pose (`active`), is temporarily suspended retaining
4
+ * state (`paused`), or is held off until re-enabled (`disabled`). */
5
+ export type BehaviorStatus = "active" | "paused" | "disabled";
6
+ /**
7
+ * Catch-up policy applied when a paused instance resumes. `freeze` (default, deterministic) discards
8
+ * the time spent paused; `advance` silently fast-forwards the instance by the paused duration without
9
+ * emitting intermediate pose writes. Only patrol honors `advance`; wander treats it as `freeze`.
10
+ */
11
+ export type BehaviorResumePolicy = "freeze" | "advance";
12
+ /** Serializable snapshot of one behavior instance — round-trips exactly through
13
+ * {@link BehaviorControl.serialize}/{@link BehaviorControl.restore}. */
14
+ export type BehaviorSnapshot = {
15
+ readonly kind: "patrol";
16
+ readonly state: PathFollowState;
17
+ } | {
18
+ readonly kind: "wander";
19
+ readonly origin: Waypoint;
20
+ readonly target: Waypoint | null;
21
+ };
22
+ /** Inspection readout for editor/debug tooling, from {@link BehaviorControl.inspect}/{@link BehaviorControl.list}. */
23
+ export interface BehaviorInspection {
24
+ id: string;
25
+ kind: "patrol" | "wander";
26
+ status: BehaviorStatus;
27
+ reason: string | null;
28
+ }
29
+ /**
30
+ * Per-entity control surface for the behavior runtime — pause/resume/disable/enable an instance,
31
+ * seek it to semantic progress, serialize/restore its state, and inspect it, all keyed by stable
32
+ * entity id without a full-world scan. Obtain it with {@link behaviorControl}.
33
+ */
34
+ export interface BehaviorControl {
35
+ /** Current status of the instance, or `null` if the entity has no live behavior. */
36
+ status(id: string): BehaviorStatus | null;
37
+ /** Human-readable reason attached to the last pause/disable, or `null`. */
38
+ reason(id: string): string | null;
39
+ /** Suspend advancement and pose writes, retaining state. No-op (`false`) if not active. */
40
+ pause(id: string, reason?: string): boolean;
41
+ /** Resume a paused instance, applying the catch-up `policy` (default `freeze`). */
42
+ resume(id: string, policy?: BehaviorResumePolicy): boolean;
43
+ /** Hold the instance off (no advance, no pose) until {@link enable}. Retains state. */
44
+ disable(id: string, reason?: string): boolean;
45
+ /** Re-activate a disabled instance from its retained state (no catch-up). */
46
+ enable(id: string): boolean;
47
+ /** Jump a patrol instance to semantic {@link PathProgress}. Returns `false` for non-patrol instances. */
48
+ seek(id: string, progress: PathProgress): boolean;
49
+ /** Capture the instance's exact serializable state, or `null` if absent. */
50
+ serialize(id: string): BehaviorSnapshot | null;
51
+ /** Restore an instance from a {@link BehaviorSnapshot} of the matching kind. */
52
+ restore(id: string, snapshot: BehaviorSnapshot): boolean;
53
+ /** Inspect one instance, or `null` if absent. */
54
+ inspect(id: string): BehaviorInspection | null;
55
+ /** Inspect every live instance (bounded by spawned behavior entities). */
56
+ list(): BehaviorInspection[];
57
+ }
58
+ /**
59
+ * Advance every spawned entity carrying a `patrol` or `wander` {@link BehaviorDescriptor} one tick — the
60
+ * engine reads the descriptor, keeps the per-entity nav state itself, and poses the entity, so ambient
61
+ * traffic and idle NPC routes are register-once (attach the behavior at spawn) instead of a per-game
62
+ * per-frame `advancePathFollow` + `setPose` loop. Instances that are paused or disabled through
63
+ * {@link behaviorControl} retain their state and are skipped. The shell/host call this each frame; a game never does.
64
+ *
65
+ * @capability behavior-tick auto-advance patrol/wander behaviors on spawned entities, no per-game route loop
66
+ */
67
+ export declare function advanceBehaviors(ctx: GameContext, dt: number): void;
68
+ /**
69
+ * Obtain the per-context {@link BehaviorControl} surface for suspending, resuming, seeking, serializing,
70
+ * and inspecting behavior instances by entity id — the lifecycle contract games use to hand pose
71
+ * ownership to possession/streaming/staggering code instead of bypassing the behavior runtime.
72
+ *
73
+ * @capability behavior-control pause/disable/resume/seek/inspect behavior instances per entity
74
+ */
75
+ export declare function behaviorControl(ctx: GameContext): BehaviorControl;
@@ -0,0 +1,217 @@
1
+ import { seededRng } from "../random/rng.js";
2
+ import { advancePathFollow, createPathFollow, pathFollowSeek, } from "../nav/pathFollow.js";
3
+ import { perContext } from "../runtime/perContext.js";
4
+ const DEFAULT_WANDER_SPEED = 1.5;
5
+ const WANDER_ARRIVAL = 0.6;
6
+ function patrolOf(entity) {
7
+ return entity.behaviors.find((b) => b.kind === "patrol") ?? null;
8
+ }
9
+ function wanderOf(entity) {
10
+ return entity.behaviors.find((b) => b.kind === "wander") ?? null;
11
+ }
12
+ const runtimeOf = perContext((ctx) => {
13
+ const nav = new Map();
14
+ const refresh = () => {
15
+ const live = new Set();
16
+ for (const entity of ctx.scene.entity.list()) {
17
+ live.add(entity.id);
18
+ if (nav.has(entity.id))
19
+ continue;
20
+ const patrol = patrolOf(entity);
21
+ if (patrol !== null) {
22
+ const config = { waypoints: patrol.waypoints, speed: patrol.speed, loop: patrol.loop };
23
+ nav.set(entity.id, {
24
+ kind: "patrol",
25
+ config,
26
+ state: patrol.startProgress !== undefined ? pathFollowSeek(config, patrol.startProgress) : createPathFollow(config),
27
+ groundClamp: patrol.groundClamp ?? false,
28
+ status: "active",
29
+ reason: null,
30
+ pausedElapsed: 0,
31
+ });
32
+ continue;
33
+ }
34
+ const wander = wanderOf(entity);
35
+ if (wander !== null) {
36
+ nav.set(entity.id, {
37
+ kind: "wander",
38
+ radius: wander.radius,
39
+ origin: entity.position,
40
+ target: null,
41
+ roll: seededRng(`wander:${entity.id}`),
42
+ status: "active",
43
+ reason: null,
44
+ pausedElapsed: 0,
45
+ });
46
+ }
47
+ }
48
+ for (const id of nav.keys())
49
+ if (!live.has(id))
50
+ nav.delete(id);
51
+ };
52
+ ctx.scene.entity.subscribeMembership(refresh);
53
+ refresh();
54
+ return { nav };
55
+ });
56
+ function stepWander(ctx, id, nav, dt) {
57
+ const entity = ctx.scene.entity.get(id);
58
+ if (entity === null)
59
+ return;
60
+ const [px, , pz] = entity.position;
61
+ if (nav.target === null || Math.hypot(px - nav.target[0], pz - nav.target[2]) < WANDER_ARRIVAL) {
62
+ const angle = nav.roll() * Math.PI * 2;
63
+ const distance = Math.sqrt(nav.roll()) * nav.radius;
64
+ const tx = nav.origin[0] + Math.cos(angle) * distance;
65
+ const tz = nav.origin[2] + Math.sin(angle) * distance;
66
+ nav.target = [tx, ctx.world.groundHeightAt(tx, tz), tz];
67
+ }
68
+ const speed = entity.movement.walkSpeed ?? DEFAULT_WANDER_SPEED;
69
+ const dx = nav.target[0] - px;
70
+ const dz = nav.target[2] - pz;
71
+ const dist = Math.hypot(dx, dz);
72
+ if (dist < 1e-6)
73
+ return;
74
+ const step = Math.min(dist, speed * dt);
75
+ const nx = px + (dx / dist) * step;
76
+ const nz = pz + (dz / dist) * step;
77
+ ctx.scene.entity.setPose(id, {
78
+ position: [nx, ctx.world.groundHeightAt(nx, nz), nz],
79
+ rotationY: Math.atan2(dx, dz),
80
+ dt,
81
+ });
82
+ }
83
+ function posePatrol(ctx, id, nav, dt) {
84
+ const [x, y, z] = nav.state.position;
85
+ ctx.scene.entity.setPose(id, {
86
+ position: nav.groundClamp ? [x, ctx.world.groundHeightAt(x, z), z] : [x, y, z],
87
+ rotationY: nav.state.heading,
88
+ dt,
89
+ });
90
+ }
91
+ /**
92
+ * Advance every spawned entity carrying a `patrol` or `wander` {@link BehaviorDescriptor} one tick — the
93
+ * engine reads the descriptor, keeps the per-entity nav state itself, and poses the entity, so ambient
94
+ * traffic and idle NPC routes are register-once (attach the behavior at spawn) instead of a per-game
95
+ * per-frame `advancePathFollow` + `setPose` loop. Instances that are paused or disabled through
96
+ * {@link behaviorControl} retain their state and are skipped. The shell/host call this each frame; a game never does.
97
+ *
98
+ * @capability behavior-tick auto-advance patrol/wander behaviors on spawned entities, no per-game route loop
99
+ */
100
+ export function advanceBehaviors(ctx, dt) {
101
+ if (dt <= 0)
102
+ return;
103
+ const { nav } = runtimeOf(ctx);
104
+ if (nav.size === 0)
105
+ return;
106
+ for (const [id, entry] of nav) {
107
+ if (entry.status !== "active") {
108
+ if (entry.status === "paused")
109
+ entry.pausedElapsed += dt;
110
+ continue;
111
+ }
112
+ if (entry.kind === "patrol") {
113
+ entry.state = advancePathFollow(entry.config, entry.state, dt);
114
+ posePatrol(ctx, id, entry, dt);
115
+ }
116
+ else {
117
+ stepWander(ctx, id, entry, dt);
118
+ }
119
+ }
120
+ }
121
+ /**
122
+ * Obtain the per-context {@link BehaviorControl} surface for suspending, resuming, seeking, serializing,
123
+ * and inspecting behavior instances by entity id — the lifecycle contract games use to hand pose
124
+ * ownership to possession/streaming/staggering code instead of bypassing the behavior runtime.
125
+ *
126
+ * @capability behavior-control pause/disable/resume/seek/inspect behavior instances per entity
127
+ */
128
+ export function behaviorControl(ctx) {
129
+ const { nav } = runtimeOf(ctx);
130
+ const setStatus = (id, status, reason) => {
131
+ const entry = nav.get(id);
132
+ if (entry === undefined)
133
+ return false;
134
+ entry.status = status;
135
+ entry.reason = reason;
136
+ return true;
137
+ };
138
+ return {
139
+ status: (id) => nav.get(id)?.status ?? null,
140
+ reason: (id) => nav.get(id)?.reason ?? null,
141
+ pause: (id, reason) => {
142
+ const entry = nav.get(id);
143
+ if (entry === undefined || entry.status !== "active")
144
+ return false;
145
+ entry.status = "paused";
146
+ entry.reason = reason ?? null;
147
+ entry.pausedElapsed = 0;
148
+ return true;
149
+ },
150
+ resume: (id, policy = "freeze") => {
151
+ const entry = nav.get(id);
152
+ if (entry === undefined || entry.status !== "paused")
153
+ return false;
154
+ if (policy === "advance" && entry.kind === "patrol" && entry.pausedElapsed > 0) {
155
+ entry.state = advancePathFollow(entry.config, entry.state, entry.pausedElapsed);
156
+ // Emit a single final pose at the caught-up position (no intermediate writes).
157
+ posePatrol(ctx, id, entry, entry.pausedElapsed);
158
+ }
159
+ entry.status = "active";
160
+ entry.reason = null;
161
+ entry.pausedElapsed = 0;
162
+ return true;
163
+ },
164
+ disable: (id, reason) => setStatus(id, "disabled", reason ?? null),
165
+ enable: (id) => {
166
+ const entry = nav.get(id);
167
+ if (entry === undefined || entry.status !== "disabled")
168
+ return false;
169
+ entry.status = "active";
170
+ entry.reason = null;
171
+ entry.pausedElapsed = 0;
172
+ return true;
173
+ },
174
+ seek: (id, progress) => {
175
+ const entry = nav.get(id);
176
+ if (entry === undefined || entry.kind !== "patrol")
177
+ return false;
178
+ entry.state = pathFollowSeek(entry.config, progress);
179
+ return true;
180
+ },
181
+ serialize: (id) => {
182
+ const entry = nav.get(id);
183
+ if (entry === undefined)
184
+ return null;
185
+ if (entry.kind === "patrol")
186
+ return { kind: "patrol", state: { ...entry.state } };
187
+ return { kind: "wander", origin: [...entry.origin], target: entry.target === null ? null : [...entry.target] };
188
+ },
189
+ restore: (id, snapshot) => {
190
+ const entry = nav.get(id);
191
+ if (entry === undefined || entry.kind !== snapshot.kind)
192
+ return false;
193
+ if (entry.kind === "patrol" && snapshot.kind === "patrol") {
194
+ entry.state = { ...snapshot.state };
195
+ return true;
196
+ }
197
+ if (entry.kind === "wander" && snapshot.kind === "wander") {
198
+ entry.origin = [...snapshot.origin];
199
+ entry.target = snapshot.target === null ? null : [...snapshot.target];
200
+ return true;
201
+ }
202
+ return false;
203
+ },
204
+ inspect: (id) => {
205
+ const entry = nav.get(id);
206
+ if (entry === undefined)
207
+ return null;
208
+ return { id, kind: entry.kind, status: entry.status, reason: entry.reason };
209
+ },
210
+ list: () => {
211
+ const out = [];
212
+ for (const [id, entry] of nav)
213
+ out.push({ id, kind: entry.kind, status: entry.status, reason: entry.reason });
214
+ return out;
215
+ },
216
+ };
217
+ }
@@ -1,5 +1,5 @@
1
1
  import { type ProximityPrompt } from "../interaction/proximityPrompt.js";
2
- import type { Waypoint } from "../nav/pathFollow.js";
2
+ import type { PathProgress, Waypoint } from "../nav/pathFollow.js";
3
3
  export interface WanderBehavior {
4
4
  kind: "wander";
5
5
  radius: number;
@@ -9,6 +9,16 @@ export interface PatrolBehavior {
9
9
  waypoints: readonly Waypoint[];
10
10
  speed: number;
11
11
  loop: boolean;
12
+ /**
13
+ * Optional initial progress the follower is seeded at instead of waypoint zero — lets a fleet of
14
+ * route followers start at distributed phases. Round-trips through the behavior lifecycle seek/serialize.
15
+ */
16
+ startProgress?: PathProgress;
17
+ /**
18
+ * Sample world ground height for the pose Y each tick, so a route authored in the XZ plane rides
19
+ * uneven terrain. Default false (waypoint Y is used verbatim).
20
+ */
21
+ groundClamp?: boolean;
12
22
  }
13
23
  export interface PromptableBehavior {
14
24
  kind: "promptable";
@@ -21,10 +31,12 @@ export type BehaviorDescriptor = WanderBehavior | PatrolBehavior | PromptableBeh
21
31
  export declare function wander({ radius }: {
22
32
  radius: number;
23
33
  }): WanderBehavior;
24
- export declare function patrol({ waypoints, speed, loop, }: {
34
+ export declare function patrol({ waypoints, speed, loop, startProgress, groundClamp, }: {
25
35
  waypoints: readonly Waypoint[];
26
36
  speed: number;
27
37
  loop?: boolean;
38
+ startProgress?: PathProgress;
39
+ groundClamp?: boolean;
28
40
  }): PatrolBehavior;
29
41
  export declare function promptable(prompt: ProximityPrompt): PromptableBehavior;
30
42
  export declare function talkable(dialogueId: string): PromptableBehavior;
@@ -2,8 +2,13 @@ import { command, keybind, proximityPrompt, } from "../interaction/proximityProm
2
2
  export function wander({ radius }) {
3
3
  return { kind: "wander", radius };
4
4
  }
5
- export function patrol({ waypoints, speed, loop = true, }) {
6
- return { kind: "patrol", waypoints, speed, loop };
5
+ export function patrol({ waypoints, speed, loop = true, startProgress, groundClamp, }) {
6
+ const behavior = { kind: "patrol", waypoints, speed, loop };
7
+ if (startProgress !== undefined)
8
+ behavior.startProgress = startProgress;
9
+ if (groundClamp !== undefined)
10
+ behavior.groundClamp = groundClamp;
11
+ return behavior;
7
12
  }
8
13
  export function promptable(prompt) {
9
14
  return { kind: "promptable", prompt };