@jgengine/core 0.18.1 → 0.21.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 (404) hide show
  1. package/CHANGELOG.md +504 -7
  2. package/dist/ai/decisionGraph.d.ts +50 -4
  3. package/dist/ai/decisionGraph.js +159 -23
  4. package/dist/ai/flock.d.ts +1 -1
  5. package/dist/ai/flock.js +7 -4
  6. package/dist/ai/groupAssist.d.ts +10 -0
  7. package/dist/ai/groupAssist.js +11 -0
  8. package/dist/ai/pursuit.d.ts +1 -1
  9. package/dist/ai/pursuit.js +1 -1
  10. package/dist/ai/threat.d.ts +8 -0
  11. package/dist/ai/threat.js +10 -0
  12. package/dist/anim/animGraph.d.ts +43 -1
  13. package/dist/anim/animGraph.js +326 -10
  14. package/dist/anim/boneTexture.d.ts +55 -0
  15. package/dist/anim/boneTexture.js +43 -0
  16. package/dist/anim/footPlacement.d.ts +57 -0
  17. package/dist/anim/footPlacement.js +67 -0
  18. package/dist/anim/locomotionGraph.d.ts +18 -1
  19. package/dist/anim/locomotionGraph.js +42 -3
  20. package/dist/audio/audioFalloff.d.ts +6 -0
  21. package/dist/audio/doppler.d.ts +21 -0
  22. package/dist/audio/doppler.js +32 -0
  23. package/dist/audio/engineLayers.d.ts +83 -0
  24. package/dist/audio/engineLayers.js +115 -0
  25. package/dist/audio/voiceAllocator.d.ts +46 -0
  26. package/dist/audio/voiceAllocator.js +76 -0
  27. package/dist/combat/abilityKit.d.ts +20 -0
  28. package/dist/combat/abilityKit.js +41 -4
  29. package/dist/combat/death.d.ts +11 -3
  30. package/dist/combat/death.js +3 -3
  31. package/dist/combat/magazine.d.ts +9 -0
  32. package/dist/combat/magazine.js +24 -2
  33. package/dist/combat/projectiles.d.ts +94 -2
  34. package/dist/combat/projectiles.js +282 -61
  35. package/dist/combat/regenShield.d.ts +14 -0
  36. package/dist/combat/regenShield.js +23 -7
  37. package/dist/combat/shotOrigin.d.ts +6 -0
  38. package/dist/combat/shotOrigin.js +6 -0
  39. package/dist/combat/weaponFeedback.d.ts +36 -0
  40. package/dist/combat/weaponFeedback.js +42 -0
  41. package/dist/combat/weaponHandling.d.ts +161 -0
  42. package/dist/combat/weaponHandling.js +202 -0
  43. package/dist/combat/weaponPresentation.d.ts +115 -0
  44. package/dist/combat/weaponPresentation.js +96 -0
  45. package/dist/crafting/recipeCatalog.d.ts +16 -0
  46. package/dist/crafting/recipeCatalog.js +55 -0
  47. package/dist/devtools/warnOnce.d.ts +8 -0
  48. package/dist/devtools/warnOnce.js +18 -0
  49. package/dist/economy/auctionBook.d.ts +1 -1
  50. package/dist/economy/auctionBook.js +11 -1
  51. package/dist/economy/listingBook.d.ts +1 -1
  52. package/dist/economy/listingBook.js +11 -1
  53. package/dist/economy/resourceLedger.js +3 -3
  54. package/dist/economy/shopStock.js +7 -6
  55. package/dist/economy/techTree.js +7 -6
  56. package/dist/economy/unlockPoints.js +3 -6
  57. package/dist/editor/commandApply.js +89 -16
  58. package/dist/editor/commands.d.ts +38 -1
  59. package/dist/editor/commands.js +320 -3
  60. package/dist/editor/creatorStorage.d.ts +59 -0
  61. package/dist/editor/creatorStorage.js +164 -0
  62. package/dist/editor/document.d.ts +4 -0
  63. package/dist/editor/document.js +119 -18
  64. package/dist/editor/environment.js +8 -0
  65. package/dist/editor/index.d.ts +2 -0
  66. package/dist/editor/liveSync.d.ts +4 -1
  67. package/dist/editor/liveSync.js +26 -10
  68. package/dist/editor/materialAuthoring.d.ts +14 -0
  69. package/dist/editor/materialAuthoring.js +38 -0
  70. package/dist/editor/modelNodeVisibility.d.ts +11 -0
  71. package/dist/editor/modelNodeVisibility.js +29 -0
  72. package/dist/editor/movementCatalog.d.ts +90 -0
  73. package/dist/editor/movementCatalog.js +144 -0
  74. package/dist/editor/simulation.d.ts +60 -0
  75. package/dist/editor/simulation.js +202 -0
  76. package/dist/editor/staticPrefab.d.ts +17 -0
  77. package/dist/editor/staticPrefab.js +51 -0
  78. package/dist/editor/types.d.ts +15 -0
  79. package/dist/faction/reputation.d.ts +6 -0
  80. package/dist/faction/reputation.js +11 -0
  81. package/dist/game/cameraConfig.d.ts +54 -2
  82. package/dist/game/clipRoles.d.ts +2 -1
  83. package/dist/game/clipRoles.js +7 -3
  84. package/dist/game/contentValidation.d.ts +69 -0
  85. package/dist/game/contentValidation.js +118 -0
  86. package/dist/game/controlGate.d.ts +8 -0
  87. package/dist/game/controlGate.js +43 -6
  88. package/dist/game/defineGame.d.ts +32 -3
  89. package/dist/game/dialogueGraph.d.ts +20 -0
  90. package/dist/game/dialogueGraph.js +107 -0
  91. package/dist/game/events.d.ts +11 -0
  92. package/dist/game/keyValueStore.d.ts +17 -4
  93. package/dist/game/keyValueStore.js +35 -23
  94. package/dist/game/lootModifiers.d.ts +17 -0
  95. package/dist/game/lootModifiers.js +26 -0
  96. package/dist/game/lootTable.d.ts +4 -0
  97. package/dist/game/lootTable.js +16 -0
  98. package/dist/game/narrativeAuthoring.d.ts +67 -0
  99. package/dist/game/narrativeAuthoring.js +122 -0
  100. package/dist/game/playableGame.d.ts +134 -35
  101. package/dist/game/quest.d.ts +15 -0
  102. package/dist/game/quest.js +209 -63
  103. package/dist/game/questCatalog.d.ts +50 -0
  104. package/dist/game/questCatalog.js +205 -0
  105. package/dist/game/saveStore.d.ts +6 -5
  106. package/dist/game/saveStore.js +57 -57
  107. package/dist/game/systemRuntime.d.ts +2 -2
  108. package/dist/game/systemRuntime.js +84 -33
  109. package/dist/game/toasts.d.ts +8 -0
  110. package/dist/game/toasts.js +7 -0
  111. package/dist/game/vfxInstance.d.ts +9 -0
  112. package/dist/game/vfxInstance.js +12 -1
  113. package/dist/game/viewports.d.ts +43 -0
  114. package/dist/game/viewports.js +46 -0
  115. package/dist/game/worldItem.d.ts +5 -1
  116. package/dist/game/worldItem.js +0 -1
  117. package/dist/gameplay.d.ts +3 -0
  118. package/dist/gameplay.js +3 -0
  119. package/dist/input/actionBindings.d.ts +15 -1
  120. package/dist/input/actionBindings.js +14 -3
  121. package/dist/input/actionContexts.d.ts +25 -1
  122. package/dist/input/actionContexts.js +82 -25
  123. package/dist/input/axisInput.d.ts +4 -0
  124. package/dist/input/axisInput.js +4 -0
  125. package/dist/input/axisShaper.d.ts +73 -0
  126. package/dist/input/axisShaper.js +105 -0
  127. package/dist/input/gamepadModel.d.ts +36 -2
  128. package/dist/input/gamepadModel.js +69 -30
  129. package/dist/input/haptics.d.ts +50 -0
  130. package/dist/input/haptics.js +74 -0
  131. package/dist/input/inputBuffer.d.ts +40 -0
  132. package/dist/input/inputBuffer.js +59 -0
  133. package/dist/input/lookChannel.d.ts +10 -0
  134. package/dist/input/lookChannel.js +6 -0
  135. package/dist/input/pointer.d.ts +2 -0
  136. package/dist/input/pointer.js +4 -0
  137. package/dist/interaction/promptRegistry.d.ts +5 -4
  138. package/dist/interaction/promptRegistry.js +8 -2
  139. package/dist/inventory/inventoryModel.js +9 -6
  140. package/dist/inventory/shapedGrid.d.ts +48 -9
  141. package/dist/inventory/shapedGrid.js +69 -10
  142. package/dist/item/affix.d.ts +6 -0
  143. package/dist/item/affix.js +6 -0
  144. package/dist/item/durability.js +4 -0
  145. package/dist/item/itemInstanceRegistry.d.ts +32 -1
  146. package/dist/item/itemInstanceRegistry.js +111 -7
  147. package/dist/item/itemgen.d.ts +1 -1
  148. package/dist/item/itemgen.js +1 -1
  149. package/dist/item/modularItem.js +7 -1
  150. package/dist/material/appearanceSignals.d.ts +53 -0
  151. package/dist/material/appearanceSignals.js +47 -0
  152. package/dist/material/hairCards.d.ts +47 -0
  153. package/dist/material/hairCards.js +136 -0
  154. package/dist/material/materialAsset.d.ts +162 -0
  155. package/dist/material/materialAsset.js +382 -0
  156. package/dist/meta/changelog.d.ts +1 -1
  157. package/dist/meta/changelog.js +444 -1
  158. package/dist/movement/characterController.d.ts +5 -2
  159. package/dist/movement/characterController.js +50 -23
  160. package/dist/movement/freeFlight.d.ts +2 -2
  161. package/dist/movement/freeFlight.js +3 -3
  162. package/dist/movement/glideModel.d.ts +3 -0
  163. package/dist/movement/glideModel.js +6 -0
  164. package/dist/movement/grappleSwing.d.ts +2 -0
  165. package/dist/movement/grappleSwing.js +5 -1
  166. package/dist/movement/movementModel.d.ts +63 -1
  167. package/dist/movement/movementModel.js +136 -26
  168. package/dist/movement/movementProbe.d.ts +51 -0
  169. package/dist/movement/movementProbe.js +119 -0
  170. package/dist/movement/playerMovement.d.ts +48 -2
  171. package/dist/movement/playerMovement.js +493 -87
  172. package/dist/movement/poseState.d.ts +2 -0
  173. package/dist/movement/poseState.js +29 -1
  174. package/dist/movement/solidObstacles.d.ts +11 -1
  175. package/dist/movement/solidObstacles.js +48 -3
  176. package/dist/movement/terrainGrade.d.ts +13 -0
  177. package/dist/movement/terrainGrade.js +33 -0
  178. package/dist/movement/voxelController.d.ts +2 -2
  179. package/dist/movement/voxelController.js +10 -10
  180. package/dist/nav/navFromEnvironment.d.ts +9 -3
  181. package/dist/nav/navFromEnvironment.js +18 -12
  182. package/dist/nav/navGrid.d.ts +19 -1
  183. package/dist/nav/navGrid.js +26 -10
  184. package/dist/nav/navMesh.d.ts +43 -2
  185. package/dist/nav/navMesh.js +534 -128
  186. package/dist/nav/solidRoute.d.ts +50 -0
  187. package/dist/nav/solidRoute.js +144 -0
  188. package/dist/physics/aircraftDynamics.d.ts +390 -0
  189. package/dist/physics/aircraftDynamics.js +704 -0
  190. package/dist/physics/ballisticSweep.d.ts +10 -3
  191. package/dist/physics/ballisticSweep.js +53 -29
  192. package/dist/physics/boatDynamics.d.ts +116 -0
  193. package/dist/physics/boatDynamics.js +160 -0
  194. package/dist/physics/drivableVehicle.d.ts +22 -8
  195. package/dist/physics/drivableVehicle.js +4 -2
  196. package/dist/physics/flightDynamics.d.ts +21 -4
  197. package/dist/physics/flightDynamics.js +28 -5
  198. package/dist/physics/forceVolume.d.ts +41 -0
  199. package/dist/physics/forceVolume.js +88 -0
  200. package/dist/physics/handlingProbe.d.ts +249 -0
  201. package/dist/physics/handlingProbe.js +606 -0
  202. package/dist/physics/kinematicVehicle.d.ts +40 -5
  203. package/dist/physics/kinematicVehicle.js +17 -2
  204. package/dist/physics/physicsBackend.d.ts +12 -0
  205. package/dist/physics/physicsBackendConformance.js +34 -0
  206. package/dist/physics/physicsWorldBackend.d.ts +1 -0
  207. package/dist/physics/physicsWorldBackend.js +52 -3
  208. package/dist/physics/spatialGrid.d.ts +1 -1
  209. package/dist/physics/spatialGrid.js +8 -9
  210. package/dist/physics/vehicleBackendLink.d.ts +49 -0
  211. package/dist/physics/vehicleBackendLink.js +102 -0
  212. package/dist/physics/vehicleDynamics.d.ts +375 -0
  213. package/dist/physics/vehicleDynamics.js +737 -0
  214. package/dist/physics/vehicleObstacles.d.ts +3 -2
  215. package/dist/physics/vehicleObstacles.js +29 -5
  216. package/dist/physics/worldColliders.d.ts +1 -1
  217. package/dist/physics/worldColliders.js +35 -3
  218. package/dist/puzzle/cellGrid.d.ts +15 -9
  219. package/dist/puzzle/cellGrid.js +13 -9
  220. package/dist/render/lookPreset.d.ts +9 -2
  221. package/dist/render/lookPreset.js +29 -2
  222. package/dist/render/postProcessing.d.ts +30 -0
  223. package/dist/render/postProcessing.js +1 -1
  224. package/dist/runtime/cameraDirector.d.ts +54 -3
  225. package/dist/runtime/cameraDirector.js +187 -0
  226. package/dist/runtime/commandDispatch.d.ts +14 -0
  227. package/dist/runtime/commandDispatch.js +19 -0
  228. package/dist/runtime/commandInput.d.ts +37 -0
  229. package/dist/runtime/commandInput.js +58 -0
  230. package/dist/runtime/commandRunner.d.ts +27 -0
  231. package/dist/runtime/commandRunner.js +31 -3
  232. package/dist/runtime/context/combat.d.ts +12 -4
  233. package/dist/runtime/context/combat.js +179 -11
  234. package/dist/runtime/context/deathLoot.d.ts +11 -8
  235. package/dist/runtime/context/deathLoot.js +17 -16
  236. package/dist/runtime/context/scene.d.ts +2 -0
  237. package/dist/runtime/context/scene.js +13 -21
  238. package/dist/runtime/descriptors/baseline.js +34 -3
  239. package/dist/runtime/descriptors/features.d.ts +2 -1
  240. package/dist/runtime/descriptors/features.js +18 -0
  241. package/dist/runtime/gameContext.js +86 -13
  242. package/dist/runtime/gameContextTypes.d.ts +33 -3
  243. package/dist/runtime/gameRuntime.d.ts +3 -1
  244. package/dist/runtime/gameRuntime.js +4 -0
  245. package/dist/runtime/headlessRunner.d.ts +3 -1
  246. package/dist/runtime/headlessRunner.js +11 -11
  247. package/dist/runtime/hostedGameRunner.d.ts +24 -1
  248. package/dist/runtime/hostedGameRunner.js +156 -10
  249. package/dist/runtime/hostedWorldSession.d.ts +17 -5
  250. package/dist/runtime/hostedWorldSession.js +154 -16
  251. package/dist/runtime/hostedWorldStore.d.ts +2 -2
  252. package/dist/runtime/inputRecorder.d.ts +1 -1
  253. package/dist/runtime/inputRecorder.js +21 -1
  254. package/dist/runtime/inputSnapshot.d.ts +22 -4
  255. package/dist/runtime/inputSnapshot.js +41 -3
  256. package/dist/runtime/localPlayers.d.ts +73 -0
  257. package/dist/runtime/localPlayers.js +119 -0
  258. package/dist/runtime/runtimeSave.d.ts +10 -6
  259. package/dist/runtime/runtimeSave.js +11 -5
  260. package/dist/runtime/simContext.d.ts +8 -3
  261. package/dist/runtime/simContext.js +7 -3
  262. package/dist/runtime/simSnapshot.js +2 -0
  263. package/dist/runtime/transport.d.ts +9 -0
  264. package/dist/runtime/transport.js +7 -1
  265. package/dist/runtime/worldReplication.d.ts +2 -0
  266. package/dist/runtime/worldReplication.js +1 -1
  267. package/dist/scene/assetCatalog.d.ts +2 -0
  268. package/dist/scene/behaviorRuntime.d.ts +38 -7
  269. package/dist/scene/behaviorRuntime.js +293 -30
  270. package/dist/scene/behaviors.d.ts +35 -2
  271. package/dist/scene/behaviors.js +29 -0
  272. package/dist/scene/entityStore.d.ts +14 -3
  273. package/dist/scene/entityStore.js +45 -9
  274. package/dist/scene/mount.d.ts +9 -0
  275. package/dist/scene/mount.js +35 -0
  276. package/dist/scene/possession.d.ts +2 -0
  277. package/dist/scene/possession.js +21 -1
  278. package/dist/scene/sceneKinds.d.ts +9 -0
  279. package/dist/scene/sceneRaycast.d.ts +7 -0
  280. package/dist/scene/sceneRaycast.js +55 -0
  281. package/dist/scene/spatial.d.ts +20 -1
  282. package/dist/scene/spatial.js +94 -2
  283. package/dist/scene/vehicleSeat.d.ts +41 -3
  284. package/dist/scene/vehicleSeat.js +94 -3
  285. package/dist/sensor/concealment.d.ts +6 -0
  286. package/dist/sensor/concealment.js +8 -0
  287. package/dist/sensor/freezeMonitor.d.ts +6 -0
  288. package/dist/sensor/freezeMonitor.js +8 -0
  289. package/dist/sensor/perception.d.ts +11 -1
  290. package/dist/sensor/perception.js +57 -10
  291. package/dist/sensor/recordingBuffer.d.ts +3 -0
  292. package/dist/sensor/recordingBuffer.js +8 -0
  293. package/dist/session/roundState.d.ts +4 -0
  294. package/dist/session/roundState.js +11 -0
  295. package/dist/settings/frameRateLimit.d.ts +16 -0
  296. package/dist/settings/frameRateLimit.js +37 -0
  297. package/dist/settings/graphicsProfile.d.ts +2 -0
  298. package/dist/settings/graphicsProfile.js +12 -0
  299. package/dist/settings/graphicsSettings.d.ts +40 -0
  300. package/dist/settings/graphicsSettings.js +81 -0
  301. package/dist/settings/settingsModel.d.ts +9 -1
  302. package/dist/settings/settingsModel.js +10 -0
  303. package/dist/stats/accumulatorMeter.d.ts +10 -0
  304. package/dist/stats/accumulatorMeter.js +6 -0
  305. package/dist/stats/eventMeter.d.ts +10 -3
  306. package/dist/stats/eventMeter.js +6 -3
  307. package/dist/store/defineStore.d.ts +3 -1
  308. package/dist/store/defineStore.js +3 -1
  309. package/dist/store/observableKeyedStore.d.ts +1 -1
  310. package/dist/store/observableKeyedStore.js +8 -6
  311. package/dist/time/simClock.d.ts +6 -2
  312. package/dist/time/simClock.js +5 -0
  313. package/dist/vfx/feedbackMixer.d.ts +61 -0
  314. package/dist/vfx/feedbackMixer.js +106 -0
  315. package/dist/vfx/particleDirector.d.ts +58 -6
  316. package/dist/vfx/particleDirector.js +113 -22
  317. package/dist/vfx/particles.d.ts +68 -5
  318. package/dist/vfx/particles.js +284 -32
  319. package/dist/visibility/assetStreaming.d.ts +21 -3
  320. package/dist/visibility/assetStreaming.js +108 -24
  321. package/dist/visibility/settings.d.ts +8 -2
  322. package/dist/visibility/settings.js +3 -0
  323. package/dist/visibility/simulationCulling.d.ts +8 -1
  324. package/dist/visibility/simulationCulling.js +7 -0
  325. package/dist/visibility/spatialIndex.d.ts +21 -0
  326. package/dist/visibility/spatialIndex.js +16 -0
  327. package/dist/visibility/visibilitySystem.js +1 -0
  328. package/dist/work/expedition.d.ts +110 -0
  329. package/dist/work/expedition.js +195 -0
  330. package/dist/work/staffedStation.d.ts +29 -0
  331. package/dist/work/staffedStation.js +27 -0
  332. package/dist/world/authoredAnimation.d.ts +38 -0
  333. package/dist/world/authoredAnimation.js +99 -0
  334. package/dist/world/authoredObjects.d.ts +24 -4
  335. package/dist/world/authoredObjects.js +43 -16
  336. package/dist/world/authoredSimulation.d.ts +74 -0
  337. package/dist/world/authoredSimulation.js +302 -0
  338. package/dist/world/authoredSolids.d.ts +46 -0
  339. package/dist/world/authoredSolids.js +75 -0
  340. package/dist/world/authoredWeather.d.ts +120 -0
  341. package/dist/world/authoredWeather.js +314 -0
  342. package/dist/world/buildingGenerator.js +2 -2
  343. package/dist/world/buildingKit.d.ts +11 -4
  344. package/dist/world/buildingKit.js +21 -8
  345. package/dist/world/buildings.d.ts +34 -2
  346. package/dist/world/buildings.js +11 -1
  347. package/dist/world/cityKind.d.ts +7 -0
  348. package/dist/world/cityKind.js +52 -1
  349. package/dist/world/environmentForces.d.ts +21 -0
  350. package/dist/world/environmentForces.js +42 -0
  351. package/dist/world/features.d.ts +32 -5
  352. package/dist/world/features.js +6 -0
  353. package/dist/world/footprintGrid.d.ts +62 -0
  354. package/dist/world/footprintGrid.js +217 -0
  355. package/dist/world/interiors.d.ts +1 -0
  356. package/dist/world/interiors.js +5 -3
  357. package/dist/world/lod.d.ts +6 -0
  358. package/dist/world/lod.js +8 -0
  359. package/dist/world/pathTerrain.d.ts +1 -1
  360. package/dist/world/terraform.d.ts +9 -1
  361. package/dist/world/terraform.js +53 -18
  362. package/dist/world/walls.d.ts +7 -0
  363. package/dist/world/walls.js +7 -0
  364. package/dist/world/weather.d.ts +17 -0
  365. package/dist/world/weather.js +116 -20
  366. package/dist/world/worldSolids.d.ts +95 -0
  367. package/dist/world/worldSolids.js +351 -0
  368. package/dist/world.d.ts +6 -6
  369. package/dist/world.js +5 -5
  370. package/package.json +1 -1
  371. package/skills/ce-handoff/SKILL.md +2 -2
  372. package/skills/game-design/SKILL.md +2 -2
  373. package/skills/jgengine/SKILL.md +28 -6
  374. package/skills/jgengine/api.md +139 -99
  375. package/skills/jgengine/capabilities.md +28 -0
  376. package/skills/jgengine/recipes/minimal-game.md +10 -2
  377. package/skills/jgengine-combat/SKILL.md +13 -2
  378. package/skills/jgengine-combat/api.md +150 -103
  379. package/skills/jgengine-combat/capabilities.md +29 -1
  380. package/skills/jgengine-combat/recipes/portable-runtime-state.md +60 -6
  381. package/skills/jgengine-combat/recipes/portable-weapon-plumbing.md +37 -3
  382. package/skills/jgengine-combat/recipes/weapon-feel.md +50 -0
  383. package/skills/jgengine-combat/reference.md +24 -2
  384. package/skills/jgengine-gameplay/SKILL.md +63 -0
  385. package/skills/jgengine-gameplay/api.md +583 -463
  386. package/skills/jgengine-gameplay/capabilities.md +92 -0
  387. package/skills/jgengine-gameplay/recipes/device-save-status.md +46 -0
  388. package/skills/jgengine-gameplay/recipes/expeditions.md +108 -0
  389. package/skills/jgengine-gameplay/recipes/narrative-authoring.md +76 -0
  390. package/skills/jgengine-gameplay/recipes/paged-item-storage.md +101 -0
  391. package/skills/jgengine-gameplay/recipes/quest-authoring.md +63 -0
  392. package/skills/jgengine-gameplay/recipes/shaped-inventory.md +50 -0
  393. package/skills/jgengine-gameplay/reference-content-validation.md +74 -0
  394. package/skills/jgengine-gameplay/reference-systems.md +123 -0
  395. package/skills/jgengine-world/SKILL.md +25 -4
  396. package/skills/jgengine-world/api.md +1045 -655
  397. package/skills/jgengine-world/capabilities.md +246 -9
  398. package/skills/jgengine-world/recipes/character-animation.md +62 -0
  399. package/skills/jgengine-world/recipes/controls.md +48 -0
  400. package/skills/jgengine-world/recipes/flight-feel.md +76 -0
  401. package/skills/jgengine-world/recipes/npc-senses.md +55 -0
  402. package/skills/jgengine-world/recipes/vehicle-feel.md +87 -0
  403. package/skills/jgengine-world/reference.md +180 -4
  404. package/skills/jgengine-world/visibility.md +139 -0
@@ -1,60 +1,92 @@
1
+ import { validateEmitterConfig } from "./particles.js";
1
2
  /**
2
3
  * Create the particle intent registry a `GameContext` exposes as `ctx.particles`.
3
4
  * State is data-only and serializable: standing emitters survive `snapshot`/`restore`,
4
5
  * queued bursts are transient. The renderer subscribes, drains bursts, and mirrors
5
6
  * the emitter list — the director never allocates particle pools itself.
6
7
  *
7
- * @capability particle-director game-reachable VFX seam: queue one-shot particle bursts and keyed follow-capable standing emitters as serializable data for the shell to render
8
+ * @capability particle-director named particle start/stop/burst/retune lifecycle, local/world following, render outputs, bounded cosmetic event exchange, and serializable emitter definitions
8
9
  */
9
- export function createParticleDirector() {
10
+ export function createParticleDirector(options = {}) {
10
11
  let nextSeq = 1;
11
12
  let bursts = [];
12
13
  const emitters = new Map();
13
14
  const listeners = new Set();
15
+ let events = [];
16
+ const limit = (n, fallback, cap) => Number.isFinite(n) ? Math.max(0, Math.min(cap, Math.floor(n))) : fallback;
17
+ const maxEmitters = limit(options.maxEmitters, 128, 1024);
18
+ const maxBursts = limit(options.maxBursts, 32, 256);
19
+ const maxEvents = limit(options.maxEvents, 128, 4096);
20
+ function queue(config, count, blending, emitterId, attachOptions) {
21
+ const wanted = Number.isFinite(count) ? Math.min(65536, Math.floor(count)) : 0;
22
+ if (wanted <= 0 || bursts.length >= maxBursts)
23
+ return;
24
+ bursts.push({ seq: nextSeq++, config: structuredClone(config), count: wanted,
25
+ ...(blending === undefined ? {} : { blending }),
26
+ ...(emitterId === undefined ? {} : { emitterId }),
27
+ ...(attachOptions === undefined ? {} : { options: structuredClone(attachOptions) }) });
28
+ notify();
29
+ }
30
+ function setActive(id, active) {
31
+ const current = emitters.get(id);
32
+ if (current === undefined || (current.active ?? true) === active)
33
+ return;
34
+ emitters.set(id, { ...current, active });
35
+ notify();
36
+ }
14
37
  function notify() {
15
38
  for (const listener of listeners)
16
39
  listener();
17
40
  }
18
41
  return {
19
- burst(config, count, blending) {
20
- const wanted = Math.floor(count);
21
- if (wanted <= 0)
22
- return;
23
- bursts.push({ seq: nextSeq++, config, count: wanted, ...(blending === undefined ? {} : { blending }) });
24
- notify();
42
+ burst(config, count, blending, options) {
43
+ queue(config, count, blending, undefined, options);
25
44
  },
26
45
  attach(id, config, options) {
27
- emitters.set(id, {
28
- id,
29
- config,
30
- ...(options?.follow === undefined ? {} : { follow: options.follow }),
31
- ...(options?.offset === undefined ? {} : { offset: options.offset }),
32
- ...(options?.blending === undefined ? {} : { blending: options.blending }),
33
- });
46
+ if (!emitters.has(id) && emitters.size >= maxEmitters)
47
+ throw new RangeError(`Particle emitter capacity ${maxEmitters} exceeded by ${id}`);
48
+ emitters.set(id, { id, config: structuredClone(config), ...structuredClone(options ?? {}) });
34
49
  notify();
35
50
  },
36
- retune(id, patch) {
51
+ retune(id, patch, options) {
37
52
  const current = emitters.get(id);
38
53
  if (current === undefined)
39
54
  return;
40
- emitters.set(id, { ...current, config: { ...current.config, ...patch } });
55
+ emitters.set(id, { ...current, ...structuredClone(options ?? {}), config: { ...current.config, ...structuredClone(patch) } });
41
56
  notify();
42
57
  },
58
+ start(id) { setActive(id, true); },
59
+ stop(id) { setActive(id, false); },
60
+ burstNamed(id, count) {
61
+ const spec = emitters.get(id);
62
+ if (spec === undefined)
63
+ return;
64
+ const { id: _, config, ...options } = spec;
65
+ queue(config, count, spec.blending, id, options);
66
+ },
67
+ reportEvents(id, next) {
68
+ for (let i = 0, n = Math.min(next.length, maxEvents - events.length); i < n; i++) {
69
+ events.push({ ...structuredClone(next[i]), emitterId: id });
70
+ }
71
+ },
72
+ drainEvents() { const drained = events; events = []; return drained; },
43
73
  detach(id) {
44
74
  if (!emitters.delete(id))
45
75
  return;
46
76
  notify();
47
77
  },
48
78
  clear() {
49
- if (emitters.size === 0 && bursts.length === 0)
79
+ if (emitters.size === 0 && bursts.length === 0 && events.length === 0)
50
80
  return;
51
81
  emitters.clear();
52
82
  bursts = [];
83
+ events = [];
53
84
  notify();
54
85
  },
55
86
  emitters() {
56
87
  return Array.from(emitters.values());
57
88
  },
89
+ limits() { return { maxEmitters, maxBursts, maxEvents }; },
58
90
  drainBursts() {
59
91
  if (bursts.length === 0)
60
92
  return [];
@@ -67,15 +99,74 @@ export function createParticleDirector() {
67
99
  return () => listeners.delete(listener);
68
100
  },
69
101
  snapshot() {
70
- return { nextSeq, emitters: Array.from(emitters.values()) };
102
+ return { nextSeq, emitters: structuredClone(Array.from(emitters.values())) };
71
103
  },
72
104
  restore(state) {
73
- nextSeq = state.nextSeq;
105
+ nextSeq = Math.max(1, Number.isFinite(state.nextSeq) ? Math.floor(state.nextSeq) : 1);
74
106
  bursts = [];
75
107
  emitters.clear();
76
- for (const spec of state.emitters)
77
- emitters.set(spec.id, spec);
108
+ events = [];
109
+ for (const spec of state.emitters.slice(0, maxEmitters))
110
+ emitters.set(spec.id, structuredClone(spec));
78
111
  notify();
79
112
  },
80
113
  };
81
114
  }
115
+ /**
116
+ * Validate serializable binding, output, and bounded collision-child descriptors.
117
+ * @capability particle-binding-validation validate named particle follow spaces, render outputs, environment influence, and bounded collision child effects
118
+ */
119
+ export function validateParticleAttachOptions(value) {
120
+ if (value === null || typeof value !== "object" || Array.isArray(value))
121
+ return ["particle options must be an object"];
122
+ const options = value;
123
+ const errors = [];
124
+ if (options.follow !== undefined && typeof options.follow !== "string")
125
+ errors.push("follow must be an entity id");
126
+ if (options.offset !== undefined && (!Array.isArray(options.offset) || options.offset.length !== 3 || options.offset.some((v) => typeof v !== "number" || !Number.isFinite(v))))
127
+ errors.push("offset must contain three finite numbers");
128
+ if (options.space !== undefined && options.space !== "world" && options.space !== "local")
129
+ errors.push("space must be world or local");
130
+ if (options.active !== undefined && typeof options.active !== "boolean")
131
+ errors.push("active must be boolean");
132
+ const output = (render, blending, prefix) => {
133
+ if (blending !== undefined && blending !== "normal" && blending !== "additive")
134
+ errors.push(`${prefix}blending must be normal or additive`);
135
+ if (render === undefined)
136
+ return;
137
+ if (render === null || typeof render !== "object" || Array.isArray(render)) {
138
+ errors.push(`${prefix}render must be an output descriptor`);
139
+ return;
140
+ }
141
+ const hint = render;
142
+ if (!["point", "streak", "flake", "flame", "smoke", "ribbon", "ripple"].includes(hint.shape))
143
+ errors.push(`${prefix}render.shape is unsupported`);
144
+ if (hint.stretch !== undefined && (typeof hint.stretch !== "number" || !Number.isFinite(hint.stretch) || hint.stretch < 0))
145
+ errors.push(`${prefix}render.stretch must be finite and nonnegative`);
146
+ };
147
+ output(options.render, options.blending, "");
148
+ if (options.environment !== undefined) {
149
+ const influence = options.environment;
150
+ if (influence === null || typeof influence !== "object" || Array.isArray(influence))
151
+ errors.push("environment must be an influence descriptor");
152
+ else {
153
+ for (const name of ["windResponse", "maxAcceleration"])
154
+ if (influence[name] !== undefined && (typeof influence[name] !== "number" || !Number.isFinite(influence[name]) || influence[name] < 0 || influence[name] > 1e12))
155
+ errors.push(`environment.${name} must be finite in 0..1e12`);
156
+ if (influence.mask !== undefined && (typeof influence.mask !== "number" || !Number.isInteger(influence.mask) || influence.mask < 0 || influence.mask > 0xffffffff))
157
+ errors.push("environment.mask must be an unsigned 32-bit integer");
158
+ }
159
+ }
160
+ if (options.collisionEffect !== undefined) {
161
+ const child = options.collisionEffect;
162
+ if (child === null || typeof child !== "object" || Array.isArray(child))
163
+ errors.push("collisionEffect must be a child effect descriptor");
164
+ else {
165
+ errors.push(...validateEmitterConfig(child.config).map((error) => `collisionEffect.config.${error}`));
166
+ if (typeof child.count !== "number" || !Number.isInteger(child.count) || child.count < 1 || child.count > 65536)
167
+ errors.push("collisionEffect.count must be an integer in [1, 65536]");
168
+ output(child.render, child.blending, "collisionEffect.");
169
+ }
170
+ }
171
+ return errors;
172
+ }
@@ -1,3 +1,4 @@
1
+ import { type ForceFieldConfig } from "../physics/forceVolume.js";
1
2
  /** A 3D vector `[x, y, z]`. */
2
3
  export type Vec3 = readonly [number, number, number];
3
4
  /** A `[min, max]` range a spawned particle draws uniformly from. */
@@ -10,6 +11,41 @@ export interface Curve {
10
11
  start: number;
11
12
  end: number;
12
13
  }
14
+ /** Serializable spawn volume in emitter coordinates; cone widens from its base along +Y. */
15
+ export interface ParticleSpawnShape {
16
+ kind: "disc" | "sphere" | "cone";
17
+ radius: number;
18
+ height?: number;
19
+ /** Spawn on the outer surface instead of filling the volume. */
20
+ surface?: boolean;
21
+ }
22
+ /** Bounded particle contact policy; a query adapter can replace the fallback horizontal plane. */
23
+ export interface ParticleCollisionConfig {
24
+ planeY?: number;
25
+ response?: "kill" | "bounce";
26
+ restitution?: number;
27
+ maxQueries?: number;
28
+ maxEvents?: number;
29
+ }
30
+ /** One contact from an injected scene query, in simulation coordinates. */
31
+ export interface ParticleCollisionHit {
32
+ position: Vec3;
33
+ normal: Vec3;
34
+ }
35
+ /** Presentation events never authorize gameplay damage or physical impulses. */
36
+ export interface ParticleEvent {
37
+ type: "collision" | "death";
38
+ particleId: number;
39
+ position: Vec3;
40
+ velocity: Vec3;
41
+ normal?: Vec3;
42
+ }
43
+ /** Optional geometry adapter; queries are capped independently of rendering. */
44
+ export interface ParticleSystemOptions {
45
+ collision?: (from: Vec3, to: Vec3) => ParticleCollisionHit | null;
46
+ /** External cosmetic acceleration; return `out` to reuse its allocation. */
47
+ acceleration?: (position: Vec3, velocity: Vec3, out: [number, number, number]) => Vec3;
48
+ }
13
49
  /**
14
50
  * A particle emitter: how particles spawn and how each one evolves over its life.
15
51
  * Every field is data — no functions — so an emitter is fully serializable and an
@@ -24,6 +60,7 @@ export interface EmitterConfig {
24
60
  position?: Vec3;
25
61
  /** Half-extents of a box the spawn point is jittered within. Default `[0, 0, 0]`. */
26
62
  spawnJitter?: Vec3;
63
+ spawnShape?: ParticleSpawnShape;
27
64
  /** Particle lifetime in seconds. Default `{ min: 1, max: 1 }`. */
28
65
  lifetime?: Range;
29
66
  /** Initial speed along the emit direction, in units/second. Default `{ min: 1, max: 1 }`. */
@@ -44,8 +81,13 @@ export interface EmitterConfig {
44
81
  colorEnd?: number;
45
82
  /** Opacity over life, each `0..1`. Default `{ start: 1, end: 0 }` (fade out). */
46
83
  alpha?: Curve;
47
- /** Injected clock — unused by the sim (it is dt-driven) but reserved; determinism comes from `seed`. */
84
+ /** Seed for deterministic births; retuning it resets future randomness. */
48
85
  seed?: string | number;
86
+ /** Shared physical field descriptors, sampled as cosmetic acceleration; at most eight per particle. */
87
+ forces?: readonly ForceFieldConfig[];
88
+ collision?: ParticleCollisionConfig;
89
+ /** Enable bounded death events. Collision events use `collision.maxEvents`. */
90
+ deathEvents?: boolean;
49
91
  }
50
92
  /**
51
93
  * Read-only packed buffers of the live particles, laid out for a renderer to
@@ -62,6 +104,11 @@ export interface ParticleBuffers {
62
104
  colors: Float32Array;
63
105
  /** `count` floats: opacity `0..1` per particle. */
64
106
  alphas: Float32Array;
107
+ /** Stable birth ids, retained through pool compaction. */
108
+ ids: Float64Array;
109
+ /** Packed velocity and prior integration positions for streak/ribbon outputs. */
110
+ velocities: Float32Array;
111
+ previousPositions: Float32Array;
65
112
  }
66
113
  /** Serializable simulation state for save/restore and deterministic replay. */
67
114
  export interface ParticleSnapshot {
@@ -69,6 +116,11 @@ export interface ParticleSnapshot {
69
116
  accumulator: number;
70
117
  count: number;
71
118
  data: number[];
119
+ running?: boolean;
120
+ nextId?: number;
121
+ ids?: number[];
122
+ previousPositions?: number[];
123
+ config?: EmitterConfig;
72
124
  }
73
125
  /** A live, dt-driven particle simulation. */
74
126
  export interface ParticleSystem {
@@ -76,14 +128,20 @@ export interface ParticleSystem {
76
128
  update(dt: number): void;
77
129
  /** Spawn `n` particles immediately (a one-shot puff/explosion), independent of `rate`. */
78
130
  emit(n: number): void;
131
+ /** Resume continuous emission without replacing the live pool. */
132
+ start(): void;
133
+ /** Stop spawning while existing particles continue aging. */
134
+ stop(): void;
135
+ /** Consume bounded presentation collision/death events exactly once. */
136
+ drainEvents(): ParticleEvent[];
79
137
  /** Live particle count. */
80
138
  count(): number;
81
139
  /** The packed buffers for rendering (valid until the next `update`/`emit`). */
82
140
  buffers(): ParticleBuffers;
83
141
  /** Kill all particles and reset the emission accumulator (keeps the seed stream). */
84
142
  clear(): void;
85
- /** Patch the emitter config in place (e.g. move the origin, change the rate). */
86
- configure(patch: Partial<EmitterConfig>): void;
143
+ /** Patch tuning in place; `replace` resets omitted fields to defaults while retaining live particles. */
144
+ configure(patch: Partial<EmitterConfig>, replace?: boolean): void;
87
145
  subscribe(listener: () => void): () => void;
88
146
  snapshot(): ParticleSnapshot;
89
147
  restore(snapshot: ParticleSnapshot): void;
@@ -98,6 +156,11 @@ export interface ParticleSystem {
98
156
  * embers, magic, or confetti. Travel/gameplay stays elsewhere; this owns only
99
157
  * the spawn-integrate-fade lifecycle.
100
158
  *
101
- * @capability particle-system deterministic pooled particle emitter with SoA render buffers, burst/continuous emission, gravity/drag, size/color/alpha-over-life, and serializable state
159
+ * @capability particle-system deterministic pooled particle emitter with spawn volumes, force fields, bounded collision/death events, live tuning, SoA render buffers, and serializable state
160
+ */
161
+ export declare function createParticleSystem(config?: EmitterConfig, options?: ParticleSystemOptions): ParticleSystem;
162
+ /**
163
+ * Validate the serializable spawn/update descriptor before authoring or loading it.
164
+ * @capability particle-emitter-validation validate finite spawn volumes, force fields, lifetimes, appearance curves, and bounded particle collision policies
102
165
  */
103
- export declare function createParticleSystem(config?: EmitterConfig): ParticleSystem;
166
+ export declare function validateEmitterConfig(value: unknown): string[];