@jgengine/core 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (631) hide show
  1. package/CHANGELOG.md +34 -3
  2. package/LICENSE +203 -661
  3. package/README.md +1 -1
  4. package/dist/ai/crowd.d.ts +55 -0
  5. package/dist/ai/crowd.js +114 -0
  6. package/dist/ai/flock.d.ts +5 -2
  7. package/dist/ai/flock.js +5 -2
  8. package/dist/ai/groupAssist.d.ts +1 -0
  9. package/dist/ai/groupAssist.js +1 -0
  10. package/dist/ai/heatSystem.d.ts +76 -0
  11. package/dist/ai/heatSystem.js +97 -0
  12. package/dist/ai/interestScheduler.d.ts +107 -0
  13. package/dist/ai/interestScheduler.js +118 -0
  14. package/dist/ai/jobBoard.d.ts +1 -0
  15. package/dist/ai/jobBoard.js +1 -0
  16. package/dist/ai/laneSelect.d.ts +5 -2
  17. package/dist/ai/laneSelect.js +5 -2
  18. package/dist/ai/mobBrain.d.ts +1 -0
  19. package/dist/ai/mobBrain.js +1 -0
  20. package/dist/ai/spawnDirector.d.ts +19 -1
  21. package/dist/ai/spawnDirector.js +53 -26
  22. package/dist/ai/spawnPoint.d.ts +7 -0
  23. package/dist/ai/spawnPoint.js +7 -0
  24. package/dist/ai/targetAcquisition.d.ts +84 -0
  25. package/dist/ai/targetAcquisition.js +92 -0
  26. package/dist/anim/easing.d.ts +19 -0
  27. package/dist/anim/easing.js +19 -0
  28. package/dist/anim/oscillator.d.ts +12 -0
  29. package/dist/anim/oscillator.js +25 -0
  30. package/dist/area/areaEffectField.d.ts +127 -0
  31. package/dist/area/areaEffectField.js +175 -0
  32. package/dist/area/stackPolicy.d.ts +47 -0
  33. package/dist/area/stackPolicy.js +99 -0
  34. package/dist/audio/audioFalloff.d.ts +5 -2
  35. package/dist/audio/music.d.ts +53 -0
  36. package/dist/audio/music.js +34 -0
  37. package/dist/audio/synth.d.ts +60 -0
  38. package/dist/audio/synth.js +8 -0
  39. package/dist/authoring.d.ts +15 -0
  40. package/dist/authoring.js +15 -0
  41. package/dist/board/laneBoard.d.ts +13 -0
  42. package/dist/board/laneBoard.js +13 -0
  43. package/dist/board/timelineBoard.d.ts +10 -0
  44. package/dist/board/timelineBoard.js +10 -0
  45. package/dist/combat/abilityKit.d.ts +18 -0
  46. package/dist/combat/abilityKit.js +24 -9
  47. package/dist/combat/animationState.d.ts +5 -0
  48. package/dist/combat/animationState.js +5 -0
  49. package/dist/combat/breakMeters.d.ts +10 -0
  50. package/dist/combat/breakMeters.js +10 -0
  51. package/dist/combat/castRunner.d.ts +5 -0
  52. package/dist/combat/castRunner.js +5 -0
  53. package/dist/combat/comboPoints.d.ts +5 -0
  54. package/dist/combat/comboPoints.js +5 -0
  55. package/dist/combat/comboString.d.ts +5 -0
  56. package/dist/combat/comboString.js +5 -0
  57. package/dist/combat/damageInterceptors.d.ts +192 -0
  58. package/dist/combat/damageInterceptors.js +251 -0
  59. package/dist/combat/damageMatchup.d.ts +68 -0
  60. package/dist/combat/damageMatchup.js +42 -0
  61. package/dist/combat/damageResolution.d.ts +63 -0
  62. package/dist/combat/damageResolution.js +50 -0
  63. package/dist/combat/death.d.ts +7 -1
  64. package/dist/combat/death.js +5 -0
  65. package/dist/combat/deathReason.d.ts +14 -0
  66. package/dist/combat/deathReason.js +1 -0
  67. package/dist/combat/defensiveWindow.d.ts +5 -0
  68. package/dist/combat/defensiveWindow.js +5 -0
  69. package/dist/combat/dotField.d.ts +47 -0
  70. package/dist/combat/dotField.js +52 -0
  71. package/dist/combat/downed.d.ts +5 -0
  72. package/dist/combat/downed.js +5 -0
  73. package/dist/combat/effects.d.ts +5 -0
  74. package/dist/combat/effects.js +5 -0
  75. package/dist/combat/encounterSequence.d.ts +258 -0
  76. package/dist/combat/encounterSequence.js +426 -0
  77. package/dist/combat/hitReaction.d.ts +57 -1
  78. package/dist/combat/hitReaction.js +45 -5
  79. package/dist/combat/magazine.d.ts +54 -0
  80. package/dist/combat/magazine.js +96 -0
  81. package/dist/combat/projectiles.d.ts +7 -2
  82. package/dist/combat/projectiles.js +48 -17
  83. package/dist/combat/receivedDamage.d.ts +117 -0
  84. package/dist/combat/receivedDamage.js +92 -0
  85. package/dist/combat/regenShield.d.ts +39 -0
  86. package/dist/combat/regenShield.js +49 -0
  87. package/dist/combat/renderCues.d.ts +51 -0
  88. package/dist/combat/renderCues.js +44 -0
  89. package/dist/combat/resourcePool.d.ts +5 -0
  90. package/dist/combat/resourcePool.js +5 -0
  91. package/dist/combat/rewardAllocation.d.ts +121 -0
  92. package/dist/combat/rewardAllocation.js +251 -0
  93. package/dist/combat/shotOrigin.d.ts +30 -1
  94. package/dist/combat/shotOrigin.js +70 -2
  95. package/dist/combat/statusApplication.d.ts +96 -0
  96. package/dist/combat/statusApplication.js +81 -0
  97. package/dist/combat/telegraph.d.ts +11 -2
  98. package/dist/combat/telegraph.js +11 -2
  99. package/dist/combat/thresholdCrossings.d.ts +85 -0
  100. package/dist/combat/thresholdCrossings.js +116 -0
  101. package/dist/combat.d.ts +34 -0
  102. package/dist/combat.js +34 -0
  103. package/dist/commands/commandRegistry.d.ts +11 -0
  104. package/dist/commands/commandRegistry.js +9 -2
  105. package/dist/crafting/crop.d.ts +18 -0
  106. package/dist/crafting/crop.js +18 -0
  107. package/dist/crafting/production.d.ts +5 -0
  108. package/dist/crafting/production.js +5 -0
  109. package/dist/devtools/rewriteTunables.d.ts +17 -0
  110. package/dist/devtools/rewriteTunables.js +276 -0
  111. package/dist/devtools/saveEndpoint.d.ts +46 -0
  112. package/dist/devtools/saveEndpoint.js +48 -0
  113. package/dist/devtools/transformTunables.d.ts +3 -0
  114. package/dist/devtools/transformTunables.js +3 -0
  115. package/dist/devtools/tunableSchema.d.ts +31 -0
  116. package/dist/devtools/tunableSchema.js +31 -0
  117. package/dist/economy/currency.d.ts +12 -1
  118. package/dist/economy/currency.js +12 -1
  119. package/dist/economy/listingBook.d.ts +91 -0
  120. package/dist/economy/listingBook.js +144 -0
  121. package/dist/economy/resourceLedger.d.ts +222 -0
  122. package/dist/economy/resourceLedger.js +353 -0
  123. package/dist/economy/sharedWallet.d.ts +14 -0
  124. package/dist/economy/sharedWallet.js +14 -0
  125. package/dist/economy/techTree.d.ts +12 -0
  126. package/dist/economy/techTree.js +12 -0
  127. package/dist/economy/wallet.d.ts +26 -2
  128. package/dist/economy/wallet.js +35 -6
  129. package/dist/editor/commands.d.ts +248 -0
  130. package/dist/editor/commands.js +865 -0
  131. package/dist/editor/document.d.ts +186 -0
  132. package/dist/editor/document.js +884 -0
  133. package/dist/editor/grid.d.ts +229 -0
  134. package/dist/editor/grid.js +366 -0
  135. package/dist/editor/gridAdapters.d.ts +80 -0
  136. package/dist/editor/gridAdapters.js +134 -0
  137. package/dist/editor/index.d.ts +97 -0
  138. package/dist/editor/index.js +10 -0
  139. package/dist/editor/liveSync.d.ts +127 -0
  140. package/dist/editor/liveSync.js +249 -0
  141. package/dist/editor/runtimeInspector.d.ts +88 -0
  142. package/dist/editor/runtimeInspector.js +239 -0
  143. package/dist/editor/types.d.ts +175 -0
  144. package/dist/editor/types.js +29 -0
  145. package/dist/faction/reputation.d.ts +5 -0
  146. package/dist/faction/reputation.js +5 -0
  147. package/dist/format/distance.d.ts +17 -0
  148. package/dist/format/distance.js +18 -0
  149. package/dist/format/duration.d.ts +27 -0
  150. package/dist/format/duration.js +45 -0
  151. package/dist/format/speed.d.ts +17 -0
  152. package/dist/format/speed.js +25 -0
  153. package/dist/game/connectedPlayers.d.ts +30 -0
  154. package/dist/game/connectedPlayers.js +21 -0
  155. package/dist/game/cosmetics.d.ts +9 -0
  156. package/dist/game/cosmetics.js +16 -0
  157. package/dist/game/defineGame.d.ts +141 -2
  158. package/dist/game/defineGame.js +39 -1
  159. package/dist/game/defineSystem.d.ts +88 -0
  160. package/dist/game/defineSystem.js +45 -0
  161. package/dist/game/dialogue.d.ts +33 -0
  162. package/dist/game/dialogue.js +21 -0
  163. package/dist/game/events.d.ts +50 -13
  164. package/dist/game/events.js +5 -0
  165. package/dist/game/feed.d.ts +33 -0
  166. package/dist/game/feed.js +35 -2
  167. package/dist/game/gamePhase.d.ts +11 -0
  168. package/dist/game/gamePhase.js +16 -0
  169. package/dist/game/keyValueStore.d.ts +25 -0
  170. package/dist/game/keyValueStore.js +61 -0
  171. package/dist/game/leaderboard.d.ts +5 -0
  172. package/dist/game/leaderboard.js +5 -0
  173. package/dist/game/levelSequence.d.ts +24 -2
  174. package/dist/game/levelSequence.js +51 -2
  175. package/dist/game/loadout.d.ts +5 -0
  176. package/dist/game/loadout.js +5 -0
  177. package/dist/game/lootFilter.d.ts +2 -0
  178. package/dist/game/lootFilter.js +2 -0
  179. package/dist/game/lootPipeline.d.ts +164 -0
  180. package/dist/game/lootPipeline.js +216 -0
  181. package/dist/game/lootTable.d.ts +21 -0
  182. package/dist/game/lootTable.js +15 -4
  183. package/dist/game/modelAnimation.d.ts +8 -0
  184. package/dist/game/modelAnimation.js +18 -0
  185. package/dist/game/objectives.d.ts +43 -0
  186. package/dist/game/objectives.js +36 -0
  187. package/dist/game/paramLayers.d.ts +148 -0
  188. package/dist/game/paramLayers.js +185 -0
  189. package/dist/game/ping.d.ts +5 -0
  190. package/dist/game/ping.js +5 -0
  191. package/dist/game/playableGame.d.ts +160 -12
  192. package/dist/game/quest.d.ts +8 -0
  193. package/dist/game/quest.js +29 -0
  194. package/dist/game/race.d.ts +141 -0
  195. package/dist/game/race.js +169 -0
  196. package/dist/game/recordBook.d.ts +5 -5
  197. package/dist/game/recordBook.js +4 -1
  198. package/dist/game/ruleSelection.d.ts +75 -0
  199. package/dist/game/ruleSelection.js +127 -0
  200. package/dist/game/runDraft.d.ts +5 -0
  201. package/dist/game/runDraft.js +5 -0
  202. package/dist/game/saveStore.d.ts +111 -0
  203. package/dist/game/saveStore.js +312 -0
  204. package/dist/game/snapshotHistory.d.ts +67 -0
  205. package/dist/game/snapshotHistory.js +95 -0
  206. package/dist/game/social.d.ts +38 -1
  207. package/dist/game/social.js +71 -0
  208. package/dist/game/spawnPoints.d.ts +5 -0
  209. package/dist/game/spawnPoints.js +5 -0
  210. package/dist/game/systemRuntime.d.ts +50 -0
  211. package/dist/game/systemRuntime.js +157 -0
  212. package/dist/game/systemSchedule.d.ts +72 -0
  213. package/dist/game/systemSchedule.js +242 -0
  214. package/dist/game/toasts.d.ts +43 -0
  215. package/dist/game/toasts.js +44 -0
  216. package/dist/game/trade.d.ts +10 -0
  217. package/dist/game/trade.js +10 -0
  218. package/dist/game/unlocks.d.ts +8 -0
  219. package/dist/game/unlocks.js +16 -0
  220. package/dist/game/vfxInstance.d.ts +138 -0
  221. package/dist/game/vfxInstance.js +96 -0
  222. package/dist/game/worldItem.d.ts +17 -4
  223. package/dist/game/worldItem.js +17 -4
  224. package/dist/gameplay.d.ts +91 -0
  225. package/dist/gameplay.js +91 -0
  226. package/dist/index.d.ts +5 -7
  227. package/dist/index.js +5 -7
  228. package/dist/input/actionBindings.d.ts +24 -5
  229. package/dist/input/actionBindings.js +23 -5
  230. package/dist/input/axisInput.d.ts +13 -1
  231. package/dist/input/axisInput.js +22 -1
  232. package/dist/input/controlGroups.d.ts +67 -0
  233. package/dist/input/controlGroups.js +41 -0
  234. package/dist/input/touchScheme.d.ts +82 -6
  235. package/dist/input/touchScheme.js +123 -10
  236. package/dist/interaction/contextMenu.d.ts +1 -0
  237. package/dist/interaction/contextMenu.js +1 -0
  238. package/dist/interaction/lockpick.d.ts +61 -0
  239. package/dist/interaction/lockpick.js +168 -0
  240. package/dist/interaction/proximityPrompt.d.ts +5 -1
  241. package/dist/interaction/proximityPrompt.js +5 -3
  242. package/dist/interaction/qte.d.ts +5 -0
  243. package/dist/interaction/qte.js +5 -0
  244. package/dist/interaction/skillCheck.d.ts +5 -0
  245. package/dist/interaction/skillCheck.js +5 -0
  246. package/dist/inventory/inventoryModel.d.ts +12 -0
  247. package/dist/inventory/inventoryModel.js +12 -0
  248. package/dist/inventory/shapedGrid.d.ts +16 -0
  249. package/dist/inventory/shapedGrid.js +16 -0
  250. package/dist/inventory/slotModel.d.ts +10 -0
  251. package/dist/inventory/slotModel.js +10 -0
  252. package/dist/item/durability.d.ts +5 -0
  253. package/dist/item/durability.js +5 -0
  254. package/dist/item/itemIdentity.d.ts +171 -0
  255. package/dist/item/itemIdentity.js +138 -0
  256. package/dist/item/itemInstanceRegistry.d.ts +32 -0
  257. package/dist/item/itemInstanceRegistry.js +34 -0
  258. package/dist/item/itemgen.d.ts +163 -0
  259. package/dist/item/itemgen.js +151 -0
  260. package/dist/item/modularItem.d.ts +5 -0
  261. package/dist/item/modularItem.js +5 -0
  262. package/dist/item/use.d.ts +5 -0
  263. package/dist/item/use.js +5 -0
  264. package/dist/item/useBehavior.d.ts +142 -0
  265. package/dist/item/useBehavior.js +105 -0
  266. package/dist/item/weapon.d.ts +5 -0
  267. package/dist/item/weapon.js +5 -0
  268. package/dist/math/scalar.d.ts +25 -0
  269. package/dist/math/scalar.js +47 -0
  270. package/dist/meta/changelog.d.ts +4 -1
  271. package/dist/meta/changelog.js +36 -1
  272. package/dist/movement/avoidance.d.ts +45 -0
  273. package/dist/movement/avoidance.js +123 -0
  274. package/dist/movement/cameraRig.d.ts +8 -0
  275. package/dist/movement/cameraRig.js +8 -0
  276. package/dist/movement/dash.d.ts +11 -0
  277. package/dist/movement/dash.js +11 -0
  278. package/dist/movement/formation.d.ts +135 -0
  279. package/dist/movement/formation.js +194 -0
  280. package/dist/movement/glideModel.d.ts +5 -0
  281. package/dist/movement/glideModel.js +5 -0
  282. package/dist/movement/grappleSwing.d.ts +5 -0
  283. package/dist/movement/grappleSwing.js +5 -0
  284. package/dist/movement/leaderTrail.d.ts +5 -0
  285. package/dist/movement/leaderTrail.js +5 -0
  286. package/dist/movement/movementModel.d.ts +38 -7
  287. package/dist/movement/movementModel.js +54 -13
  288. package/dist/movement/playerMovement.d.ts +41 -0
  289. package/dist/movement/playerMovement.js +236 -0
  290. package/dist/movement/poseState.d.ts +13 -0
  291. package/dist/movement/poseState.js +16 -0
  292. package/dist/movement/steering.d.ts +8 -0
  293. package/dist/movement/steering.js +18 -0
  294. package/dist/multiplayer/combatSnapshot.d.ts +3 -0
  295. package/dist/multiplayer/combatSnapshot.js +3 -0
  296. package/dist/multiplayer/lagCompensation.d.ts +5 -0
  297. package/dist/multiplayer/lagCompensation.js +5 -0
  298. package/dist/multiplayer/presenceModel.d.ts +9 -1
  299. package/dist/multiplayer/presenceModel.js +9 -1
  300. package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
  301. package/dist/multiplayer/simultaneousCommit.js +3 -0
  302. package/dist/multiplayer.d.ts +11 -0
  303. package/dist/multiplayer.js +11 -0
  304. package/dist/nav/pathFollow.d.ts +57 -0
  305. package/dist/nav/pathFollow.js +109 -0
  306. package/dist/orders/orderKinds.d.ts +156 -0
  307. package/dist/orders/orderKinds.js +197 -0
  308. package/dist/orders/orderQueue.d.ts +208 -0
  309. package/dist/orders/orderQueue.js +211 -0
  310. package/dist/physics/drivableVehicle.d.ts +29 -0
  311. package/dist/physics/drivableVehicle.js +16 -0
  312. package/dist/physics/kinematicVehicle.d.ts +21 -1
  313. package/dist/physics/kinematicVehicle.js +23 -8
  314. package/dist/physics/physicsWorld.d.ts +24 -12
  315. package/dist/physics/physicsWorld.js +11 -5
  316. package/dist/physics/radialImpulse.d.ts +25 -0
  317. package/dist/physics/radialImpulse.js +27 -0
  318. package/dist/procedural.d.ts +3 -0
  319. package/dist/procedural.js +3 -0
  320. package/dist/progression/statGraph.d.ts +116 -0
  321. package/dist/progression/statGraph.js +318 -0
  322. package/dist/puzzle/cellGrid.d.ts +9 -0
  323. package/dist/puzzle/cellGrid.js +9 -0
  324. package/dist/puzzle/fallingPiece.d.ts +9 -0
  325. package/dist/puzzle/fallingPiece.js +9 -0
  326. package/dist/puzzle/nonogram.d.ts +39 -0
  327. package/dist/puzzle/nonogram.js +136 -0
  328. package/dist/random/nameGen.d.ts +5 -0
  329. package/dist/random/nameGen.js +5 -0
  330. package/dist/random/pick.d.ts +8 -0
  331. package/dist/random/pick.js +31 -0
  332. package/dist/random/rng.d.ts +24 -0
  333. package/dist/random/rng.js +30 -8
  334. package/dist/random/seedLink.d.ts +4 -0
  335. package/dist/random/seedLink.js +4 -0
  336. package/dist/relation/keyedValues.d.ts +54 -0
  337. package/dist/relation/keyedValues.js +115 -0
  338. package/dist/relation/thresholds.d.ts +62 -0
  339. package/dist/relation/thresholds.js +62 -0
  340. package/dist/render/color.d.ts +12 -0
  341. package/dist/render/color.js +26 -0
  342. package/dist/render/lookPreset.d.ts +41 -0
  343. package/dist/render/lookPreset.js +29 -0
  344. package/dist/render/postProcessing.d.ts +76 -0
  345. package/dist/render/postProcessing.js +21 -0
  346. package/dist/rules/predicate.d.ts +53 -0
  347. package/dist/rules/predicate.js +64 -0
  348. package/dist/rules/ruleEffects.d.ts +38 -0
  349. package/dist/rules/ruleEffects.js +37 -0
  350. package/dist/rules/triggeredRules.d.ts +160 -0
  351. package/dist/rules/triggeredRules.js +241 -0
  352. package/dist/runtime/adapter.d.ts +58 -0
  353. package/dist/runtime/adapter.js +54 -5
  354. package/dist/runtime/cameraDirector.d.ts +1 -0
  355. package/dist/runtime/cameraDirector.js +1 -0
  356. package/dist/runtime/commandRunner.d.ts +1 -0
  357. package/dist/runtime/commandRunner.js +1 -0
  358. package/dist/runtime/context/combatFx.d.ts +23 -0
  359. package/dist/runtime/context/combatFx.js +161 -0
  360. package/dist/runtime/context/registries.d.ts +13 -0
  361. package/dist/runtime/context/registries.js +84 -0
  362. package/dist/runtime/context/worldItems.d.ts +21 -0
  363. package/dist/runtime/context/worldItems.js +37 -0
  364. package/dist/runtime/descriptors/baseline.d.ts +48 -0
  365. package/dist/runtime/descriptors/baseline.js +134 -0
  366. package/dist/runtime/descriptors/features.d.ts +74 -0
  367. package/dist/runtime/descriptors/features.js +281 -0
  368. package/dist/runtime/gameContext.d.ts +163 -19
  369. package/dist/runtime/gameContext.js +385 -339
  370. package/dist/runtime/gameRuntime.d.ts +1 -0
  371. package/dist/runtime/gameRuntime.js +1 -0
  372. package/dist/runtime/headlessRunner.d.ts +60 -0
  373. package/dist/runtime/headlessRunner.js +44 -0
  374. package/dist/runtime/hostPersistence.d.ts +12 -0
  375. package/dist/runtime/hostPersistence.js +12 -0
  376. package/dist/runtime/hostedGameRunner.d.ts +54 -0
  377. package/dist/runtime/hostedGameRunner.js +85 -0
  378. package/dist/runtime/hostedWorldSession.d.ts +73 -0
  379. package/dist/runtime/hostedWorldSession.js +64 -0
  380. package/dist/runtime/inputSnapshot.d.ts +21 -3
  381. package/dist/runtime/inputSnapshot.js +8 -2
  382. package/dist/runtime/motionIntents.d.ts +12 -1
  383. package/dist/runtime/motionIntents.js +26 -1
  384. package/dist/runtime/perContext.d.ts +15 -0
  385. package/dist/runtime/perContext.js +21 -0
  386. package/dist/runtime/runtimeSave.d.ts +79 -0
  387. package/dist/runtime/runtimeSave.js +105 -0
  388. package/dist/runtime/save.d.ts +4 -0
  389. package/dist/runtime/save.js +4 -0
  390. package/dist/runtime/snapshot.d.ts +7 -0
  391. package/dist/runtime/snapshot.js +7 -0
  392. package/dist/runtime/visibility.d.ts +2 -1
  393. package/dist/runtime/visibility.js +2 -1
  394. package/dist/runtime/worldChannel.d.ts +62 -0
  395. package/dist/runtime/worldChannel.js +114 -0
  396. package/dist/runtime/worldMirror.d.ts +36 -0
  397. package/dist/runtime/worldMirror.js +44 -0
  398. package/dist/runtime/worldProjection.d.ts +47 -0
  399. package/dist/runtime/worldProjection.js +52 -0
  400. package/dist/runtime/worldReplication.d.ts +69 -0
  401. package/dist/runtime/worldReplication.js +217 -0
  402. package/dist/runtime/worldSnapshot.d.ts +44 -0
  403. package/dist/runtime/worldSnapshot.js +30 -0
  404. package/dist/scene/assetCatalog.d.ts +22 -0
  405. package/dist/scene/assetCatalog.js +4 -0
  406. package/dist/scene/assetDiagnostics.d.ts +69 -0
  407. package/dist/scene/assetDiagnostics.js +110 -0
  408. package/dist/scene/assetGenerator.d.ts +65 -0
  409. package/dist/scene/assetGenerator.js +64 -0
  410. package/dist/scene/assetSpace.d.ts +137 -0
  411. package/dist/scene/assetSpace.js +259 -0
  412. package/dist/scene/authoredTriggers.d.ts +169 -0
  413. package/dist/scene/authoredTriggers.js +340 -0
  414. package/dist/scene/behaviorRuntime.d.ts +75 -0
  415. package/dist/scene/behaviorRuntime.js +217 -0
  416. package/dist/scene/behaviors.d.ts +14 -2
  417. package/dist/scene/behaviors.js +7 -2
  418. package/dist/scene/bodyBind.d.ts +60 -0
  419. package/dist/scene/bodyBind.js +51 -0
  420. package/dist/scene/builtinSceneKinds.d.ts +5 -0
  421. package/dist/scene/builtinSceneKinds.js +62 -0
  422. package/dist/scene/colliders.d.ts +18 -0
  423. package/dist/scene/colliders.js +61 -1
  424. package/dist/scene/entityStats.d.ts +13 -0
  425. package/dist/scene/entityStats.js +30 -0
  426. package/dist/scene/entityStore.d.ts +41 -1
  427. package/dist/scene/entityStore.js +75 -0
  428. package/dist/scene/facing.d.ts +18 -0
  429. package/dist/scene/facing.js +26 -0
  430. package/dist/scene/modelSockets.d.ts +33 -0
  431. package/dist/scene/modelSockets.js +29 -0
  432. package/dist/scene/objectQuery.d.ts +2 -0
  433. package/dist/scene/objectQuery.js +2 -0
  434. package/dist/scene/objectStore.d.ts +4 -0
  435. package/dist/scene/objectStore.js +6 -0
  436. package/dist/scene/possession.d.ts +8 -0
  437. package/dist/scene/possession.js +14 -0
  438. package/dist/scene/roster.d.ts +3 -0
  439. package/dist/scene/roster.js +12 -0
  440. package/dist/scene/sceneKinds.d.ts +240 -0
  441. package/dist/scene/sceneKinds.js +214 -0
  442. package/dist/scene/sceneOwnership.d.ts +169 -0
  443. package/dist/scene/sceneOwnership.js +179 -0
  444. package/dist/scene/selectionBookmarks.d.ts +93 -0
  445. package/dist/scene/selectionBookmarks.js +122 -0
  446. package/dist/scene/vehicleSeat.d.ts +68 -0
  447. package/dist/scene/vehicleSeat.js +59 -0
  448. package/dist/sensor/concealment.d.ts +3 -0
  449. package/dist/sensor/concealment.js +3 -0
  450. package/dist/sensor/freezeMonitor.d.ts +1 -0
  451. package/dist/sensor/freezeMonitor.js +1 -0
  452. package/dist/sensor/frustumSensor.d.ts +7 -3
  453. package/dist/sensor/frustumSensor.js +7 -3
  454. package/dist/sensor/hiddenStateProbe.d.ts +5 -2
  455. package/dist/sensor/hiddenStateProbe.js +5 -2
  456. package/dist/sensor/recordingBuffer.d.ts +2 -1
  457. package/dist/sensor/recordingBuffer.js +2 -1
  458. package/dist/sensor/replayLoop.d.ts +6 -2
  459. package/dist/sensor/replayLoop.js +6 -2
  460. package/dist/sensor/revealQuery.d.ts +2 -1
  461. package/dist/sensor/revealQuery.js +2 -1
  462. package/dist/sensor/visionCone.d.ts +10 -3
  463. package/dist/sensor/visionCone.js +10 -3
  464. package/dist/session/contestedChannel.d.ts +1 -0
  465. package/dist/session/contestedChannel.js +1 -0
  466. package/dist/session/extraction.d.ts +1 -0
  467. package/dist/session/extraction.js +1 -0
  468. package/dist/session/roles.d.ts +6 -0
  469. package/dist/session/roles.js +6 -0
  470. package/dist/session/roundState.d.ts +8 -0
  471. package/dist/session/roundState.js +2 -0
  472. package/dist/settings/settingsModel.d.ts +1 -0
  473. package/dist/settings/settingsModel.js +1 -0
  474. package/dist/stats/accumulatorMeter.d.ts +6 -0
  475. package/dist/stats/accumulatorMeter.js +6 -0
  476. package/dist/stats/eventMeter.d.ts +5 -0
  477. package/dist/stats/eventMeter.js +5 -0
  478. package/dist/stats/rollCheck.d.ts +5 -0
  479. package/dist/stats/rollCheck.js +5 -0
  480. package/dist/stats/statModifiers.d.ts +5 -0
  481. package/dist/stats/statModifiers.js +5 -0
  482. package/dist/store/defineKeyedStore.d.ts +38 -0
  483. package/dist/store/defineKeyedStore.js +42 -0
  484. package/dist/store/defineStore.d.ts +33 -0
  485. package/dist/store/defineStore.js +35 -0
  486. package/dist/store/observableKeyedStore.d.ts +9 -0
  487. package/dist/store/observableKeyedStore.js +43 -2
  488. package/dist/survival/decayMeter.d.ts +55 -0
  489. package/dist/survival/decayMeter.js +130 -55
  490. package/dist/survival/moodle.d.ts +2 -0
  491. package/dist/survival/regionHealth.d.ts +6 -0
  492. package/dist/survival/regionHealth.js +5 -0
  493. package/dist/tactics/fallingGrid.d.ts +6 -4
  494. package/dist/tactics/fallingGrid.js +6 -4
  495. package/dist/tactics/predictiveQuery.d.ts +3 -0
  496. package/dist/tactics/predictiveQuery.js +3 -0
  497. package/dist/tactics/snapshot.d.ts +2 -0
  498. package/dist/tactics/snapshot.js +2 -0
  499. package/dist/tactics/surface.d.ts +1 -0
  500. package/dist/tactics/surface.js +1 -0
  501. package/dist/tactics/tacticalGrid.d.ts +1 -0
  502. package/dist/tactics/tacticalGrid.js +1 -0
  503. package/dist/time/beatClock.d.ts +14 -4
  504. package/dist/time/beatClock.js +14 -4
  505. package/dist/time/calendarClock.d.ts +3 -0
  506. package/dist/time/calendarClock.js +3 -0
  507. package/dist/time/idleProgress.d.ts +4 -0
  508. package/dist/time/idleProgress.js +4 -0
  509. package/dist/time/simClock.d.ts +2 -0
  510. package/dist/time/simClock.js +20 -5
  511. package/dist/ui/actionModel.d.ts +110 -0
  512. package/dist/ui/actionModel.js +159 -0
  513. package/dist/ui/gameLayout.d.ts +144 -0
  514. package/dist/ui/gameLayout.js +148 -0
  515. package/dist/ui/hudDocument.d.ts +114 -0
  516. package/dist/ui/hudDocument.js +220 -0
  517. package/dist/ui/hudLayout.d.ts +33 -1
  518. package/dist/ui/hudLayout.js +204 -17
  519. package/dist/ui/orientation.d.ts +39 -0
  520. package/dist/ui/orientation.js +49 -0
  521. package/dist/ui/selectionModel.d.ts +92 -0
  522. package/dist/ui/selectionModel.js +88 -0
  523. package/dist/ui/swingTimer.d.ts +42 -0
  524. package/dist/ui/swingTimer.js +38 -0
  525. package/dist/ui/tooltipModel.d.ts +63 -0
  526. package/dist/ui/tooltipModel.js +82 -0
  527. package/dist/ui.d.ts +15 -0
  528. package/dist/ui.js +15 -0
  529. package/dist/visibility/bounds.d.ts +8 -1
  530. package/dist/visibility/bounds.js +8 -1
  531. package/dist/visibility/frustum.d.ts +12 -3
  532. package/dist/visibility/frustum.js +12 -3
  533. package/dist/visibility/spatialIndex.js +34 -20
  534. package/dist/work/jobQueue.d.ts +201 -0
  535. package/dist/work/jobQueue.js +253 -0
  536. package/dist/work/unitTraining.d.ts +58 -0
  537. package/dist/work/unitTraining.js +52 -0
  538. package/dist/world/authoredObjects.d.ts +58 -0
  539. package/dist/world/authoredObjects.js +69 -0
  540. package/dist/world/buildingGenerator.d.ts +18 -0
  541. package/dist/world/buildingGenerator.js +62 -0
  542. package/dist/world/buildings.d.ts +5 -0
  543. package/dist/world/buildings.js +5 -0
  544. package/dist/world/catenary.d.ts +22 -0
  545. package/dist/world/catenary.js +69 -0
  546. package/dist/world/environmentSummary.d.ts +11 -2
  547. package/dist/world/environmentSummary.js +11 -1
  548. package/dist/world/features.d.ts +244 -7
  549. package/dist/world/features.js +92 -4
  550. package/dist/world/footprintGrid.d.ts +59 -0
  551. package/dist/world/footprintGrid.js +141 -0
  552. package/dist/world/geometry.d.ts +64 -0
  553. package/dist/world/geometry.js +94 -0
  554. package/dist/world/grassKind.d.ts +51 -0
  555. package/dist/world/grassKind.js +101 -0
  556. package/dist/world/pathInstances.d.ts +27 -0
  557. package/dist/world/pathInstances.js +27 -0
  558. package/dist/world/pathTerrain.d.ts +80 -0
  559. package/dist/world/pathTerrain.js +142 -0
  560. package/dist/world/placeAsset.d.ts +81 -0
  561. package/dist/world/placeAsset.js +77 -0
  562. package/dist/world/placement.d.ts +4 -0
  563. package/dist/world/placement.js +4 -0
  564. package/dist/world/placementController.d.ts +6 -0
  565. package/dist/world/placementController.js +6 -0
  566. package/dist/world/polyline.d.ts +34 -0
  567. package/dist/world/polyline.js +81 -0
  568. package/dist/world/roads.d.ts +55 -0
  569. package/dist/world/roads.js +184 -0
  570. package/dist/world/scatterRegion.d.ts +164 -0
  571. package/dist/world/scatterRegion.js +409 -0
  572. package/dist/world/sceneShapes.d.ts +43 -0
  573. package/dist/world/sceneShapes.js +1 -0
  574. package/dist/world/segment.d.ts +27 -0
  575. package/dist/world/segment.js +43 -0
  576. package/dist/world/soilKind.d.ts +48 -0
  577. package/dist/world/soilKind.js +92 -0
  578. package/dist/world/spatialSample.d.ts +241 -0
  579. package/dist/world/spatialSample.js +465 -0
  580. package/dist/world/streets.d.ts +80 -0
  581. package/dist/world/streets.js +144 -0
  582. package/dist/world/terraform.d.ts +213 -1
  583. package/dist/world/terraform.js +655 -20
  584. package/dist/world/terrain.d.ts +138 -12
  585. package/dist/world/terrain.js +346 -28
  586. package/dist/world/terrainGuides.d.ts +182 -0
  587. package/dist/world/terrainGuides.js +343 -0
  588. package/dist/world/vec2.d.ts +81 -0
  589. package/dist/world/vec2.js +128 -0
  590. package/dist/world/vec3.d.ts +49 -0
  591. package/dist/world/vec3.js +76 -0
  592. package/dist/world/vegetation.d.ts +71 -0
  593. package/dist/world/vegetation.js +151 -0
  594. package/dist/world/visibilityField.d.ts +154 -0
  595. package/dist/world/visibilityField.js +271 -0
  596. package/dist/world/volumetricClouds.d.ts +52 -0
  597. package/dist/world/volumetricClouds.js +43 -0
  598. package/dist/world/walls.d.ts +9 -0
  599. package/dist/world/walls.js +9 -0
  600. package/dist/world/waterKind.d.ts +55 -0
  601. package/dist/world/waterKind.js +99 -0
  602. package/dist/world.d.ts +132 -0
  603. package/dist/world.js +132 -0
  604. package/package.json +32 -8
  605. package/skills/jgengine/SKILL.md +51 -0
  606. package/skills/jgengine/api.md +434 -0
  607. package/skills/jgengine/capabilities.md +29 -0
  608. package/skills/jgengine/reference-cartridge.md +72 -0
  609. package/skills/jgengine-combat/SKILL.md +34 -0
  610. package/skills/jgengine-combat/api.md +549 -0
  611. package/skills/jgengine-combat/capabilities.md +169 -0
  612. package/skills/jgengine-combat/reference.md +98 -0
  613. package/skills/jgengine-gameplay/SKILL.md +39 -0
  614. package/skills/jgengine-gameplay/api.md +1794 -0
  615. package/skills/jgengine-gameplay/capabilities.md +378 -0
  616. package/skills/jgengine-gameplay/reference-systems.md +60 -0
  617. package/skills/jgengine-world/SKILL.md +38 -0
  618. package/skills/jgengine-world/api.md +2652 -0
  619. package/skills/jgengine-world/capabilities.md +370 -0
  620. package/skills/jgengine-world/reference.md +222 -0
  621. package/dist/cartridge/runtime.d.ts +0 -15
  622. package/dist/cartridge/runtime.js +0 -556
  623. package/dist/cartridge/spec.d.ts +0 -188
  624. package/dist/cartridge/spec.js +0 -19
  625. package/dist/cartridge/validate.d.ts +0 -2
  626. package/dist/cartridge/validate.js +0 -78
  627. package/dist/store/engineStore.d.ts +0 -22
  628. package/dist/store/engineStore.js +0 -50
  629. package/dist/store/features.d.ts +0 -10
  630. package/dist/store/features.js +0 -23
  631. package/llms.txt +0 -4983
@@ -0,0 +1,25 @@
1
+ /** Sawtooth ramp: rises 0→1 over each `period` then resets, for looping sweeps and scrolls.
2
+ * @internal
3
+ */
4
+ export function sawWave(time, period) {
5
+ if (!(period > 0))
6
+ return 0;
7
+ const phase = ((time % period) + period) % period;
8
+ return phase / period;
9
+ }
10
+ /** Triangle wave: ramps 0→1→0 across each `period`, for patrols, searchlights, and pulsing glows.
11
+ * @internal
12
+ */
13
+ export function triangleWave(time, period) {
14
+ const up = sawWave(time, period);
15
+ return up < 0.5 ? up * 2 : 2 - up * 2;
16
+ }
17
+ /** Ping-pong a value across `[0, length]`, bouncing at each edge — the index/position analog of {@link triangleWave}.
18
+ * @internal
19
+ */
20
+ export function pingPong(value, length) {
21
+ if (!(length > 0))
22
+ return 0;
23
+ const t = ((value % (length * 2)) + length * 2) % (length * 2);
24
+ return t <= length ? t : length * 2 - t;
25
+ }
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Continuous area-effect membership: moving sources emit an area that follows them each tick,
3
+ * receivers that move in and out get enter / refresh / leave edges, and membership is cleaned up
4
+ * when a source is removed, disabled, or the field is cleared. A pure lifecycle machine — it never
5
+ * applies damage, heals, or stat changes itself; the caller routes each edge through its own
6
+ * effect pipeline (see `combat/effects`, `combat/dotField`, `stats/statModifiers`). This is the
7
+ * dynamic, source-following counterpart to `scene/authoredTriggers` (static document volumes).
8
+ *
9
+ * Bounded by design: the caller supplies a broad-phase `candidates(shape)` query (e.g.
10
+ * `visibility/spatialIndex`'s `querySphere`) plus a `positionOf` lookup, so a step visits only
11
+ * receivers near each source — never the whole world. Serializable: `serialize()` captures the
12
+ * membership set and each member's refresh phase so cadence and enter/leave edges survive save/load.
13
+ */
14
+ import type { EntityPosition } from "../scene/entityStore.js";
15
+ /**
16
+ * The area a source occupies this tick. `sphere` is first-class; `custom` leaves a seam for authored
17
+ * volumes and other shapes while still exposing a bounding sphere (`center`/`radius`) for the caller's
18
+ * broad-phase candidate query.
19
+ */
20
+ export type AreaShape = {
21
+ readonly kind: "sphere";
22
+ readonly center: EntityPosition;
23
+ readonly radius: number;
24
+ } | {
25
+ readonly kind: "custom";
26
+ /** Bounding-sphere center the caller's broad-phase `candidates` query is built from. */
27
+ readonly center: EntityPosition;
28
+ /** Bounding-sphere radius the caller's broad-phase `candidates` query is built from. */
29
+ readonly radius: number;
30
+ /** Authoritative containment test applied to each broad-phase candidate. */
31
+ readonly contains: (point: EntityPosition) => boolean;
32
+ };
33
+ /** Descriptor for one continuous area source; re-supplied each tick so its shape follows the emitter. */
34
+ export interface AreaSourceSpec<P> {
35
+ /** Stable source id (the emitter). Re-using an id updates the descriptor and preserves membership. */
36
+ readonly id: string;
37
+ /** The source's area this tick — pass the emitter's live position so membership follows it. */
38
+ readonly shape: AreaShape;
39
+ /** Caller data describing what this source does (damage amount, heal, buff key, capture rate…). */
40
+ readonly payload: P;
41
+ /** Milliseconds between `refresh` edges emitted for each member; omit for enter/leave only. */
42
+ readonly refreshMs?: number;
43
+ /** Aggregation group key for stacking policies; defaults to the source id. */
44
+ readonly stackKey?: string;
45
+ /** When false the source keeps its descriptor but holds no members (current members `leave`). Default true. */
46
+ readonly enabled?: boolean;
47
+ }
48
+ /** Why a `leave` edge fired. */
49
+ export type AreaLeaveReason = "exit" | "source-removed" | "disabled" | "cleared";
50
+ /** The three membership edges a step can emit. */
51
+ export type AreaEventKind = "enter" | "refresh" | "leave";
52
+ /** One membership edge emitted by `step`, `removeSource`, or `clear`. */
53
+ export interface AreaEffectEvent<P> {
54
+ readonly kind: AreaEventKind;
55
+ readonly sourceId: string;
56
+ readonly receiverId: string;
57
+ readonly stackKey: string;
58
+ readonly payload: P;
59
+ /** Number of refresh cadences crossed this step (>= 1 on `refresh`; a large dt can cross several). */
60
+ readonly ticks?: number;
61
+ /** Present only on `leave`. */
62
+ readonly reason?: AreaLeaveReason;
63
+ }
64
+ /** One active (source, receiver) membership — feed a receiver's list to a stacking policy. */
65
+ export interface AreaMembership<P> {
66
+ readonly sourceId: string;
67
+ readonly receiverId: string;
68
+ readonly stackKey: string;
69
+ readonly payload: P;
70
+ }
71
+ /** Per-tick inputs the field needs to reconcile membership without scanning the world. */
72
+ export interface AreaStepInput {
73
+ /** Milliseconds since the previous step; negative values are clamped to 0. */
74
+ readonly dtMs: number;
75
+ /** Bounded broad-phase: receiver ids possibly inside `shape` (e.g. `spatialIndex.querySphere`). */
76
+ readonly candidates: (shape: AreaShape) => Iterable<string>;
77
+ /** Precise receiver position; `undefined` means the receiver is gone (removed/dead) and is dropped. */
78
+ readonly positionOf: (receiverId: string) => EntityPosition | undefined;
79
+ /** Optional per-pair gate (team filter, immunity, line-of-sight already resolved by the caller). */
80
+ readonly eligible?: (sourceId: string, receiverId: string, payload: unknown) => boolean;
81
+ }
82
+ /** Serialized field state: source descriptors (minus their transient shape) and per-member refresh phase. */
83
+ export interface AreaFieldState<P> {
84
+ readonly sources: {
85
+ readonly id: string;
86
+ readonly payload: P;
87
+ readonly refreshMs?: number;
88
+ readonly stackKey: string;
89
+ readonly enabled: boolean;
90
+ }[];
91
+ readonly memberships: {
92
+ readonly sourceId: string;
93
+ readonly receiverId: string;
94
+ readonly sinceRefreshMs: number;
95
+ }[];
96
+ }
97
+ /** Runtime handle tracking continuous area membership across ticks. */
98
+ export interface AreaEffectField<P> {
99
+ /** Register or update a source (upsert by id); an update preserves existing membership and refresh phase. */
100
+ setSource(spec: AreaSourceSpec<P>): void;
101
+ /** Remove a source and return a `leave` (reason `source-removed`) for each of its members. */
102
+ removeSource(id: string): AreaEffectEvent<P>[];
103
+ hasSource(id: string): boolean;
104
+ sourceIds(): string[];
105
+ /** Reconcile every source against the receivers its `candidates` query returns; emit enter/refresh/leave. */
106
+ step(input: AreaStepInput): AreaEffectEvent<P>[];
107
+ /** Receiver ids currently inside `sourceId`. */
108
+ members(sourceId: string): string[];
109
+ isMember(sourceId: string, receiverId: string): boolean;
110
+ /** Every active membership across all sources. */
111
+ memberships(): AreaMembership<P>[];
112
+ /** Active memberships affecting a single receiver — the input to a stacking policy. */
113
+ membershipsOf(receiverId: string): AreaMembership<P>[];
114
+ /** Drop all sources and members; returns a `leave` (reason `cleared`) for each member. */
115
+ clear(): AreaEffectEvent<P>[];
116
+ /** Snapshot the persistent membership lifecycle for save/load; shapes are transient and re-supplied via `setSource`. */
117
+ serialize(): AreaFieldState<P>;
118
+ }
119
+ /**
120
+ * Build a continuous area-effect field. Drive it with `setSource` (once per live source per tick, so
121
+ * shapes follow their emitters) and `step` (to reconcile membership and drain enter/refresh/leave edges).
122
+ * Optionally restore prior membership by passing a `serialize()` snapshot; re-`setSource` live shapes
123
+ * before the first `step` after restore, since shapes are transient.
124
+ *
125
+ * @capability area-effect-field source-following area membership with enter/refresh/leave edges, stacking, and cleanup
126
+ */
127
+ export declare function createAreaEffectField<P = unknown>(state?: AreaFieldState<P>): AreaEffectField<P>;
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Continuous area-effect membership: moving sources emit an area that follows them each tick,
3
+ * receivers that move in and out get enter / refresh / leave edges, and membership is cleaned up
4
+ * when a source is removed, disabled, or the field is cleared. A pure lifecycle machine — it never
5
+ * applies damage, heals, or stat changes itself; the caller routes each edge through its own
6
+ * effect pipeline (see `combat/effects`, `combat/dotField`, `stats/statModifiers`). This is the
7
+ * dynamic, source-following counterpart to `scene/authoredTriggers` (static document volumes).
8
+ *
9
+ * Bounded by design: the caller supplies a broad-phase `candidates(shape)` query (e.g.
10
+ * `visibility/spatialIndex`'s `querySphere`) plus a `positionOf` lookup, so a step visits only
11
+ * receivers near each source — never the whole world. Serializable: `serialize()` captures the
12
+ * membership set and each member's refresh phase so cadence and enter/leave edges survive save/load.
13
+ */
14
+ const SENTINEL_SHAPE = { kind: "sphere", center: [0, 0, 0], radius: 0 };
15
+ function shapeContains(shape, point) {
16
+ if (shape.kind === "custom")
17
+ return shape.contains(point);
18
+ const dx = point[0] - shape.center[0];
19
+ const dy = point[1] - shape.center[1];
20
+ const dz = point[2] - shape.center[2];
21
+ return dx * dx + dy * dy + dz * dz <= shape.radius * shape.radius;
22
+ }
23
+ /**
24
+ * Build a continuous area-effect field. Drive it with `setSource` (once per live source per tick, so
25
+ * shapes follow their emitters) and `step` (to reconcile membership and drain enter/refresh/leave edges).
26
+ * Optionally restore prior membership by passing a `serialize()` snapshot; re-`setSource` live shapes
27
+ * before the first `step` after restore, since shapes are transient.
28
+ *
29
+ * @capability area-effect-field source-following area membership with enter/refresh/leave edges, stacking, and cleanup
30
+ */
31
+ export function createAreaEffectField(state) {
32
+ const sources = new Map();
33
+ if (state !== undefined) {
34
+ for (const source of state.sources) {
35
+ sources.set(source.id, {
36
+ shape: SENTINEL_SHAPE,
37
+ payload: source.payload,
38
+ refreshMs: source.refreshMs,
39
+ stackKey: source.stackKey,
40
+ enabled: source.enabled,
41
+ members: new Map(),
42
+ });
43
+ }
44
+ for (const membership of state.memberships) {
45
+ sources.get(membership.sourceId)?.members.set(membership.receiverId, {
46
+ sinceRefreshMs: membership.sinceRefreshMs,
47
+ });
48
+ }
49
+ }
50
+ function leaveAll(rec, sourceId, reason) {
51
+ const events = [];
52
+ for (const receiverId of rec.members.keys()) {
53
+ events.push({ kind: "leave", sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload, reason });
54
+ }
55
+ rec.members.clear();
56
+ return events;
57
+ }
58
+ return {
59
+ setSource(spec) {
60
+ const stackKey = spec.stackKey ?? spec.id;
61
+ const enabled = spec.enabled ?? true;
62
+ const existing = sources.get(spec.id);
63
+ if (existing !== undefined) {
64
+ existing.shape = spec.shape;
65
+ existing.payload = spec.payload;
66
+ existing.refreshMs = spec.refreshMs;
67
+ existing.stackKey = stackKey;
68
+ existing.enabled = enabled;
69
+ return;
70
+ }
71
+ sources.set(spec.id, {
72
+ shape: spec.shape,
73
+ payload: spec.payload,
74
+ refreshMs: spec.refreshMs,
75
+ stackKey,
76
+ enabled,
77
+ members: new Map(),
78
+ });
79
+ },
80
+ removeSource(id) {
81
+ const rec = sources.get(id);
82
+ if (rec === undefined)
83
+ return [];
84
+ const events = leaveAll(rec, id, "source-removed");
85
+ sources.delete(id);
86
+ return events;
87
+ },
88
+ hasSource: (id) => sources.has(id),
89
+ sourceIds: () => [...sources.keys()],
90
+ step(input) {
91
+ const dtMs = Math.max(0, input.dtMs);
92
+ const events = [];
93
+ for (const [sourceId, rec] of sources) {
94
+ if (!rec.enabled) {
95
+ events.push(...leaveAll(rec, sourceId, "disabled"));
96
+ continue;
97
+ }
98
+ const seen = new Set();
99
+ for (const receiverId of input.candidates(rec.shape)) {
100
+ if (seen.has(receiverId))
101
+ continue;
102
+ const position = input.positionOf(receiverId);
103
+ if (position === undefined)
104
+ continue;
105
+ if (!shapeContains(rec.shape, position))
106
+ continue;
107
+ if (input.eligible !== undefined && !input.eligible(sourceId, receiverId, rec.payload))
108
+ continue;
109
+ seen.add(receiverId);
110
+ const member = rec.members.get(receiverId);
111
+ if (member === undefined) {
112
+ rec.members.set(receiverId, { sinceRefreshMs: 0 });
113
+ events.push({ kind: "enter", sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload });
114
+ continue;
115
+ }
116
+ if (rec.refreshMs !== undefined && rec.refreshMs > 0) {
117
+ member.sinceRefreshMs += dtMs;
118
+ let ticks = 0;
119
+ while (member.sinceRefreshMs >= rec.refreshMs) {
120
+ member.sinceRefreshMs -= rec.refreshMs;
121
+ ticks += 1;
122
+ }
123
+ if (ticks > 0) {
124
+ events.push({ kind: "refresh", sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload, ticks });
125
+ }
126
+ }
127
+ }
128
+ for (const receiverId of [...rec.members.keys()]) {
129
+ if (seen.has(receiverId))
130
+ continue;
131
+ rec.members.delete(receiverId);
132
+ events.push({ kind: "leave", sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload, reason: "exit" });
133
+ }
134
+ }
135
+ return events;
136
+ },
137
+ members: (sourceId) => [...(sources.get(sourceId)?.members.keys() ?? [])],
138
+ isMember: (sourceId, receiverId) => sources.get(sourceId)?.members.has(receiverId) ?? false,
139
+ memberships() {
140
+ const out = [];
141
+ for (const [sourceId, rec] of sources) {
142
+ for (const receiverId of rec.members.keys()) {
143
+ out.push({ sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload });
144
+ }
145
+ }
146
+ return out;
147
+ },
148
+ membershipsOf(receiverId) {
149
+ const out = [];
150
+ for (const [sourceId, rec] of sources) {
151
+ if (rec.members.has(receiverId)) {
152
+ out.push({ sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload });
153
+ }
154
+ }
155
+ return out;
156
+ },
157
+ clear() {
158
+ const events = [];
159
+ for (const [sourceId, rec] of sources)
160
+ events.push(...leaveAll(rec, sourceId, "cleared"));
161
+ sources.clear();
162
+ return events;
163
+ },
164
+ serialize() {
165
+ const out = { sources: [], memberships: [] };
166
+ for (const [id, rec] of sources) {
167
+ out.sources.push({ id, payload: rec.payload, refreshMs: rec.refreshMs, stackKey: rec.stackKey, enabled: rec.enabled });
168
+ for (const [receiverId, member] of rec.members) {
169
+ out.memberships.push({ sourceId: id, receiverId, sinceRefreshMs: member.sinceRefreshMs });
170
+ }
171
+ }
172
+ return out;
173
+ },
174
+ };
175
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Overlap aggregation for {@link AreaMembership} lists: when several area sources cover the same
3
+ * receiver, a policy decides which memberships actually apply. Genre-agnostic and pure — policies
4
+ * are `(memberships) => memberships` reducers over one receiver's memberships, so the caller stays
5
+ * in control of magnitude and meaning. Pair with `createAreaEffectField().membershipsOf(receiverId)`.
6
+ */
7
+ import type { AreaMembership } from "./areaEffectField.js";
8
+ /** Reduce one receiver's overlapping memberships to the subset that applies under a stacking rule. */
9
+ export type AreaStackPolicy<P> = (memberships: readonly AreaMembership<P>[]) => AreaMembership<P>[];
10
+ /** Read a comparable magnitude from a membership (e.g. buff strength, damage per tick). */
11
+ export type MagnitudeOf<P> = (membership: AreaMembership<P>) => number;
12
+ /**
13
+ * Every overlapping membership applies independently (no deduplication) — the default for hazards,
14
+ * fields, and lights where two sources genuinely stack.
15
+ *
16
+ * @capability area-stack-independent apply every overlapping area membership independently
17
+ */
18
+ export declare function independentStacks<P>(): AreaStackPolicy<P>;
19
+ /**
20
+ * Keep at most one membership per `stackKey`. With `magnitudeOf` the strongest per key wins (ties
21
+ * broken by `sourceId` for determinism); without it the first-seen per key wins. Use for
22
+ * unique-by-key buffs where reapplying the same aura should not stack.
23
+ *
24
+ * @capability area-stack-unique keep one area membership per stack key, strongest wins
25
+ */
26
+ export declare function uniqueByStackKey<P>(magnitudeOf?: MagnitudeOf<P>): AreaStackPolicy<P>;
27
+ /**
28
+ * Keep at most `limit` memberships per `stackKey` (the highest-magnitude ones when `magnitudeOf` is
29
+ * given, else the first-seen). Models capped stacks — e.g. a poison that stacks up to 5 times.
30
+ *
31
+ * @capability area-stack-capped cap area memberships per stack key at a maximum count
32
+ */
33
+ export declare function cappedStacks<P>(limit: number, magnitudeOf?: MagnitudeOf<P>): AreaStackPolicy<P>;
34
+ /**
35
+ * Reduce to the single strongest membership overall (`weakest = false` picks the weakest); ties broken
36
+ * by `sourceId`. Use when only the best or worst overlapping source should apply.
37
+ *
38
+ * @capability area-stack-extremum keep only the strongest or weakest overlapping area membership
39
+ */
40
+ export declare function extremumStack<P>(magnitudeOf: MagnitudeOf<P>, weakest?: boolean): AreaStackPolicy<P>;
41
+ /**
42
+ * Sum a numeric magnitude across memberships — additive aggregation for a total field strength
43
+ * (total damage per tick, total slow). A terminal reducer, not a filter, so it returns the number.
44
+ *
45
+ * @capability area-stack-additive sum a magnitude across overlapping area memberships
46
+ */
47
+ export declare function sumMagnitude<P>(memberships: readonly AreaMembership<P>[], magnitudeOf: MagnitudeOf<P>): number;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Overlap aggregation for {@link AreaMembership} lists: when several area sources cover the same
3
+ * receiver, a policy decides which memberships actually apply. Genre-agnostic and pure — policies
4
+ * are `(memberships) => memberships` reducers over one receiver's memberships, so the caller stays
5
+ * in control of magnitude and meaning. Pair with `createAreaEffectField().membershipsOf(receiverId)`.
6
+ */
7
+ function byMagnitudeDesc(magnitudeOf) {
8
+ return (a, b) => {
9
+ const diff = magnitudeOf(b) - magnitudeOf(a);
10
+ if (diff !== 0)
11
+ return diff;
12
+ return a.sourceId < b.sourceId ? -1 : a.sourceId > b.sourceId ? 1 : 0;
13
+ };
14
+ }
15
+ function groupByStackKey(memberships) {
16
+ const groups = new Map();
17
+ for (const membership of memberships) {
18
+ const list = groups.get(membership.stackKey);
19
+ if (list === undefined)
20
+ groups.set(membership.stackKey, [membership]);
21
+ else
22
+ list.push(membership);
23
+ }
24
+ return groups;
25
+ }
26
+ /**
27
+ * Every overlapping membership applies independently (no deduplication) — the default for hazards,
28
+ * fields, and lights where two sources genuinely stack.
29
+ *
30
+ * @capability area-stack-independent apply every overlapping area membership independently
31
+ */
32
+ export function independentStacks() {
33
+ return (memberships) => [...memberships];
34
+ }
35
+ /**
36
+ * Keep at most one membership per `stackKey`. With `magnitudeOf` the strongest per key wins (ties
37
+ * broken by `sourceId` for determinism); without it the first-seen per key wins. Use for
38
+ * unique-by-key buffs where reapplying the same aura should not stack.
39
+ *
40
+ * @capability area-stack-unique keep one area membership per stack key, strongest wins
41
+ */
42
+ export function uniqueByStackKey(magnitudeOf) {
43
+ return (memberships) => {
44
+ const out = [];
45
+ for (const group of groupByStackKey(memberships).values()) {
46
+ if (magnitudeOf === undefined) {
47
+ out.push(group[0]);
48
+ }
49
+ else {
50
+ out.push([...group].sort(byMagnitudeDesc(magnitudeOf))[0]);
51
+ }
52
+ }
53
+ return out;
54
+ };
55
+ }
56
+ /**
57
+ * Keep at most `limit` memberships per `stackKey` (the highest-magnitude ones when `magnitudeOf` is
58
+ * given, else the first-seen). Models capped stacks — e.g. a poison that stacks up to 5 times.
59
+ *
60
+ * @capability area-stack-capped cap area memberships per stack key at a maximum count
61
+ */
62
+ export function cappedStacks(limit, magnitudeOf) {
63
+ const cap = Math.max(0, Math.floor(limit));
64
+ return (memberships) => {
65
+ const out = [];
66
+ for (const group of groupByStackKey(memberships).values()) {
67
+ const ordered = magnitudeOf === undefined ? group : [...group].sort(byMagnitudeDesc(magnitudeOf));
68
+ for (const membership of ordered.slice(0, cap))
69
+ out.push(membership);
70
+ }
71
+ return out;
72
+ };
73
+ }
74
+ /**
75
+ * Reduce to the single strongest membership overall (`weakest = false` picks the weakest); ties broken
76
+ * by `sourceId`. Use when only the best or worst overlapping source should apply.
77
+ *
78
+ * @capability area-stack-extremum keep only the strongest or weakest overlapping area membership
79
+ */
80
+ export function extremumStack(magnitudeOf, weakest = false) {
81
+ return (memberships) => {
82
+ if (memberships.length === 0)
83
+ return [];
84
+ const ordered = [...memberships].sort(byMagnitudeDesc(magnitudeOf));
85
+ return [weakest ? ordered[ordered.length - 1] : ordered[0]];
86
+ };
87
+ }
88
+ /**
89
+ * Sum a numeric magnitude across memberships — additive aggregation for a total field strength
90
+ * (total damage per tick, total slow). A terminal reducer, not a filter, so it returns the number.
91
+ *
92
+ * @capability area-stack-additive sum a magnitude across overlapping area memberships
93
+ */
94
+ export function sumMagnitude(memberships, magnitudeOf) {
95
+ let total = 0;
96
+ for (const membership of memberships)
97
+ total += magnitudeOf(membership);
98
+ return total;
99
+ }
@@ -1,3 +1,4 @@
1
+ import type { SynthPatch } from "./synth.js";
1
2
  export type AudioBusId = string;
2
3
  export type FalloffCurve = "linear" | "inverse" | "none";
3
4
  export interface AudioFalloffConfig {
@@ -15,8 +16,10 @@ export interface AudioBusDef {
15
16
  }
16
17
  export interface SoundDef {
17
18
  id: string;
18
- /** Playable source — a URL/data URI the shell's Web Audio glue fetches and decodes. */
19
- url: string;
19
+ /** Sample source — a URL/data URI the shell's Web Audio glue fetches and decodes. Provide exactly one of `url` or `synth`. */
20
+ url?: string;
21
+ /** Procedural source — a pure synth patch the shell realises on Web Audio, no file fetch. Provide exactly one of `url` or `synth`. */
22
+ synth?: SynthPatch;
20
23
  bus: AudioBusId;
21
24
  /** Base gain before bus/falloff multipliers. Default 1. */
22
25
  gain?: number;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Named synthesised instrument. Each maps to a voice in the shell's instrument
3
+ * library (`@jgengine/shell/audio/musicVoices`); an unknown name falls back to a
4
+ * plain sine voice so a theme is never silent.
5
+ */
6
+ export type MusicInstrument = "strings" | "flute" | "harp" | "horn" | "choir" | "bell" | "timpani" | "bass" | "stacc" | "pad" | "lute" | "dulcimer" | "frameDrum" | "warDrum" | "reed" | "pipe" | "squareLead" | "woodBlock" | "tinyBell" | "piano" | "shaker" | "brassStab" | "cymSwell" | "oboe";
7
+ /** One scheduled note in a theme, positioned on the loop's quarter-note grid. */
8
+ export interface NoteEvent {
9
+ /** Quarter-note position within the loop (0-based). */
10
+ beat: number;
11
+ /** MIDI note number (60 = middle C). */
12
+ midi: number;
13
+ /** Sounding length in quarter-note beats. */
14
+ dur: number;
15
+ /** Velocity 0..1. */
16
+ vel: number;
17
+ /** Which instrument voice plays it. */
18
+ inst: MusicInstrument;
19
+ }
20
+ /**
21
+ * A through-composed, looping music track. `events` need not be sorted; the
22
+ * director schedules them ahead against a fixed anchor so loops are seamless.
23
+ */
24
+ export interface MusicTheme {
25
+ id: string;
26
+ /** Tempo in beats (quarter notes) per minute. */
27
+ bpm: number;
28
+ /** Loop length in 4/4 bars; the loop is `bars * 4` beats long. */
29
+ bars: number;
30
+ events: readonly NoteEvent[];
31
+ /**
32
+ * Per-theme loudness normalisation multiplied into the crossfade target, so
33
+ * dense and sparse themes sit at the same perceived level. Default 1.
34
+ */
35
+ trim?: number;
36
+ }
37
+ /** A resolved note occurrence: the source note plus its absolute onset in seconds. */
38
+ export interface ScheduledNote {
39
+ event: NoteEvent;
40
+ /** Absolute onset in seconds, on the timeline of the `anchorSec`/window args. */
41
+ when: number;
42
+ }
43
+ /** Standard equal-temperament MIDI-to-frequency (A4 = 440 Hz at MIDI 69). */
44
+ export declare function mtof(midi: number): number;
45
+ /** Loop length of a theme in seconds. */
46
+ export declare function themeLoopSeconds(theme: MusicTheme): number;
47
+ /**
48
+ * Pure lookahead scheduler: every note occurrence of `theme` whose onset falls
49
+ * in the half-open window `(fromSec, toSec]`, given the theme's loop-zero at
50
+ * `anchorSec`. Handles any number of loop wraps, so a director calls it once per
51
+ * tick with a non-overlapping window and never double-schedules a note.
52
+ */
53
+ export declare function notesInWindow(theme: MusicTheme, anchorSec: number, fromSec: number, toSec: number): ScheduledNote[];
@@ -0,0 +1,34 @@
1
+ /** Standard equal-temperament MIDI-to-frequency (A4 = 440 Hz at MIDI 69). */
2
+ export function mtof(midi) {
3
+ return 440 * 2 ** ((midi - 69) / 12);
4
+ }
5
+ /** Loop length of a theme in seconds. */
6
+ export function themeLoopSeconds(theme) {
7
+ return (theme.bars * 4 * 60) / theme.bpm;
8
+ }
9
+ /**
10
+ * Pure lookahead scheduler: every note occurrence of `theme` whose onset falls
11
+ * in the half-open window `(fromSec, toSec]`, given the theme's loop-zero at
12
+ * `anchorSec`. Handles any number of loop wraps, so a director calls it once per
13
+ * tick with a non-overlapping window and never double-schedules a note.
14
+ */
15
+ export function notesInWindow(theme, anchorSec, fromSec, toSec) {
16
+ const loop = themeLoopSeconds(theme);
17
+ if (loop <= 0 || toSec <= fromSec)
18
+ return [];
19
+ const spb = 60 / theme.bpm;
20
+ const out = [];
21
+ for (const event of theme.events) {
22
+ const onset = event.beat * spb;
23
+ let k = Math.max(0, Math.floor((fromSec - anchorSec - onset) / loop));
24
+ for (;;) {
25
+ const when = anchorSec + onset + k * loop;
26
+ if (when > toSec)
27
+ break;
28
+ if (when > fromSec)
29
+ out.push({ event, when });
30
+ k += 1;
31
+ }
32
+ }
33
+ return out;
34
+ }
@@ -0,0 +1,60 @@
1
+ /** Oscillator waveform available to a pitched synth voice. */
2
+ export type SynthWave = "sine" | "square" | "sawtooth" | "triangle";
3
+ /** Biquad filter shape a noise voice is coloured through. */
4
+ export type SynthFilter = "lowpass" | "highpass" | "bandpass";
5
+ /**
6
+ * A pitched oscillator voice: a 12ms linear attack to `gain`, then an
7
+ * exponential decay to silence across `duration`, with an optional
8
+ * exponential pitch slide from `freq` to `slideTo`.
9
+ */
10
+ export interface ToneVoice {
11
+ kind: "tone";
12
+ /** Start frequency in Hz. */
13
+ freq: number;
14
+ /** Total voice length in seconds (the decay spans this). */
15
+ duration: number;
16
+ /** Peak gain before patch/bus scaling. Default 1. */
17
+ gain?: number;
18
+ /** Oscillator waveform. Default "sine". */
19
+ wave?: SynthWave;
20
+ /** Start offset in seconds from the cue trigger. Default 0. */
21
+ delay?: number;
22
+ /** When set, pitch ramps exponentially from `freq` to this Hz across `duration`. */
23
+ slideTo?: number;
24
+ /** Attack ramp in seconds. Default 0.012. */
25
+ attack?: number;
26
+ }
27
+ /**
28
+ * A filtered white-noise burst — impacts, whooshes, breath, crackle. Realised
29
+ * from a shared 1s noise buffer at a randomised playback rate and start offset,
30
+ * decaying exponentially to silence at `duration * decay`.
31
+ */
32
+ export interface NoiseVoice {
33
+ kind: "noise";
34
+ /** Total voice length in seconds. */
35
+ duration: number;
36
+ /** Biquad cutoff/centre in Hz. */
37
+ filterFreq: number;
38
+ /** Peak gain before patch/bus scaling. Default 1. */
39
+ gain?: number;
40
+ /** Filter shape. Default "lowpass". */
41
+ filterType?: SynthFilter;
42
+ /** Fraction of `duration` over which the burst decays to silence. Default 0.9. */
43
+ decay?: number;
44
+ /** Start offset in seconds from the cue trigger. Default 0. */
45
+ delay?: number;
46
+ }
47
+ /** One layered voice of a synth cue. */
48
+ export type SynthVoice = ToneVoice | NoiseVoice;
49
+ /**
50
+ * A procedural sound cue: a set of voices triggered together, each with its own
51
+ * `delay`, summed into one one-shot. Pure serialisable data — the shell realises
52
+ * it on Web Audio, so the same catalog runs headless in tests with no `AudioContext`.
53
+ */
54
+ export interface SynthPatch {
55
+ voices: readonly SynthVoice[];
56
+ /** Overall cue gain multiplier applied to every voice. Default 1. */
57
+ gain?: number;
58
+ }
59
+ /** Total wall-clock length of a patch in seconds — the latest voice end across all voices. */
60
+ export declare function patchDuration(patch: SynthPatch): number;
@@ -0,0 +1,8 @@
1
+ /** Total wall-clock length of a patch in seconds — the latest voice end across all voices. */
2
+ export function patchDuration(patch) {
3
+ let end = 0;
4
+ for (const voice of patch.voices) {
5
+ end = Math.max(end, (voice.delay ?? 0) + voice.duration);
6
+ }
7
+ return end;
8
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Task-first JGEngine authoring surface.
3
+ *
4
+ * Game code should begin here. Domain and runtime deep imports remain available for
5
+ * advanced composition, but this module intentionally exposes common authored
6
+ * concepts without requiring callers to understand the repository layout.
7
+ */
8
+ export { defineGame, type GameDefinition, type GameDefinitionConfig, type GameLoop, type InventoryDeclaration, type PhysicsConfig, type GameServerConfig, } from "./game/defineGame.js";
9
+ export { lootTable, type LootTableDef, type LootEntry, type Drop, } from "./game/lootTable.js";
10
+ export { biomes, voxel, plots, tilemap, flat, environment, terrain, rain, snow, grass, ocean, building, road, type WorldFeature, } from "./world/features.js";
11
+ export { seededRng, seededStreams } from "./random/rng.js";
12
+ export { selectSpawnPoint, type SpawnPointSelectionOptions, type SpawnPointDistanceBias, } from "./ai/spawnPoint.js";
13
+ export { contextVerb } from "./interaction/contextMenu.js";
14
+ export { type ActionCodesMap } from "./input/actionBindings.js";
15
+ export { classifyOwnership, collectOwnershipDiagnostics, auditManifest, ownershipKey, isSceneOwnershipManifest, SCENE_OWNERSHIP_MANIFEST_VERSION, type SceneProvenance, type SceneProvenanceKind, type AuthoredProvenance, type GeneratedProvenance, type RuntimeProvenance, type TransientProvenance, type ProviderCapabilities, type SceneOwnershipDeclaration, type OwnershipDecision, type OwnershipVerdict, type OwnershipDiagnostic, type SceneOwnershipManifest, } from "./scene/sceneOwnership.js";