@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,42 +1,54 @@
1
- /** The ambient `localStorage` as a {@link KeyValueStorage} when one exists (browser), otherwise `null` (server/tests) — never references the DOM `Storage` type, so it is safe in core. */
2
- export function defaultKeyValueStorage() {
1
+ /** The ambient `localStorage` when available, otherwise `null`. An optional observer receives denied getter errors; it may rethrow to reject fallback. Never references the DOM `Storage` type, so it is safe in core. */
2
+ export function defaultKeyValueStorage(onError) {
3
3
  try {
4
4
  if (typeof globalThis !== "undefined" && "localStorage" in globalThis) {
5
5
  return globalThis.localStorage ?? null;
6
6
  }
7
7
  }
8
- catch {
8
+ catch (error) {
9
+ onError?.(error);
9
10
  return null;
10
11
  }
11
12
  return null;
12
13
  }
13
- /** A lightweight mutable local save cell for single-player state (a credit bank, a settings blob, level progress) — the read-modify-write counterpart to the monotonic `recordBook`. Persists through a {@link KeyValueStorage} (browser `localStorage` by default); corrupt or unavailable storage degrades to in-memory and never throws into a game tick. */
14
+ /** @internal */
15
+ export function reportStorageFailure(policy, failure) {
16
+ policy.onError?.(failure);
17
+ if (policy.errorMode === "throw")
18
+ throw failure.error;
19
+ }
20
+ /** A mutable local save cell through {@link KeyValueStorage}. Default fallback keeps session state on failure; `errorMode: "throw"` exposes failed reads/writes/removals through the original error. `storage: null` deliberately uses memory only. */
14
21
  export function createKeyValueStore(config) {
15
- const storage = config.storage === undefined ? defaultKeyValueStorage() : config.storage;
22
+ const fail = (operation, error) => reportStorageFailure(config, { operation, key: config.key, error });
23
+ const storage = config.storage === undefined ? defaultKeyValueStorage((error) => fail("read", error)) : config.storage;
16
24
  const serialize = config.serialize ?? ((value) => JSON.stringify(value));
17
25
  const deserialize = config.deserialize ?? ((raw) => JSON.parse(raw));
18
26
  const read = () => {
19
- if (storage === null)
27
+ if (storage === null) {
28
+ if (config.storage !== null && config.errorMode === "throw")
29
+ fail("read", new Error("Local storage is unavailable"));
20
30
  return config.initial;
31
+ }
21
32
  try {
22
33
  const raw = storage.getItem(config.key);
23
34
  return raw === null ? config.initial : deserialize(raw);
24
35
  }
25
- catch {
36
+ catch (error) {
37
+ fail("read", error);
26
38
  return config.initial;
27
39
  }
28
40
  };
29
41
  let current = read();
30
42
  const write = (value) => {
31
- current = value;
32
- if (storage === null)
33
- return;
34
- try {
35
- storage.setItem(config.key, serialize(value));
36
- }
37
- catch {
38
- // storage rejected the write; keep the value in memory for this session
43
+ if (storage !== null) {
44
+ try {
45
+ storage.setItem(config.key, serialize(value));
46
+ }
47
+ catch (error) {
48
+ fail("write", error);
49
+ }
39
50
  }
51
+ current = value;
40
52
  };
41
53
  return {
42
54
  get: () => current,
@@ -47,15 +59,15 @@ export function createKeyValueStore(config) {
47
59
  return next;
48
60
  },
49
61
  clear: () => {
50
- current = config.initial;
51
- if (storage === null)
52
- return;
53
- try {
54
- storage.removeItem(config.key);
55
- }
56
- catch {
57
- // ignore removal failure; in-memory value already reset
62
+ if (storage !== null) {
63
+ try {
64
+ storage.removeItem(config.key);
65
+ }
66
+ catch (error) {
67
+ fail("remove", error);
68
+ }
58
69
  }
70
+ current = config.initial;
59
71
  },
60
72
  };
61
73
  }
@@ -0,0 +1,17 @@
1
+ import type { LootEntry } from "./lootTable.js";
2
+ import type { LootModifier } from "./lootPipeline.js";
3
+ /** Caller-authored weighting curve; item ids, quality tiers and balance never live in the modifier. */
4
+ export interface TimeScaledRarityOptions {
5
+ id?: string;
6
+ ramp: (entry: LootEntry, hours: number) => number;
7
+ }
8
+ /**
9
+ * Multiply weighted odds (or independent chances, clamped to one) by a caller-authored elapsed-time
10
+ * curve. Keeps source tables unchanged and uses the existing pipeline's modifier provenance.
11
+ * Elapsed time and multipliers must be finite and nonnegative; invalid curves reject the roll.
12
+ *
13
+ * @capability time-scaled-loot shape loot odds by elapsed hours with caller-authored curves and pipeline provenance
14
+ */
15
+ export declare function timeScaledRarity<TCtx extends {
16
+ elapsedMs: number;
17
+ }>(options: TimeScaledRarityOptions): LootModifier<TCtx>;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Multiply weighted odds (or independent chances, clamped to one) by a caller-authored elapsed-time
3
+ * curve. Keeps source tables unchanged and uses the existing pipeline's modifier provenance.
4
+ * Elapsed time and multipliers must be finite and nonnegative; invalid curves reject the roll.
5
+ *
6
+ * @capability time-scaled-loot shape loot odds by elapsed hours with caller-authored curves and pipeline provenance
7
+ */
8
+ export function timeScaledRarity(options) {
9
+ return {
10
+ id: options.id ?? "time-scaled-rarity",
11
+ plan(plan, ctx) {
12
+ if (!Number.isFinite(ctx.elapsedMs) || ctx.elapsedMs < 0)
13
+ throw new RangeError("Loot elapsedMs must be finite and nonnegative");
14
+ const hours = ctx.elapsedMs / 3_600_000;
15
+ return { ...plan, entries: plan.entries.map(candidate => {
16
+ const factor = options.ramp(candidate.entry, hours);
17
+ if (!Number.isFinite(factor) || factor < 0)
18
+ throw new RangeError("Loot time multiplier must be finite and nonnegative");
19
+ const value = (plan.mode === "weighted" ? candidate.weight : candidate.chance ?? 0) * factor;
20
+ if (!Number.isFinite(value))
21
+ throw new RangeError("Loot time weighting overflowed");
22
+ return plan.mode === "weighted" ? { ...candidate, weight: value } : { ...candidate, chance: Math.min(1, value) };
23
+ }) };
24
+ },
25
+ };
26
+ }
@@ -38,6 +38,10 @@ export interface LootRegistry {
38
38
  register(def: LootTableDef): void;
39
39
  has(id: string): boolean;
40
40
  roll(id: string, rng?: () => number): Drop[];
41
+ /** Registered tables in registration order; plain JSON unless an entry uses `generate`. */
42
+ snapshot(): LootTableDef[];
43
+ /** Replaces every registered table with `next`, validating each. */
44
+ restore(next: readonly LootTableDef[]): void;
41
45
  }
42
46
  /** Options for {@link createLootRegistry} — inject a default RNG so bare `roll(id)` uses the world stream. */
43
47
  export interface LootRegistryOptions {
@@ -1,4 +1,10 @@
1
1
  import { resolveRng } from "../random/resolveRng.js";
2
+ function copyDef(def) {
3
+ return {
4
+ ...def,
5
+ entries: def.entries.map((entry) => ({ ...entry, count: typeof entry.count === "number" ? entry.count : [entry.count[0], entry.count[1]] })),
6
+ };
7
+ }
2
8
  function assertValidEntry(entry, mode) {
3
9
  const kinds = [entry.item !== undefined, entry.currency !== undefined, entry.generate !== undefined].filter(Boolean).length;
4
10
  if (kinds !== 1) {
@@ -88,6 +94,16 @@ export function createLootRegistry(options = {}) {
88
94
  }
89
95
  return drops;
90
96
  },
97
+ snapshot() {
98
+ return [...tables.values()].map(copyDef);
99
+ },
100
+ restore(next) {
101
+ for (const def of next)
102
+ assertValidDef(def);
103
+ tables.clear();
104
+ for (const def of next)
105
+ tables.set(def.id, copyDef(def));
106
+ },
91
107
  };
92
108
  }
93
109
  /**
@@ -0,0 +1,67 @@
1
+ import { type DialogueGraph } from "./dialogueGraph.js";
2
+ /** Caller-reviewed facts for one authoring revision; event ids are in strict chronological order. */
3
+ export interface NarrativeCanon {
4
+ readonly revision: string;
5
+ readonly characterIds: readonly string[];
6
+ readonly facts: Readonly<Record<string, string>>;
7
+ readonly eventIds: readonly string[];
8
+ }
9
+ /** An explicit assertion attached to a dialogue node; dialogue prose is never parsed. */
10
+ export type NarrativeClaim = {
11
+ readonly nodeId: string;
12
+ } & ({
13
+ readonly kind: "character";
14
+ readonly characterId: string;
15
+ } | {
16
+ readonly kind: "fact";
17
+ readonly factId: string;
18
+ readonly value: string;
19
+ } | {
20
+ readonly kind: "before";
21
+ readonly earlier: string;
22
+ readonly later: string;
23
+ });
24
+ /** Authored dialogue with optional structured assertions against canon. */
25
+ export interface NarrativeDialogue {
26
+ readonly id: string;
27
+ readonly graph: DialogueGraph;
28
+ readonly claims: readonly NarrativeClaim[];
29
+ }
30
+ /** A candidate batch never changes canon; accepted new facts need a separately reviewed revision. */
31
+ export interface NarrativeBatch {
32
+ readonly canonRevision: string;
33
+ readonly dialogues: readonly NarrativeDialogue[];
34
+ }
35
+ /** Caller budgets across the entire batch, including graph branches and explicit assertions. */
36
+ export interface NarrativeBatchLimits {
37
+ readonly maxDialogues: number;
38
+ readonly maxNodes: number;
39
+ readonly maxChoices: number;
40
+ readonly maxClaims: number;
41
+ /** Sum of spoken lines and player choice text lengths (UTF-16 code units). */
42
+ readonly maxTextCharacters: number;
43
+ }
44
+ /** A repair diagnostic with a JSON-pointer location in the candidate batch. */
45
+ export interface NarrativeIssue {
46
+ readonly code: string;
47
+ readonly severity: "error" | "warning";
48
+ readonly path: string;
49
+ readonly message: string;
50
+ }
51
+ /**
52
+ * Detach and freeze reviewed canon before passing it to an asynchronous authoring callback.
53
+ * Duplicate character/event ids and an empty revision throw; facts retain exact caller values.
54
+ *
55
+ * @capability narrative-canon freeze caller-reviewed character ids, facts and chronology for a narrative authoring revision
56
+ */
57
+ export declare function freezeNarrativeCanon(canon: NarrativeCanon): NarrativeCanon;
58
+ /**
59
+ * Check a typed candidate against caller budgets, canon revision, explicit claims and graph topology.
60
+ * Stops at the first exceeded budget before topology work; stale revisions also stop immediately.
61
+ * Claims check exact fact values and the declared strict event order, never prose, speaker labels,
62
+ * motivations, branch consequences or story quality. O(canon + bounded nodes + choices + claims).
63
+ * Validate/parse external JSON before calling; this is not an untrusted JSON decoder.
64
+ *
65
+ * @capability narrative-batch-validation locate stale canon, oversized batches, explicit character/fact/chronology contradictions and dialogue graph issues for bounded repair
66
+ */
67
+ export declare function validateNarrativeBatch(canon: NarrativeCanon, batch: NarrativeBatch, limits: NarrativeBatchLimits): NarrativeIssue[];
@@ -0,0 +1,122 @@
1
+ import { validateDialogueGraph } from "./dialogueGraph.js";
2
+ /**
3
+ * Detach and freeze reviewed canon before passing it to an asynchronous authoring callback.
4
+ * Duplicate character/event ids and an empty revision throw; facts retain exact caller values.
5
+ *
6
+ * @capability narrative-canon freeze caller-reviewed character ids, facts and chronology for a narrative authoring revision
7
+ */
8
+ export function freezeNarrativeCanon(canon) {
9
+ if (canon.revision.length === 0)
10
+ throw new RangeError("Canon revision must not be empty.");
11
+ for (const ids of [canon.characterIds, canon.eventIds]) {
12
+ if (new Set(ids).size !== ids.length)
13
+ throw new RangeError("Canon ids must be unique within each list.");
14
+ }
15
+ return Object.freeze({
16
+ revision: canon.revision,
17
+ characterIds: Object.freeze([...canon.characterIds]),
18
+ facts: Object.freeze({ ...canon.facts }),
19
+ eventIds: Object.freeze([...canon.eventIds]),
20
+ });
21
+ }
22
+ /**
23
+ * Check a typed candidate against caller budgets, canon revision, explicit claims and graph topology.
24
+ * Stops at the first exceeded budget before topology work; stale revisions also stop immediately.
25
+ * Claims check exact fact values and the declared strict event order, never prose, speaker labels,
26
+ * motivations, branch consequences or story quality. O(canon + bounded nodes + choices + claims).
27
+ * Validate/parse external JSON before calling; this is not an untrusted JSON decoder.
28
+ *
29
+ * @capability narrative-batch-validation locate stale canon, oversized batches, explicit character/fact/chronology contradictions and dialogue graph issues for bounded repair
30
+ */
31
+ export function validateNarrativeBatch(canon, batch, limits) {
32
+ for (const value of Object.values(limits)) {
33
+ if (!Number.isSafeInteger(value) || value < 0)
34
+ throw new RangeError("Narrative limits must be non-negative safe integers.");
35
+ }
36
+ if (batch.canonRevision !== canon.revision) {
37
+ return [{ code: "stale-canon", severity: "error", path: "/canonRevision", message: "Candidate uses a different canon revision." }];
38
+ }
39
+ const budget = (path) => [{
40
+ code: "batch-budget", severity: "error", path, message: "Candidate exceeds the caller's narrative batch budget.",
41
+ }];
42
+ if (batch.dialogues.length > limits.maxDialogues)
43
+ return budget("/dialogues");
44
+ let nodes = 0;
45
+ let choices = 0;
46
+ let claims = 0;
47
+ let text = 0;
48
+ for (let index = 0; index < batch.dialogues.length; index++) {
49
+ const dialogue = batch.dialogues[index];
50
+ const path = `/dialogues/${index}`;
51
+ nodes += dialogue.graph.nodes.length;
52
+ claims += dialogue.claims.length;
53
+ if (nodes > limits.maxNodes)
54
+ return budget(`${path}/graph/nodes`);
55
+ if (claims > limits.maxClaims)
56
+ return budget(`${path}/claims`);
57
+ for (let nodeIndex = 0; nodeIndex < dialogue.graph.nodes.length; nodeIndex++) {
58
+ const node = dialogue.graph.nodes[nodeIndex];
59
+ choices += node.choices?.length ?? 0;
60
+ if (choices > limits.maxChoices)
61
+ return budget(`${path}/graph/nodes/${nodeIndex}/choices`);
62
+ text += node.text.length;
63
+ for (const choice of node.choices ?? [])
64
+ text += choice.text.length;
65
+ if (text > limits.maxTextCharacters)
66
+ return budget(`${path}/graph/nodes/${nodeIndex}`);
67
+ }
68
+ }
69
+ const issues = [];
70
+ const add = (code, path, message) => {
71
+ issues.push({ code, severity: "error", path, message });
72
+ };
73
+ const characters = new Set(canon.characterIds);
74
+ const facts = new Map(Object.entries(canon.facts));
75
+ const events = new Map(canon.eventIds.map((id, index) => [id, index]));
76
+ const dialogueIds = new Set();
77
+ for (let index = 0; index < batch.dialogues.length; index++) {
78
+ const dialogue = batch.dialogues[index];
79
+ const path = `/dialogues/${index}`;
80
+ if (dialogueIds.has(dialogue.id))
81
+ add("duplicate-dialogue", `${path}/id`, "Dialogue id repeats within the batch.");
82
+ dialogueIds.add(dialogue.id);
83
+ for (const issue of validateDialogueGraph(dialogue.graph)) {
84
+ let location = `${path}/graph`;
85
+ if (issue.nodeIndex !== undefined)
86
+ location += `/nodes/${issue.nodeIndex}`;
87
+ if (issue.choiceIndex !== undefined)
88
+ location += `/choices/${issue.choiceIndex}/to`;
89
+ if (issue.code === "missing-start")
90
+ location += "/start";
91
+ issues.push({ code: `dialogue:${issue.code}`, severity: issue.severity, path: location, message: issue.message });
92
+ }
93
+ const nodeIds = new Set(dialogue.graph.nodes.map((node) => node.id));
94
+ for (let claimIndex = 0; claimIndex < dialogue.claims.length; claimIndex++) {
95
+ const claim = dialogue.claims[claimIndex];
96
+ const location = `${path}/claims/${claimIndex}`;
97
+ if (!nodeIds.has(claim.nodeId))
98
+ add("missing-claim-node", `${location}/nodeId`, "Claim references an unknown dialogue node.");
99
+ if (claim.kind === "character" && !characters.has(claim.characterId)) {
100
+ add("unknown-character", `${location}/characterId`, "Claim references an unknown canon character.");
101
+ }
102
+ else if (claim.kind === "fact") {
103
+ if (!facts.has(claim.factId))
104
+ add("unknown-fact", `${location}/factId`, "Claim references an unknown canon fact.");
105
+ else if (facts.get(claim.factId) !== claim.value)
106
+ add("fact-conflict", `${location}/value`, "Claim differs from the reviewed fact value.");
107
+ }
108
+ else if (claim.kind === "before") {
109
+ const earlier = events.get(claim.earlier);
110
+ const later = events.get(claim.later);
111
+ if (earlier === undefined)
112
+ add("unknown-event", `${location}/earlier`, "Claim references an unknown canon event.");
113
+ if (later === undefined)
114
+ add("unknown-event", `${location}/later`, "Claim references an unknown canon event.");
115
+ if (earlier !== undefined && later !== undefined && earlier >= later) {
116
+ add("chronology-conflict", location, "Claim contradicts the reviewed strict event order.");
117
+ }
118
+ }
119
+ }
120
+ }
121
+ return issues;
122
+ }