@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
@@ -50,6 +50,11 @@ export interface SurfacePaintStore {
50
50
  }
51
51
  /** @internal */
52
52
  export declare function createSurfacePaint(): SurfacePaintStore;
53
+ /** Plain JSON state of a {@link WallDrawTool}: the drawn points and whether the loop is closed. */
54
+ export interface WallDrawToolState {
55
+ points: Vec2[];
56
+ closed: boolean;
57
+ }
53
58
  export interface WallDrawTool {
54
59
  addPoint(point: Vec2, snap?: number): Vec2;
55
60
  undo(): void;
@@ -60,6 +65,8 @@ export interface WallDrawTool {
60
65
  isClosed(): boolean;
61
66
  footprint(): EnclosedFootprint | null;
62
67
  roof(config?: RoofConfig): RoofPlan | null;
68
+ snapshot(): WallDrawToolState;
69
+ restore(next: WallDrawToolState): void;
63
70
  }
64
71
  /** @internal */
65
72
  export declare function createWallDrawTool(config?: {
@@ -220,6 +220,13 @@ export function createWallDrawTool(config = {}) {
220
220
  const fp = this.footprint();
221
221
  return fp === null ? null : autoRoof(fp, roofConfig);
222
222
  },
223
+ snapshot() {
224
+ return { points: pts.map((point) => [point[0], point[1]]), closed };
225
+ },
226
+ restore(next) {
227
+ pts = next.points.map((point) => [point[0], point[1]]);
228
+ closed = next.closed;
229
+ },
223
230
  };
224
231
  }
225
232
  /** @internal */
@@ -48,19 +48,34 @@ export interface FireGridConfig {
48
48
  wind?: WindVector;
49
49
  /** How strongly wind biases downwind vs upwind spread, 0..1. Default 0.6. */
50
50
  windBias?: number;
51
+ /** Hard allocation bound; defaults to 65536 cells. */
52
+ maxCells?: number;
51
53
  }
54
+ /** Live fire ignition, spread, consumption and wind policies; grid geometry stays fixed. */
55
+ export type FireGridTuning = Pick<FireGridConfig, "ignitionThreshold" | "spreadRate" | "burnRate" | "wind" | "windBias">;
52
56
  export interface FireStepOptions {
53
57
  /** Global spread multiplier this step (rain suppression from resolveWeather().spread). Default 1. */
54
58
  spread?: number;
59
+ /** Live wind in metres/second along world X,Z, overriding configured wind this step. */
60
+ wind?: WindVector;
61
+ windAt?: (x: number, z: number) => WindVector;
55
62
  /** Per-cell wetness 0..1 that resists ignition — from an environment field. */
56
63
  wetnessAt?: (col: number, row: number) => number;
64
+ /** Heat removed per second at full wetness; 0 (default) leaves extinction to game policy. */
65
+ extinguishRate?: number;
57
66
  }
58
67
  export interface FireGrid {
59
68
  readonly cols: number;
60
69
  readonly rows: number;
70
+ readonly cellSize: number;
71
+ readonly origin: readonly [number, number];
61
72
  /** Advance the cellular propagation by game-time `dt`. */
62
73
  step(dt: number, options?: FireStepOptions): void;
63
74
  igniteCell(col: number, row: number): void;
75
+ /** Cool a burning cell to unburnt without replacing its remaining fuel. */
76
+ extinguishCell(col: number, row: number): boolean;
77
+ /** Extinguish the cell under a world position; false outside the grid or when not burning. */
78
+ extinguish(x: number, z: number): boolean;
64
79
  /** Ignite the cell under a world position; no-op if outside the grid. */
65
80
  ignite(x: number, z: number): boolean;
66
81
  cell(col: number, row: number): FireCell;
@@ -73,5 +88,7 @@ export interface FireGrid {
73
88
  readonly burning: number;
74
89
  /** Flat snapshot (row-major) for rendering. */
75
90
  snapshot(): FireCell[];
91
+ restore(state: readonly FireCell[]): void;
92
+ retune(tuning: FireGridTuning): void;
76
93
  }
77
94
  export declare function createFireGrid(config: FireGridConfig): FireGrid;
@@ -29,39 +29,66 @@ const NEIGHBOURS = [
29
29
  ];
30
30
  export function createFireGrid(config) {
31
31
  const { cols, rows, cellSize } = config;
32
- if (cols <= 0 || rows <= 0)
33
- throw new Error("createFireGrid: cols/rows must be positive");
32
+ const maxCells = config.maxCells ?? 65_536;
33
+ if (!Number.isSafeInteger(maxCells) || maxCells < 1 || maxCells > 1_048_576)
34
+ throw new Error("createFireGrid: maxCells must be an integer in 1..1048576");
35
+ if (!Number.isSafeInteger(cols) || !Number.isSafeInteger(rows) || cols <= 0 || rows <= 0 || cols * rows > maxCells)
36
+ throw new Error("createFireGrid: cols/rows must be positive integers within maxCells");
37
+ if (!Number.isFinite(cellSize) || cellSize <= 0)
38
+ throw new Error("createFireGrid: cellSize must be finite and positive");
34
39
  const originX = config.origin?.[0] ?? 0;
35
40
  const originZ = config.origin?.[1] ?? 0;
36
- const ignitionThreshold = config.ignitionThreshold ?? 1;
37
- const spreadRate = config.spreadRate ?? 0.6;
38
- const burnRate = config.burnRate ?? 0.25;
39
- const windBias = Math.max(0, Math.min(1, config.windBias ?? 0.6));
40
- const wind = config.wind;
41
- const windLen = wind === undefined ? 0 : Math.hypot(wind[0], wind[1]);
42
- const windX = windLen > 0 ? wind[0] / windLen : 0;
43
- const windZ = windLen > 0 ? wind[1] / windLen : 0;
41
+ if (!Number.isFinite(originX) || !Number.isFinite(originZ))
42
+ throw new Error("createFireGrid: origin must be finite");
43
+ let ignitionThreshold = 1;
44
+ let spreadRate = 0.6;
45
+ let burnRate = 0.25;
46
+ let windBias = 0.6;
47
+ let wind;
48
+ function retune(tuning) {
49
+ for (const key of ["ignitionThreshold", "spreadRate", "burnRate", "windBias"]) {
50
+ const value = tuning[key];
51
+ if (value !== undefined && (!Number.isFinite(value) || value < 0 || (key === "windBias" && value > 1)))
52
+ throw new Error(`fire ${key} is invalid`);
53
+ }
54
+ if (tuning.wind !== undefined && (!Number.isFinite(tuning.wind[0]) || !Number.isFinite(tuning.wind[1])))
55
+ throw new Error("fire wind must be finite");
56
+ ignitionThreshold = tuning.ignitionThreshold ?? ignitionThreshold;
57
+ spreadRate = tuning.spreadRate ?? spreadRate;
58
+ burnRate = tuning.burnRate ?? burnRate;
59
+ windBias = tuning.windBias ?? windBias;
60
+ if (tuning.wind !== undefined)
61
+ wind = [tuning.wind[0], tuning.wind[1]];
62
+ }
63
+ retune(config);
44
64
  const cells = new Array(cols * rows);
45
65
  for (let row = 0; row < rows; row += 1) {
46
66
  for (let col = 0; col < cols; col += 1) {
47
67
  const fuel = config.fuelAt?.(col, row) ?? 1;
68
+ if (!Number.isFinite(fuel) || fuel < 0)
69
+ throw new Error("fire initial fuel must be finite and nonnegative");
48
70
  cells[row * cols + col] = { fuel: Math.max(0, fuel), heat: 0, state: "unburnt" };
49
71
  }
50
72
  }
51
73
  const index = (col, row) => row * cols + col;
52
- const inBounds = (col, row) => col >= 0 && col < cols && row >= 0 && row < rows;
74
+ const inBounds = (col, row) => Number.isInteger(col) && Number.isInteger(row) && col >= 0 && col < cols && row >= 0 && row < rows;
53
75
  const cellCoord = (x, z) => {
54
76
  const col = Math.round((x - originX) / cellSize);
55
77
  const row = Math.round((z - originZ) / cellSize);
56
78
  return inBounds(col, row) ? { col, row } : null;
57
79
  };
58
- const directionalWeight = (dx, dz) => {
80
+ const directionalWeight = (dx, dz, vector) => {
81
+ if (vector === undefined)
82
+ return 1;
83
+ const windLen = Math.hypot(vector[0], vector[1]);
59
84
  if (windLen === 0)
60
85
  return 1;
61
86
  const len = Math.hypot(dx, dz) || 1;
62
- const alignment = (dx / len) * windX + (dz / len) * windZ;
87
+ const alignment = (dx / len) * vector[0] / windLen + (dz / len) * vector[1] / windLen;
63
88
  return 1 + windBias * alignment;
64
89
  };
90
+ const addedHeat = new Float64Array(cols * rows);
91
+ const wetness = new Float64Array(cols * rows);
65
92
  let burning = 0;
66
93
  for (const cell of cells)
67
94
  if (cell.state === "burning")
@@ -77,20 +104,71 @@ export function createFireGrid(config) {
77
104
  cell.state = "burning";
78
105
  cell.heat = Math.max(cell.heat, ignitionThreshold);
79
106
  };
107
+ const extinguishCell = (col, row) => {
108
+ if (!inBounds(col, row))
109
+ return false;
110
+ const cell = cells[index(col, row)];
111
+ if (cell.state !== "burning")
112
+ return false;
113
+ cell.state = "unburnt";
114
+ cell.heat = 0;
115
+ burning -= 1;
116
+ return true;
117
+ };
80
118
  return {
81
119
  cols,
82
120
  rows,
121
+ cellSize,
122
+ origin: [originX, originZ],
123
+ retune,
124
+ restore(state) {
125
+ if (state.length !== cells.length)
126
+ throw new Error("fire snapshot dimensions do not match");
127
+ const next = state.map((cell) => {
128
+ if (!Number.isFinite(cell.fuel) || cell.fuel < 0 || !Number.isFinite(cell.heat) || cell.heat < 0 || !["unburnt", "burning", "burnt"].includes(cell.state) || (cell.state === "burning" && cell.fuel <= 0) || (cell.state === "burnt" && (cell.fuel !== 0 || cell.heat !== 0)))
129
+ throw new Error("invalid fire snapshot cell");
130
+ return { ...cell };
131
+ });
132
+ burning = 0;
133
+ for (let i = 0; i < cells.length; i += 1) {
134
+ cells[i] = next[i];
135
+ if (cells[i].state === "burning")
136
+ burning += 1;
137
+ }
138
+ },
83
139
  step(dt, options) {
84
- if (dt <= 0)
140
+ if (!Number.isFinite(dt) || dt < 0)
141
+ throw new Error("fire dt must be finite and nonnegative");
142
+ if (dt === 0)
85
143
  return;
86
144
  const globalSpread = options?.spread ?? 1;
145
+ if (!Number.isFinite(globalSpread) || globalSpread < 0)
146
+ throw new Error("fire spread multiplier must be finite and nonnegative");
87
147
  const wetnessAt = options?.wetnessAt;
88
- const addedHeat = new Float64Array(cols * rows);
148
+ const extinguishRate = options?.extinguishRate ?? 0;
149
+ if (!Number.isFinite(extinguishRate) || extinguishRate < 0)
150
+ throw new Error("fire extinguishRate must be finite and nonnegative");
151
+ const resolveWetness = (col, row) => {
152
+ const value = wetnessAt?.(col, row) ?? 0;
153
+ if (!Number.isFinite(value))
154
+ throw new Error("fire wetness must be finite");
155
+ return Math.max(0, Math.min(1, value));
156
+ };
157
+ addedHeat.fill(0);
158
+ wetness.fill(0);
89
159
  for (let row = 0; row < rows; row += 1) {
90
160
  for (let col = 0; col < cols; col += 1) {
91
161
  const cell = cells[index(col, row)];
92
162
  if (cell.state !== "burning")
93
163
  continue;
164
+ const vector = options?.windAt?.(originX + col * cellSize, originZ + row * cellSize) ?? options?.wind ?? wind;
165
+ if (vector !== undefined && (!Number.isFinite(vector[0]) || !Number.isFinite(vector[1])))
166
+ throw new Error("fire step wind must be finite");
167
+ const i = index(col, row);
168
+ if (extinguishRate > 0)
169
+ wetness[i] = resolveWetness(col, row);
170
+ const coolingRate = extinguishRate * wetness[i];
171
+ const burningDt = Math.min(dt, burnRate === 0 ? Infinity : cell.fuel / burnRate, coolingRate === 0 ? Infinity : cell.heat / coolingRate);
94
172
  for (const [dx, dz] of NEIGHBOURS) {
95
173
  const nc = col + dx;
96
174
  const nr = row + dz;
@@ -100,7 +178,7 @@ export function createFireGrid(config) {
100
178
  if (neighbour.state === "burnt" || neighbour.fuel <= 0)
101
179
  continue;
102
180
  addedHeat[index(nc, nr)] +=
103
- spreadRate * globalSpread * directionalWeight(dx, dz) * dt;
181
+ spreadRate * globalSpread * directionalWeight(dx, dz, vector) * burningDt;
104
182
  }
105
183
  }
106
184
  }
@@ -108,19 +186,32 @@ export function createFireGrid(config) {
108
186
  for (let col = 0; col < cols; col += 1) {
109
187
  const i = index(col, row);
110
188
  const cell = cells[i];
189
+ if (cell.state === "unburnt" && (addedHeat[i] > 0 || (extinguishRate > 0 && cell.heat > 0)))
190
+ wetness[i] = resolveWetness(col, row);
191
+ }
192
+ }
193
+ for (let row = 0; row < rows; row += 1) {
194
+ for (let col = 0; col < cols; col += 1) {
195
+ const i = index(col, row);
196
+ const cell = cells[i];
197
+ const coolingRate = extinguishRate * wetness[i];
111
198
  if (cell.state === "burning") {
112
- cell.fuel = Math.max(0, cell.fuel - burnRate * dt);
199
+ const burningDt = Math.min(dt, coolingRate === 0 ? Infinity : cell.heat / coolingRate);
200
+ cell.fuel = Math.max(0, cell.fuel - burnRate * burningDt);
201
+ cell.heat = Math.max(0, cell.heat - coolingRate * dt);
113
202
  if (cell.fuel <= 0) {
114
203
  cell.state = "burnt";
115
204
  cell.heat = 0;
116
205
  burning -= 1;
117
206
  }
207
+ else if (coolingRate > 0 && cell.heat <= 0) {
208
+ extinguishCell(col, row);
209
+ }
118
210
  continue;
119
211
  }
120
- if (cell.state !== "unburnt" || addedHeat[i] === 0)
212
+ if (cell.state !== "unburnt" || (addedHeat[i] === 0 && coolingRate === 0))
121
213
  continue;
122
- const resist = wetnessAt === undefined ? 0 : Math.max(0, Math.min(1, wetnessAt(col, row)));
123
- cell.heat += addedHeat[i] * (1 - resist);
214
+ cell.heat = Math.max(0, cell.heat + addedHeat[i] * (1 - wetness[i]) - coolingRate * dt);
124
215
  if (cell.heat >= ignitionThreshold && cell.fuel > 0) {
125
216
  cell.state = "burning";
126
217
  burning += 1;
@@ -129,6 +220,11 @@ export function createFireGrid(config) {
129
220
  }
130
221
  },
131
222
  igniteCell,
223
+ extinguishCell,
224
+ extinguish(x, z) {
225
+ const coord = cellCoord(x, z);
226
+ return coord !== null && extinguishCell(coord.col, coord.row);
227
+ },
132
228
  ignite(x, z) {
133
229
  const coord = cellCoord(x, z);
134
230
  if (coord === null)
@@ -0,0 +1,95 @@
1
+ import type { GeneratedBuilding } from "./buildings.js";
2
+ import type { EnvironmentWorldFeature } from "./features.js";
3
+ import type { Aabb } from "./geometry.js";
4
+ import type { WallSegment } from "./walls.js";
5
+ /** One solid box in world space: the collision half of generated or authored world geometry. */
6
+ export interface WorldSolid {
7
+ center: readonly [number, number, number];
8
+ halfExtents: readonly [number, number, number];
9
+ /** Yaw about `center`, radians, in the engine's `rotationY` convention. Default `0`. */
10
+ rotationY?: number;
11
+ }
12
+ /** Serializable contents of a {@link WorldSolids}: every layer's solids by layer id. */
13
+ export interface WorldSolidsState {
14
+ layers: Record<string, readonly WorldSolid[]>;
15
+ }
16
+ /** Caller-owned work counters, reset by each world-solid ray candidate query. */
17
+ export interface WorldSolidRayWork {
18
+ /** Hash-grid cell lookups, including empty cells. */
19
+ cells: number;
20
+ /** Indexed entry visits, including duplicates removed before bounds tests. */
21
+ entries: number;
22
+ /** Cached AABB ray tests after deduplication. */
23
+ bounds: number;
24
+ }
25
+ /**
26
+ * Static collision for world geometry that is not a scene object: generated buildings, studio
27
+ * volumes like `city`, wall runs. Solids live in named layers so a feature can replace or drop its
28
+ * own set without touching the rest. `solidObstaclesNear` (player and NPC movement),
29
+ * `syncWorldColliders` (physics backends) and `populateNavGridFromSolids` all read this one store.
30
+ */
31
+ export interface WorldSolids {
32
+ /** Replace a layer's solids; an empty list removes the layer. */
33
+ set(layer: string, solids: readonly WorldSolid[]): void;
34
+ remove(layer: string): void;
35
+ /** Run several `set`/`remove` calls as one change: one index rebuild, one notification. */
36
+ batch(apply: () => void): void;
37
+ /** Solids in one layer, empty when absent. */
38
+ layer(layer: string): readonly WorldSolid[];
39
+ layers(): readonly string[];
40
+ /** Every solid whose world AABB overlaps `min`..`max`. Bounded by a uniform XZ hash grid. */
41
+ inBox(min: readonly [number, number, number], max: readonly [number, number, number]): WorldSolid[];
42
+ /** Optional accelerated ray candidates; finite coordinates/direction and nonnegative finite distance, normalized internally. */
43
+ inRay?(origin: readonly [number, number, number], direction: readonly [number, number, number], maxDistance: number, work?: WorldSolidRayWork): WorldSolid[];
44
+ /** Every solid in every layer. */
45
+ all(): WorldSolid[];
46
+ count(): number;
47
+ /** Bumps on every change; cheap cache key for consumers. */
48
+ version(): number;
49
+ subscribe(listener: () => void): () => void;
50
+ snapshot(): WorldSolidsState;
51
+ restore(state: WorldSolidsState): void;
52
+ }
53
+ /**
54
+ * Yaw-expanded world AABB of an oriented solid box.
55
+ * @capability world-solid-bounds world AABB and nav footprint of a world solid
56
+ */
57
+ export declare function worldSolidBounds(solid: WorldSolid): {
58
+ min: [number, number, number];
59
+ max: [number, number, number];
60
+ };
61
+ /**
62
+ * XZ footprint of a solid's world AABB, for 2D consumers such as nav grids.
63
+ * @capability world-solid-bounds world AABB and nav footprint of a world solid
64
+ */
65
+ export declare function worldSolidFootprint(solid: WorldSolid): Aabb;
66
+ /**
67
+ * A store of static world solids in named layers.
68
+ * @capability world-solids collision for generated and authored world geometry (buildings, city lots, walls)
69
+ */
70
+ export declare function createWorldSolids(options?: {
71
+ cellSize?: number;
72
+ }): WorldSolids;
73
+ /**
74
+ * One solid per generated building: its `bounds` footprint turned by `rotationY` about `center`,
75
+ * from the ground under its center up through its floors. `groundHeight` defaults to flat `0`.
76
+ * @capability world-solids-from-data derive collision boxes from generated buildings and wall runs
77
+ */
78
+ export declare function buildingSolids(buildings: readonly GeneratedBuilding[], groundHeight?: (x: number, z: number) => number): WorldSolid[];
79
+ /**
80
+ * Solids for every `structures` descriptor on an environment feature, skipping any marked `solid: false`.
81
+ * @capability world-solids-from-data derive collision boxes from generated buildings and wall runs
82
+ */
83
+ export declare function structureSolids(world: EnvironmentWorldFeature, groundHeight?: (x: number, z: number) => number): WorldSolid[];
84
+ /** Wall height, thickness and base for {@link wallSolids}. */
85
+ export interface WallSolidOptions {
86
+ height: number;
87
+ thickness: number;
88
+ /** Ground height under a point; the wall stands on it at each segment's midpoint. Default flat `0`. */
89
+ groundHeight?: (x: number, z: number) => number;
90
+ }
91
+ /**
92
+ * One oriented solid per wall segment (see `wallSegments` in `world/walls`).
93
+ * @capability world-solids-from-data derive collision boxes from generated buildings and wall runs
94
+ */
95
+ export declare function wallSolids(segments: readonly WallSegment[], options: WallSolidOptions): WorldSolid[];