@jgengine/core 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (631) hide show
  1. package/CHANGELOG.md +34 -3
  2. package/LICENSE +203 -661
  3. package/README.md +1 -1
  4. package/dist/ai/crowd.d.ts +55 -0
  5. package/dist/ai/crowd.js +114 -0
  6. package/dist/ai/flock.d.ts +5 -2
  7. package/dist/ai/flock.js +5 -2
  8. package/dist/ai/groupAssist.d.ts +1 -0
  9. package/dist/ai/groupAssist.js +1 -0
  10. package/dist/ai/heatSystem.d.ts +76 -0
  11. package/dist/ai/heatSystem.js +97 -0
  12. package/dist/ai/interestScheduler.d.ts +107 -0
  13. package/dist/ai/interestScheduler.js +118 -0
  14. package/dist/ai/jobBoard.d.ts +1 -0
  15. package/dist/ai/jobBoard.js +1 -0
  16. package/dist/ai/laneSelect.d.ts +5 -2
  17. package/dist/ai/laneSelect.js +5 -2
  18. package/dist/ai/mobBrain.d.ts +1 -0
  19. package/dist/ai/mobBrain.js +1 -0
  20. package/dist/ai/spawnDirector.d.ts +19 -1
  21. package/dist/ai/spawnDirector.js +53 -26
  22. package/dist/ai/spawnPoint.d.ts +7 -0
  23. package/dist/ai/spawnPoint.js +7 -0
  24. package/dist/ai/targetAcquisition.d.ts +84 -0
  25. package/dist/ai/targetAcquisition.js +92 -0
  26. package/dist/anim/easing.d.ts +19 -0
  27. package/dist/anim/easing.js +19 -0
  28. package/dist/anim/oscillator.d.ts +12 -0
  29. package/dist/anim/oscillator.js +25 -0
  30. package/dist/area/areaEffectField.d.ts +127 -0
  31. package/dist/area/areaEffectField.js +175 -0
  32. package/dist/area/stackPolicy.d.ts +47 -0
  33. package/dist/area/stackPolicy.js +99 -0
  34. package/dist/audio/audioFalloff.d.ts +5 -2
  35. package/dist/audio/music.d.ts +53 -0
  36. package/dist/audio/music.js +34 -0
  37. package/dist/audio/synth.d.ts +60 -0
  38. package/dist/audio/synth.js +8 -0
  39. package/dist/authoring.d.ts +15 -0
  40. package/dist/authoring.js +15 -0
  41. package/dist/board/laneBoard.d.ts +13 -0
  42. package/dist/board/laneBoard.js +13 -0
  43. package/dist/board/timelineBoard.d.ts +10 -0
  44. package/dist/board/timelineBoard.js +10 -0
  45. package/dist/combat/abilityKit.d.ts +18 -0
  46. package/dist/combat/abilityKit.js +24 -9
  47. package/dist/combat/animationState.d.ts +5 -0
  48. package/dist/combat/animationState.js +5 -0
  49. package/dist/combat/breakMeters.d.ts +10 -0
  50. package/dist/combat/breakMeters.js +10 -0
  51. package/dist/combat/castRunner.d.ts +5 -0
  52. package/dist/combat/castRunner.js +5 -0
  53. package/dist/combat/comboPoints.d.ts +5 -0
  54. package/dist/combat/comboPoints.js +5 -0
  55. package/dist/combat/comboString.d.ts +5 -0
  56. package/dist/combat/comboString.js +5 -0
  57. package/dist/combat/damageInterceptors.d.ts +192 -0
  58. package/dist/combat/damageInterceptors.js +251 -0
  59. package/dist/combat/damageMatchup.d.ts +68 -0
  60. package/dist/combat/damageMatchup.js +42 -0
  61. package/dist/combat/damageResolution.d.ts +63 -0
  62. package/dist/combat/damageResolution.js +50 -0
  63. package/dist/combat/death.d.ts +7 -1
  64. package/dist/combat/death.js +5 -0
  65. package/dist/combat/deathReason.d.ts +14 -0
  66. package/dist/combat/deathReason.js +1 -0
  67. package/dist/combat/defensiveWindow.d.ts +5 -0
  68. package/dist/combat/defensiveWindow.js +5 -0
  69. package/dist/combat/dotField.d.ts +47 -0
  70. package/dist/combat/dotField.js +52 -0
  71. package/dist/combat/downed.d.ts +5 -0
  72. package/dist/combat/downed.js +5 -0
  73. package/dist/combat/effects.d.ts +5 -0
  74. package/dist/combat/effects.js +5 -0
  75. package/dist/combat/encounterSequence.d.ts +258 -0
  76. package/dist/combat/encounterSequence.js +426 -0
  77. package/dist/combat/hitReaction.d.ts +57 -1
  78. package/dist/combat/hitReaction.js +45 -5
  79. package/dist/combat/magazine.d.ts +54 -0
  80. package/dist/combat/magazine.js +96 -0
  81. package/dist/combat/projectiles.d.ts +7 -2
  82. package/dist/combat/projectiles.js +48 -17
  83. package/dist/combat/receivedDamage.d.ts +117 -0
  84. package/dist/combat/receivedDamage.js +92 -0
  85. package/dist/combat/regenShield.d.ts +39 -0
  86. package/dist/combat/regenShield.js +49 -0
  87. package/dist/combat/renderCues.d.ts +51 -0
  88. package/dist/combat/renderCues.js +44 -0
  89. package/dist/combat/resourcePool.d.ts +5 -0
  90. package/dist/combat/resourcePool.js +5 -0
  91. package/dist/combat/rewardAllocation.d.ts +121 -0
  92. package/dist/combat/rewardAllocation.js +251 -0
  93. package/dist/combat/shotOrigin.d.ts +30 -1
  94. package/dist/combat/shotOrigin.js +70 -2
  95. package/dist/combat/statusApplication.d.ts +96 -0
  96. package/dist/combat/statusApplication.js +81 -0
  97. package/dist/combat/telegraph.d.ts +11 -2
  98. package/dist/combat/telegraph.js +11 -2
  99. package/dist/combat/thresholdCrossings.d.ts +85 -0
  100. package/dist/combat/thresholdCrossings.js +116 -0
  101. package/dist/combat.d.ts +34 -0
  102. package/dist/combat.js +34 -0
  103. package/dist/commands/commandRegistry.d.ts +11 -0
  104. package/dist/commands/commandRegistry.js +9 -2
  105. package/dist/crafting/crop.d.ts +18 -0
  106. package/dist/crafting/crop.js +18 -0
  107. package/dist/crafting/production.d.ts +5 -0
  108. package/dist/crafting/production.js +5 -0
  109. package/dist/devtools/rewriteTunables.d.ts +17 -0
  110. package/dist/devtools/rewriteTunables.js +276 -0
  111. package/dist/devtools/saveEndpoint.d.ts +46 -0
  112. package/dist/devtools/saveEndpoint.js +48 -0
  113. package/dist/devtools/transformTunables.d.ts +3 -0
  114. package/dist/devtools/transformTunables.js +3 -0
  115. package/dist/devtools/tunableSchema.d.ts +31 -0
  116. package/dist/devtools/tunableSchema.js +31 -0
  117. package/dist/economy/currency.d.ts +12 -1
  118. package/dist/economy/currency.js +12 -1
  119. package/dist/economy/listingBook.d.ts +91 -0
  120. package/dist/economy/listingBook.js +144 -0
  121. package/dist/economy/resourceLedger.d.ts +222 -0
  122. package/dist/economy/resourceLedger.js +353 -0
  123. package/dist/economy/sharedWallet.d.ts +14 -0
  124. package/dist/economy/sharedWallet.js +14 -0
  125. package/dist/economy/techTree.d.ts +12 -0
  126. package/dist/economy/techTree.js +12 -0
  127. package/dist/economy/wallet.d.ts +26 -2
  128. package/dist/economy/wallet.js +35 -6
  129. package/dist/editor/commands.d.ts +248 -0
  130. package/dist/editor/commands.js +865 -0
  131. package/dist/editor/document.d.ts +186 -0
  132. package/dist/editor/document.js +884 -0
  133. package/dist/editor/grid.d.ts +229 -0
  134. package/dist/editor/grid.js +366 -0
  135. package/dist/editor/gridAdapters.d.ts +80 -0
  136. package/dist/editor/gridAdapters.js +134 -0
  137. package/dist/editor/index.d.ts +97 -0
  138. package/dist/editor/index.js +10 -0
  139. package/dist/editor/liveSync.d.ts +127 -0
  140. package/dist/editor/liveSync.js +249 -0
  141. package/dist/editor/runtimeInspector.d.ts +88 -0
  142. package/dist/editor/runtimeInspector.js +239 -0
  143. package/dist/editor/types.d.ts +175 -0
  144. package/dist/editor/types.js +29 -0
  145. package/dist/faction/reputation.d.ts +5 -0
  146. package/dist/faction/reputation.js +5 -0
  147. package/dist/format/distance.d.ts +17 -0
  148. package/dist/format/distance.js +18 -0
  149. package/dist/format/duration.d.ts +27 -0
  150. package/dist/format/duration.js +45 -0
  151. package/dist/format/speed.d.ts +17 -0
  152. package/dist/format/speed.js +25 -0
  153. package/dist/game/connectedPlayers.d.ts +30 -0
  154. package/dist/game/connectedPlayers.js +21 -0
  155. package/dist/game/cosmetics.d.ts +9 -0
  156. package/dist/game/cosmetics.js +16 -0
  157. package/dist/game/defineGame.d.ts +141 -2
  158. package/dist/game/defineGame.js +39 -1
  159. package/dist/game/defineSystem.d.ts +88 -0
  160. package/dist/game/defineSystem.js +45 -0
  161. package/dist/game/dialogue.d.ts +33 -0
  162. package/dist/game/dialogue.js +21 -0
  163. package/dist/game/events.d.ts +50 -13
  164. package/dist/game/events.js +5 -0
  165. package/dist/game/feed.d.ts +33 -0
  166. package/dist/game/feed.js +35 -2
  167. package/dist/game/gamePhase.d.ts +11 -0
  168. package/dist/game/gamePhase.js +16 -0
  169. package/dist/game/keyValueStore.d.ts +25 -0
  170. package/dist/game/keyValueStore.js +61 -0
  171. package/dist/game/leaderboard.d.ts +5 -0
  172. package/dist/game/leaderboard.js +5 -0
  173. package/dist/game/levelSequence.d.ts +24 -2
  174. package/dist/game/levelSequence.js +51 -2
  175. package/dist/game/loadout.d.ts +5 -0
  176. package/dist/game/loadout.js +5 -0
  177. package/dist/game/lootFilter.d.ts +2 -0
  178. package/dist/game/lootFilter.js +2 -0
  179. package/dist/game/lootPipeline.d.ts +164 -0
  180. package/dist/game/lootPipeline.js +216 -0
  181. package/dist/game/lootTable.d.ts +21 -0
  182. package/dist/game/lootTable.js +15 -4
  183. package/dist/game/modelAnimation.d.ts +8 -0
  184. package/dist/game/modelAnimation.js +18 -0
  185. package/dist/game/objectives.d.ts +43 -0
  186. package/dist/game/objectives.js +36 -0
  187. package/dist/game/paramLayers.d.ts +148 -0
  188. package/dist/game/paramLayers.js +185 -0
  189. package/dist/game/ping.d.ts +5 -0
  190. package/dist/game/ping.js +5 -0
  191. package/dist/game/playableGame.d.ts +160 -12
  192. package/dist/game/quest.d.ts +8 -0
  193. package/dist/game/quest.js +29 -0
  194. package/dist/game/race.d.ts +141 -0
  195. package/dist/game/race.js +169 -0
  196. package/dist/game/recordBook.d.ts +5 -5
  197. package/dist/game/recordBook.js +4 -1
  198. package/dist/game/ruleSelection.d.ts +75 -0
  199. package/dist/game/ruleSelection.js +127 -0
  200. package/dist/game/runDraft.d.ts +5 -0
  201. package/dist/game/runDraft.js +5 -0
  202. package/dist/game/saveStore.d.ts +111 -0
  203. package/dist/game/saveStore.js +312 -0
  204. package/dist/game/snapshotHistory.d.ts +67 -0
  205. package/dist/game/snapshotHistory.js +95 -0
  206. package/dist/game/social.d.ts +38 -1
  207. package/dist/game/social.js +71 -0
  208. package/dist/game/spawnPoints.d.ts +5 -0
  209. package/dist/game/spawnPoints.js +5 -0
  210. package/dist/game/systemRuntime.d.ts +50 -0
  211. package/dist/game/systemRuntime.js +157 -0
  212. package/dist/game/systemSchedule.d.ts +72 -0
  213. package/dist/game/systemSchedule.js +242 -0
  214. package/dist/game/toasts.d.ts +43 -0
  215. package/dist/game/toasts.js +44 -0
  216. package/dist/game/trade.d.ts +10 -0
  217. package/dist/game/trade.js +10 -0
  218. package/dist/game/unlocks.d.ts +8 -0
  219. package/dist/game/unlocks.js +16 -0
  220. package/dist/game/vfxInstance.d.ts +138 -0
  221. package/dist/game/vfxInstance.js +96 -0
  222. package/dist/game/worldItem.d.ts +17 -4
  223. package/dist/game/worldItem.js +17 -4
  224. package/dist/gameplay.d.ts +91 -0
  225. package/dist/gameplay.js +91 -0
  226. package/dist/index.d.ts +5 -7
  227. package/dist/index.js +5 -7
  228. package/dist/input/actionBindings.d.ts +24 -5
  229. package/dist/input/actionBindings.js +23 -5
  230. package/dist/input/axisInput.d.ts +13 -1
  231. package/dist/input/axisInput.js +22 -1
  232. package/dist/input/controlGroups.d.ts +67 -0
  233. package/dist/input/controlGroups.js +41 -0
  234. package/dist/input/touchScheme.d.ts +82 -6
  235. package/dist/input/touchScheme.js +123 -10
  236. package/dist/interaction/contextMenu.d.ts +1 -0
  237. package/dist/interaction/contextMenu.js +1 -0
  238. package/dist/interaction/lockpick.d.ts +61 -0
  239. package/dist/interaction/lockpick.js +168 -0
  240. package/dist/interaction/proximityPrompt.d.ts +5 -1
  241. package/dist/interaction/proximityPrompt.js +5 -3
  242. package/dist/interaction/qte.d.ts +5 -0
  243. package/dist/interaction/qte.js +5 -0
  244. package/dist/interaction/skillCheck.d.ts +5 -0
  245. package/dist/interaction/skillCheck.js +5 -0
  246. package/dist/inventory/inventoryModel.d.ts +12 -0
  247. package/dist/inventory/inventoryModel.js +12 -0
  248. package/dist/inventory/shapedGrid.d.ts +16 -0
  249. package/dist/inventory/shapedGrid.js +16 -0
  250. package/dist/inventory/slotModel.d.ts +10 -0
  251. package/dist/inventory/slotModel.js +10 -0
  252. package/dist/item/durability.d.ts +5 -0
  253. package/dist/item/durability.js +5 -0
  254. package/dist/item/itemIdentity.d.ts +171 -0
  255. package/dist/item/itemIdentity.js +138 -0
  256. package/dist/item/itemInstanceRegistry.d.ts +32 -0
  257. package/dist/item/itemInstanceRegistry.js +34 -0
  258. package/dist/item/itemgen.d.ts +163 -0
  259. package/dist/item/itemgen.js +151 -0
  260. package/dist/item/modularItem.d.ts +5 -0
  261. package/dist/item/modularItem.js +5 -0
  262. package/dist/item/use.d.ts +5 -0
  263. package/dist/item/use.js +5 -0
  264. package/dist/item/useBehavior.d.ts +142 -0
  265. package/dist/item/useBehavior.js +105 -0
  266. package/dist/item/weapon.d.ts +5 -0
  267. package/dist/item/weapon.js +5 -0
  268. package/dist/math/scalar.d.ts +25 -0
  269. package/dist/math/scalar.js +47 -0
  270. package/dist/meta/changelog.d.ts +4 -1
  271. package/dist/meta/changelog.js +36 -1
  272. package/dist/movement/avoidance.d.ts +45 -0
  273. package/dist/movement/avoidance.js +123 -0
  274. package/dist/movement/cameraRig.d.ts +8 -0
  275. package/dist/movement/cameraRig.js +8 -0
  276. package/dist/movement/dash.d.ts +11 -0
  277. package/dist/movement/dash.js +11 -0
  278. package/dist/movement/formation.d.ts +135 -0
  279. package/dist/movement/formation.js +194 -0
  280. package/dist/movement/glideModel.d.ts +5 -0
  281. package/dist/movement/glideModel.js +5 -0
  282. package/dist/movement/grappleSwing.d.ts +5 -0
  283. package/dist/movement/grappleSwing.js +5 -0
  284. package/dist/movement/leaderTrail.d.ts +5 -0
  285. package/dist/movement/leaderTrail.js +5 -0
  286. package/dist/movement/movementModel.d.ts +38 -7
  287. package/dist/movement/movementModel.js +54 -13
  288. package/dist/movement/playerMovement.d.ts +41 -0
  289. package/dist/movement/playerMovement.js +236 -0
  290. package/dist/movement/poseState.d.ts +13 -0
  291. package/dist/movement/poseState.js +16 -0
  292. package/dist/movement/steering.d.ts +8 -0
  293. package/dist/movement/steering.js +18 -0
  294. package/dist/multiplayer/combatSnapshot.d.ts +3 -0
  295. package/dist/multiplayer/combatSnapshot.js +3 -0
  296. package/dist/multiplayer/lagCompensation.d.ts +5 -0
  297. package/dist/multiplayer/lagCompensation.js +5 -0
  298. package/dist/multiplayer/presenceModel.d.ts +9 -1
  299. package/dist/multiplayer/presenceModel.js +9 -1
  300. package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
  301. package/dist/multiplayer/simultaneousCommit.js +3 -0
  302. package/dist/multiplayer.d.ts +11 -0
  303. package/dist/multiplayer.js +11 -0
  304. package/dist/nav/pathFollow.d.ts +57 -0
  305. package/dist/nav/pathFollow.js +109 -0
  306. package/dist/orders/orderKinds.d.ts +156 -0
  307. package/dist/orders/orderKinds.js +197 -0
  308. package/dist/orders/orderQueue.d.ts +208 -0
  309. package/dist/orders/orderQueue.js +211 -0
  310. package/dist/physics/drivableVehicle.d.ts +29 -0
  311. package/dist/physics/drivableVehicle.js +16 -0
  312. package/dist/physics/kinematicVehicle.d.ts +21 -1
  313. package/dist/physics/kinematicVehicle.js +23 -8
  314. package/dist/physics/physicsWorld.d.ts +24 -12
  315. package/dist/physics/physicsWorld.js +11 -5
  316. package/dist/physics/radialImpulse.d.ts +25 -0
  317. package/dist/physics/radialImpulse.js +27 -0
  318. package/dist/procedural.d.ts +3 -0
  319. package/dist/procedural.js +3 -0
  320. package/dist/progression/statGraph.d.ts +116 -0
  321. package/dist/progression/statGraph.js +318 -0
  322. package/dist/puzzle/cellGrid.d.ts +9 -0
  323. package/dist/puzzle/cellGrid.js +9 -0
  324. package/dist/puzzle/fallingPiece.d.ts +9 -0
  325. package/dist/puzzle/fallingPiece.js +9 -0
  326. package/dist/puzzle/nonogram.d.ts +39 -0
  327. package/dist/puzzle/nonogram.js +136 -0
  328. package/dist/random/nameGen.d.ts +5 -0
  329. package/dist/random/nameGen.js +5 -0
  330. package/dist/random/pick.d.ts +8 -0
  331. package/dist/random/pick.js +31 -0
  332. package/dist/random/rng.d.ts +24 -0
  333. package/dist/random/rng.js +30 -8
  334. package/dist/random/seedLink.d.ts +4 -0
  335. package/dist/random/seedLink.js +4 -0
  336. package/dist/relation/keyedValues.d.ts +54 -0
  337. package/dist/relation/keyedValues.js +115 -0
  338. package/dist/relation/thresholds.d.ts +62 -0
  339. package/dist/relation/thresholds.js +62 -0
  340. package/dist/render/color.d.ts +12 -0
  341. package/dist/render/color.js +26 -0
  342. package/dist/render/lookPreset.d.ts +41 -0
  343. package/dist/render/lookPreset.js +29 -0
  344. package/dist/render/postProcessing.d.ts +76 -0
  345. package/dist/render/postProcessing.js +21 -0
  346. package/dist/rules/predicate.d.ts +53 -0
  347. package/dist/rules/predicate.js +64 -0
  348. package/dist/rules/ruleEffects.d.ts +38 -0
  349. package/dist/rules/ruleEffects.js +37 -0
  350. package/dist/rules/triggeredRules.d.ts +160 -0
  351. package/dist/rules/triggeredRules.js +241 -0
  352. package/dist/runtime/adapter.d.ts +58 -0
  353. package/dist/runtime/adapter.js +54 -5
  354. package/dist/runtime/cameraDirector.d.ts +1 -0
  355. package/dist/runtime/cameraDirector.js +1 -0
  356. package/dist/runtime/commandRunner.d.ts +1 -0
  357. package/dist/runtime/commandRunner.js +1 -0
  358. package/dist/runtime/context/combatFx.d.ts +23 -0
  359. package/dist/runtime/context/combatFx.js +161 -0
  360. package/dist/runtime/context/registries.d.ts +13 -0
  361. package/dist/runtime/context/registries.js +84 -0
  362. package/dist/runtime/context/worldItems.d.ts +21 -0
  363. package/dist/runtime/context/worldItems.js +37 -0
  364. package/dist/runtime/descriptors/baseline.d.ts +48 -0
  365. package/dist/runtime/descriptors/baseline.js +134 -0
  366. package/dist/runtime/descriptors/features.d.ts +74 -0
  367. package/dist/runtime/descriptors/features.js +281 -0
  368. package/dist/runtime/gameContext.d.ts +163 -19
  369. package/dist/runtime/gameContext.js +385 -339
  370. package/dist/runtime/gameRuntime.d.ts +1 -0
  371. package/dist/runtime/gameRuntime.js +1 -0
  372. package/dist/runtime/headlessRunner.d.ts +60 -0
  373. package/dist/runtime/headlessRunner.js +44 -0
  374. package/dist/runtime/hostPersistence.d.ts +12 -0
  375. package/dist/runtime/hostPersistence.js +12 -0
  376. package/dist/runtime/hostedGameRunner.d.ts +54 -0
  377. package/dist/runtime/hostedGameRunner.js +85 -0
  378. package/dist/runtime/hostedWorldSession.d.ts +73 -0
  379. package/dist/runtime/hostedWorldSession.js +64 -0
  380. package/dist/runtime/inputSnapshot.d.ts +21 -3
  381. package/dist/runtime/inputSnapshot.js +8 -2
  382. package/dist/runtime/motionIntents.d.ts +12 -1
  383. package/dist/runtime/motionIntents.js +26 -1
  384. package/dist/runtime/perContext.d.ts +15 -0
  385. package/dist/runtime/perContext.js +21 -0
  386. package/dist/runtime/runtimeSave.d.ts +79 -0
  387. package/dist/runtime/runtimeSave.js +105 -0
  388. package/dist/runtime/save.d.ts +4 -0
  389. package/dist/runtime/save.js +4 -0
  390. package/dist/runtime/snapshot.d.ts +7 -0
  391. package/dist/runtime/snapshot.js +7 -0
  392. package/dist/runtime/visibility.d.ts +2 -1
  393. package/dist/runtime/visibility.js +2 -1
  394. package/dist/runtime/worldChannel.d.ts +62 -0
  395. package/dist/runtime/worldChannel.js +114 -0
  396. package/dist/runtime/worldMirror.d.ts +36 -0
  397. package/dist/runtime/worldMirror.js +44 -0
  398. package/dist/runtime/worldProjection.d.ts +47 -0
  399. package/dist/runtime/worldProjection.js +52 -0
  400. package/dist/runtime/worldReplication.d.ts +69 -0
  401. package/dist/runtime/worldReplication.js +217 -0
  402. package/dist/runtime/worldSnapshot.d.ts +44 -0
  403. package/dist/runtime/worldSnapshot.js +30 -0
  404. package/dist/scene/assetCatalog.d.ts +22 -0
  405. package/dist/scene/assetCatalog.js +4 -0
  406. package/dist/scene/assetDiagnostics.d.ts +69 -0
  407. package/dist/scene/assetDiagnostics.js +110 -0
  408. package/dist/scene/assetGenerator.d.ts +65 -0
  409. package/dist/scene/assetGenerator.js +64 -0
  410. package/dist/scene/assetSpace.d.ts +137 -0
  411. package/dist/scene/assetSpace.js +259 -0
  412. package/dist/scene/authoredTriggers.d.ts +169 -0
  413. package/dist/scene/authoredTriggers.js +340 -0
  414. package/dist/scene/behaviorRuntime.d.ts +75 -0
  415. package/dist/scene/behaviorRuntime.js +217 -0
  416. package/dist/scene/behaviors.d.ts +14 -2
  417. package/dist/scene/behaviors.js +7 -2
  418. package/dist/scene/bodyBind.d.ts +60 -0
  419. package/dist/scene/bodyBind.js +51 -0
  420. package/dist/scene/builtinSceneKinds.d.ts +5 -0
  421. package/dist/scene/builtinSceneKinds.js +62 -0
  422. package/dist/scene/colliders.d.ts +18 -0
  423. package/dist/scene/colliders.js +61 -1
  424. package/dist/scene/entityStats.d.ts +13 -0
  425. package/dist/scene/entityStats.js +30 -0
  426. package/dist/scene/entityStore.d.ts +41 -1
  427. package/dist/scene/entityStore.js +75 -0
  428. package/dist/scene/facing.d.ts +18 -0
  429. package/dist/scene/facing.js +26 -0
  430. package/dist/scene/modelSockets.d.ts +33 -0
  431. package/dist/scene/modelSockets.js +29 -0
  432. package/dist/scene/objectQuery.d.ts +2 -0
  433. package/dist/scene/objectQuery.js +2 -0
  434. package/dist/scene/objectStore.d.ts +4 -0
  435. package/dist/scene/objectStore.js +6 -0
  436. package/dist/scene/possession.d.ts +8 -0
  437. package/dist/scene/possession.js +14 -0
  438. package/dist/scene/roster.d.ts +3 -0
  439. package/dist/scene/roster.js +12 -0
  440. package/dist/scene/sceneKinds.d.ts +240 -0
  441. package/dist/scene/sceneKinds.js +214 -0
  442. package/dist/scene/sceneOwnership.d.ts +169 -0
  443. package/dist/scene/sceneOwnership.js +179 -0
  444. package/dist/scene/selectionBookmarks.d.ts +93 -0
  445. package/dist/scene/selectionBookmarks.js +122 -0
  446. package/dist/scene/vehicleSeat.d.ts +68 -0
  447. package/dist/scene/vehicleSeat.js +59 -0
  448. package/dist/sensor/concealment.d.ts +3 -0
  449. package/dist/sensor/concealment.js +3 -0
  450. package/dist/sensor/freezeMonitor.d.ts +1 -0
  451. package/dist/sensor/freezeMonitor.js +1 -0
  452. package/dist/sensor/frustumSensor.d.ts +7 -3
  453. package/dist/sensor/frustumSensor.js +7 -3
  454. package/dist/sensor/hiddenStateProbe.d.ts +5 -2
  455. package/dist/sensor/hiddenStateProbe.js +5 -2
  456. package/dist/sensor/recordingBuffer.d.ts +2 -1
  457. package/dist/sensor/recordingBuffer.js +2 -1
  458. package/dist/sensor/replayLoop.d.ts +6 -2
  459. package/dist/sensor/replayLoop.js +6 -2
  460. package/dist/sensor/revealQuery.d.ts +2 -1
  461. package/dist/sensor/revealQuery.js +2 -1
  462. package/dist/sensor/visionCone.d.ts +10 -3
  463. package/dist/sensor/visionCone.js +10 -3
  464. package/dist/session/contestedChannel.d.ts +1 -0
  465. package/dist/session/contestedChannel.js +1 -0
  466. package/dist/session/extraction.d.ts +1 -0
  467. package/dist/session/extraction.js +1 -0
  468. package/dist/session/roles.d.ts +6 -0
  469. package/dist/session/roles.js +6 -0
  470. package/dist/session/roundState.d.ts +8 -0
  471. package/dist/session/roundState.js +2 -0
  472. package/dist/settings/settingsModel.d.ts +1 -0
  473. package/dist/settings/settingsModel.js +1 -0
  474. package/dist/stats/accumulatorMeter.d.ts +6 -0
  475. package/dist/stats/accumulatorMeter.js +6 -0
  476. package/dist/stats/eventMeter.d.ts +5 -0
  477. package/dist/stats/eventMeter.js +5 -0
  478. package/dist/stats/rollCheck.d.ts +5 -0
  479. package/dist/stats/rollCheck.js +5 -0
  480. package/dist/stats/statModifiers.d.ts +5 -0
  481. package/dist/stats/statModifiers.js +5 -0
  482. package/dist/store/defineKeyedStore.d.ts +38 -0
  483. package/dist/store/defineKeyedStore.js +42 -0
  484. package/dist/store/defineStore.d.ts +33 -0
  485. package/dist/store/defineStore.js +35 -0
  486. package/dist/store/observableKeyedStore.d.ts +9 -0
  487. package/dist/store/observableKeyedStore.js +43 -2
  488. package/dist/survival/decayMeter.d.ts +55 -0
  489. package/dist/survival/decayMeter.js +130 -55
  490. package/dist/survival/moodle.d.ts +2 -0
  491. package/dist/survival/regionHealth.d.ts +6 -0
  492. package/dist/survival/regionHealth.js +5 -0
  493. package/dist/tactics/fallingGrid.d.ts +6 -4
  494. package/dist/tactics/fallingGrid.js +6 -4
  495. package/dist/tactics/predictiveQuery.d.ts +3 -0
  496. package/dist/tactics/predictiveQuery.js +3 -0
  497. package/dist/tactics/snapshot.d.ts +2 -0
  498. package/dist/tactics/snapshot.js +2 -0
  499. package/dist/tactics/surface.d.ts +1 -0
  500. package/dist/tactics/surface.js +1 -0
  501. package/dist/tactics/tacticalGrid.d.ts +1 -0
  502. package/dist/tactics/tacticalGrid.js +1 -0
  503. package/dist/time/beatClock.d.ts +14 -4
  504. package/dist/time/beatClock.js +14 -4
  505. package/dist/time/calendarClock.d.ts +3 -0
  506. package/dist/time/calendarClock.js +3 -0
  507. package/dist/time/idleProgress.d.ts +4 -0
  508. package/dist/time/idleProgress.js +4 -0
  509. package/dist/time/simClock.d.ts +2 -0
  510. package/dist/time/simClock.js +20 -5
  511. package/dist/ui/actionModel.d.ts +110 -0
  512. package/dist/ui/actionModel.js +159 -0
  513. package/dist/ui/gameLayout.d.ts +144 -0
  514. package/dist/ui/gameLayout.js +148 -0
  515. package/dist/ui/hudDocument.d.ts +114 -0
  516. package/dist/ui/hudDocument.js +220 -0
  517. package/dist/ui/hudLayout.d.ts +33 -1
  518. package/dist/ui/hudLayout.js +204 -17
  519. package/dist/ui/orientation.d.ts +39 -0
  520. package/dist/ui/orientation.js +49 -0
  521. package/dist/ui/selectionModel.d.ts +92 -0
  522. package/dist/ui/selectionModel.js +88 -0
  523. package/dist/ui/swingTimer.d.ts +42 -0
  524. package/dist/ui/swingTimer.js +38 -0
  525. package/dist/ui/tooltipModel.d.ts +63 -0
  526. package/dist/ui/tooltipModel.js +82 -0
  527. package/dist/ui.d.ts +15 -0
  528. package/dist/ui.js +15 -0
  529. package/dist/visibility/bounds.d.ts +8 -1
  530. package/dist/visibility/bounds.js +8 -1
  531. package/dist/visibility/frustum.d.ts +12 -3
  532. package/dist/visibility/frustum.js +12 -3
  533. package/dist/visibility/spatialIndex.js +34 -20
  534. package/dist/work/jobQueue.d.ts +201 -0
  535. package/dist/work/jobQueue.js +253 -0
  536. package/dist/work/unitTraining.d.ts +58 -0
  537. package/dist/work/unitTraining.js +52 -0
  538. package/dist/world/authoredObjects.d.ts +58 -0
  539. package/dist/world/authoredObjects.js +69 -0
  540. package/dist/world/buildingGenerator.d.ts +18 -0
  541. package/dist/world/buildingGenerator.js +62 -0
  542. package/dist/world/buildings.d.ts +5 -0
  543. package/dist/world/buildings.js +5 -0
  544. package/dist/world/catenary.d.ts +22 -0
  545. package/dist/world/catenary.js +69 -0
  546. package/dist/world/environmentSummary.d.ts +11 -2
  547. package/dist/world/environmentSummary.js +11 -1
  548. package/dist/world/features.d.ts +244 -7
  549. package/dist/world/features.js +92 -4
  550. package/dist/world/footprintGrid.d.ts +59 -0
  551. package/dist/world/footprintGrid.js +141 -0
  552. package/dist/world/geometry.d.ts +64 -0
  553. package/dist/world/geometry.js +94 -0
  554. package/dist/world/grassKind.d.ts +51 -0
  555. package/dist/world/grassKind.js +101 -0
  556. package/dist/world/pathInstances.d.ts +27 -0
  557. package/dist/world/pathInstances.js +27 -0
  558. package/dist/world/pathTerrain.d.ts +80 -0
  559. package/dist/world/pathTerrain.js +142 -0
  560. package/dist/world/placeAsset.d.ts +81 -0
  561. package/dist/world/placeAsset.js +77 -0
  562. package/dist/world/placement.d.ts +4 -0
  563. package/dist/world/placement.js +4 -0
  564. package/dist/world/placementController.d.ts +6 -0
  565. package/dist/world/placementController.js +6 -0
  566. package/dist/world/polyline.d.ts +34 -0
  567. package/dist/world/polyline.js +81 -0
  568. package/dist/world/roads.d.ts +55 -0
  569. package/dist/world/roads.js +184 -0
  570. package/dist/world/scatterRegion.d.ts +164 -0
  571. package/dist/world/scatterRegion.js +409 -0
  572. package/dist/world/sceneShapes.d.ts +43 -0
  573. package/dist/world/sceneShapes.js +1 -0
  574. package/dist/world/segment.d.ts +27 -0
  575. package/dist/world/segment.js +43 -0
  576. package/dist/world/soilKind.d.ts +48 -0
  577. package/dist/world/soilKind.js +92 -0
  578. package/dist/world/spatialSample.d.ts +241 -0
  579. package/dist/world/spatialSample.js +465 -0
  580. package/dist/world/streets.d.ts +80 -0
  581. package/dist/world/streets.js +144 -0
  582. package/dist/world/terraform.d.ts +213 -1
  583. package/dist/world/terraform.js +655 -20
  584. package/dist/world/terrain.d.ts +138 -12
  585. package/dist/world/terrain.js +346 -28
  586. package/dist/world/terrainGuides.d.ts +182 -0
  587. package/dist/world/terrainGuides.js +343 -0
  588. package/dist/world/vec2.d.ts +81 -0
  589. package/dist/world/vec2.js +128 -0
  590. package/dist/world/vec3.d.ts +49 -0
  591. package/dist/world/vec3.js +76 -0
  592. package/dist/world/vegetation.d.ts +71 -0
  593. package/dist/world/vegetation.js +151 -0
  594. package/dist/world/visibilityField.d.ts +154 -0
  595. package/dist/world/visibilityField.js +271 -0
  596. package/dist/world/volumetricClouds.d.ts +52 -0
  597. package/dist/world/volumetricClouds.js +43 -0
  598. package/dist/world/walls.d.ts +9 -0
  599. package/dist/world/walls.js +9 -0
  600. package/dist/world/waterKind.d.ts +55 -0
  601. package/dist/world/waterKind.js +99 -0
  602. package/dist/world.d.ts +132 -0
  603. package/dist/world.js +132 -0
  604. package/package.json +32 -8
  605. package/skills/jgengine/SKILL.md +51 -0
  606. package/skills/jgengine/api.md +434 -0
  607. package/skills/jgengine/capabilities.md +29 -0
  608. package/skills/jgengine/reference-cartridge.md +72 -0
  609. package/skills/jgengine-combat/SKILL.md +34 -0
  610. package/skills/jgengine-combat/api.md +549 -0
  611. package/skills/jgengine-combat/capabilities.md +169 -0
  612. package/skills/jgengine-combat/reference.md +98 -0
  613. package/skills/jgengine-gameplay/SKILL.md +39 -0
  614. package/skills/jgengine-gameplay/api.md +1794 -0
  615. package/skills/jgengine-gameplay/capabilities.md +378 -0
  616. package/skills/jgengine-gameplay/reference-systems.md +60 -0
  617. package/skills/jgengine-world/SKILL.md +38 -0
  618. package/skills/jgengine-world/api.md +2652 -0
  619. package/skills/jgengine-world/capabilities.md +370 -0
  620. package/skills/jgengine-world/reference.md +222 -0
  621. package/dist/cartridge/runtime.d.ts +0 -15
  622. package/dist/cartridge/runtime.js +0 -556
  623. package/dist/cartridge/spec.d.ts +0 -188
  624. package/dist/cartridge/spec.js +0 -19
  625. package/dist/cartridge/validate.d.ts +0 -2
  626. package/dist/cartridge/validate.js +0 -78
  627. package/dist/store/engineStore.d.ts +0 -22
  628. package/dist/store/engineStore.js +0 -50
  629. package/dist/store/features.d.ts +0 -10
  630. package/dist/store/features.js +0 -23
  631. package/llms.txt +0 -4983
@@ -22,9 +22,16 @@ export interface SceneEntity<TMeta = unknown> {
22
22
  role: EntityRole;
23
23
  movement: EntityMovement;
24
24
  behaviors: readonly BehaviorDescriptor[];
25
- /** Game-defined per-instance data set at `spawn`/`update` and carried to `renderEntity`/queries — narrow with a cast or type guard on read (#286.1); never encode state in the id/name string. */
25
+ /** Game-defined per-instance data set at `spawn`/`update` and carried to `renderEntity`/queries — narrow with {@link entityMetaOf} (or a type guard) on read (#286.1); never encode state in the id/name string. */
26
26
  meta: TMeta;
27
27
  }
28
+ /**
29
+ * Narrow `entity.meta` with a type guard — prefer this over `entity.meta as T` so failed shapes return `null`
30
+ * instead of lying to the type checker.
31
+ *
32
+ * @capability entity-meta cast-free narrow of SceneEntity.meta via a type guard
33
+ */
34
+ export declare function entityMetaOf<T>(entity: SceneEntity<unknown>, isMeta: (value: unknown) => value is T): T | null;
28
35
  /** Ground speed (horizontal magnitude of velocity) in world units per second. Scale to km/h or mph in game code. */
29
36
  export declare function groundSpeed(entity: SceneEntity<unknown>): number;
30
37
  export declare function movedWhileFrozen(entity: SceneEntity<unknown>, threshold?: number): boolean;
@@ -65,6 +72,28 @@ export type EntityUpdatePatch<TMeta = unknown> = Partial<Pick<SceneEntity<TMeta>
65
72
  /** Accepts the same friendly shapes as `spawn`/`setPose` (#286.13). Raw patch semantics — velocity is not derived; use `setPose` with `dt` for that. */
66
73
  position?: SpawnPositionInput;
67
74
  };
75
+ /**
76
+ * Per-entity scratch and cooldown timers, auto-cleared on despawn (#533.8) — the home for AI state
77
+ * (next-shot-at, alert level) that would otherwise be smuggled through the serializable `meta` or a
78
+ * hand-pruned module-level map. Keys share one namespace per entity: `arm`/`ready`/`remaining` store a
79
+ * deadline under a key, `get`/`set` store arbitrary scratch.
80
+ */
81
+ export interface EntityBlackboard {
82
+ /** Read a scratch value; `undefined` if unset or the entity has despawned. */
83
+ get<T>(id: string, key: string): T | undefined;
84
+ /** Write a scratch value; does not notify subscribers, and clears when the entity despawns. */
85
+ set(id: string, key: string, value: unknown): void;
86
+ has(id: string, key: string): boolean;
87
+ delete(id: string, key: string): void;
88
+ /** Drop all scratch and timers for one entity. */
89
+ clear(id: string): void;
90
+ /** Arm a cooldown for `key` that stays busy until absolute time `untilMs`. */
91
+ arm(id: string, key: string, untilMs: number): void;
92
+ /** True when no cooldown is armed for `key`, or its deadline has passed. */
93
+ ready(id: string, key: string, nowMs: number): boolean;
94
+ /** Milliseconds until the armed cooldown elapses; 0 when ready. */
95
+ remaining(id: string, key: string, nowMs: number): number;
96
+ }
68
97
  export interface EntityStore<TMeta = unknown> {
69
98
  spawn(name: string, options?: SpawnOptions<TMeta>): string;
70
99
  despawn(id: string): boolean;
@@ -74,10 +103,21 @@ export interface EntityStore<TMeta = unknown> {
74
103
  setPoseConstraint(id: string, constraint: PoseConstraint | null): void;
75
104
  get(id: string): SceneEntity<TMeta> | null;
76
105
  list(): readonly SceneEntity<TMeta>[];
106
+ /** Stable-identity list of live entity ids; identity changes only on spawn/despawn/hydrate, not on pose writes. Pair with {@link subscribeMembership} for membership-only React subscriptions that skip per-frame pose churn (#625). */
107
+ ids(): readonly string[];
77
108
  clear(): void;
78
109
  subscribe(listener: () => void): () => void;
110
+ /** Notified only when the entity set changes (spawn/despawn/hydrate), never on a pose or field update — the render tree re-reconciles on membership, individual markers read live poses imperatively. */
111
+ subscribeMembership(listener: () => void): () => void;
79
112
  snapshot(): readonly SceneEntity<TMeta>[];
113
+ /**
114
+ * Apply a `snapshot()` (e.g. from an authoritative host) to this store — the counterpart of `snapshot()`
115
+ * for host→client world mirroring: spawns entities present in the snapshot but not here, overwrites
116
+ * existing ones field-for-field (including velocity), and despawns any local entity absent from it.
117
+ */
118
+ hydrate(entities: readonly SceneEntity<TMeta>[]): void;
80
119
  spawnPoseOf(id: string): SpawnPose | null;
81
120
  resetToSpawn(id: string): boolean;
121
+ blackboard: EntityBlackboard;
82
122
  }
83
123
  export declare function createEntityStore<TMeta = unknown>(): EntityStore<TMeta>;
@@ -1,4 +1,13 @@
1
1
  import { createObservableKeyedStore } from "../store/observableKeyedStore.js";
2
+ /**
3
+ * Narrow `entity.meta` with a type guard — prefer this over `entity.meta as T` so failed shapes return `null`
4
+ * instead of lying to the type checker.
5
+ *
6
+ * @capability entity-meta cast-free narrow of SceneEntity.meta via a type guard
7
+ */
8
+ export function entityMetaOf(entity, isMeta) {
9
+ return isMeta(entity.meta) ? entity.meta : null;
10
+ }
2
11
  /** Ground speed (horizontal magnitude of velocity) in world units per second. Scale to km/h or mph in game code. */
3
12
  export function groundSpeed(entity) {
4
13
  return Math.hypot(entity.velocity[0], entity.velocity[2]);
@@ -21,7 +30,34 @@ export function createEntityStore() {
21
30
  const store = createObservableKeyedStore();
22
31
  const spawnPoses = new Map();
23
32
  const constraints = new Map();
33
+ const blackboards = new Map();
24
34
  let nextCounter = 1;
35
+ const blackboard = {
36
+ get: (id, key) => blackboards.get(id)?.get(key),
37
+ set(id, key, value) {
38
+ const board = blackboards.get(id) ?? new Map();
39
+ board.set(key, value);
40
+ blackboards.set(id, board);
41
+ },
42
+ has: (id, key) => blackboards.get(id)?.has(key) ?? false,
43
+ delete(id, key) {
44
+ blackboards.get(id)?.delete(key);
45
+ },
46
+ clear(id) {
47
+ blackboards.delete(id);
48
+ },
49
+ arm(id, key, untilMs) {
50
+ this.set(id, key, untilMs);
51
+ },
52
+ ready(id, key, nowMs) {
53
+ const until = blackboards.get(id)?.get(key);
54
+ return typeof until !== "number" || nowMs >= until;
55
+ },
56
+ remaining(id, key, nowMs) {
57
+ const until = blackboards.get(id)?.get(key);
58
+ return typeof until === "number" ? Math.max(0, until - nowMs) : 0;
59
+ },
60
+ };
25
61
  function generateId() {
26
62
  let id = `entity-${nextCounter}`;
27
63
  while (store.has(id)) {
@@ -39,6 +75,7 @@ export function createEntityStore() {
39
75
  return options.id;
40
76
  if (onExisting === "throw")
41
77
  throw new Error(`Scene entity id "${options.id}" is already spawned.`);
78
+ blackboards.delete(options.id);
42
79
  }
43
80
  const id = options.id ?? generateId();
44
81
  const position = toEntityPosition(options.position);
@@ -64,6 +101,7 @@ export function createEntityStore() {
64
101
  store.delete(id);
65
102
  spawnPoses.delete(id);
66
103
  constraints.delete(id);
104
+ blackboards.delete(id);
67
105
  return existed;
68
106
  },
69
107
  update(id, patch) {
@@ -138,18 +176,54 @@ export function createEntityStore() {
138
176
  list() {
139
177
  return store.arraySnapshot();
140
178
  },
179
+ ids() {
180
+ return store.keysSnapshot();
181
+ },
141
182
  clear() {
142
183
  for (const entity of store.arraySnapshot()) {
143
184
  store.delete(entity.id);
144
185
  }
145
186
  constraints.clear();
187
+ blackboards.clear();
146
188
  },
147
189
  subscribe(listener) {
148
190
  return store.subscribe(listener);
149
191
  },
192
+ subscribeMembership(listener) {
193
+ return store.subscribeMembership(listener);
194
+ },
150
195
  snapshot() {
151
196
  return store.arraySnapshot();
152
197
  },
198
+ hydrate(entities) {
199
+ const incoming = new Set(entities.map((entity) => entity.id));
200
+ for (const current of store.arraySnapshot()) {
201
+ if (!incoming.has(current.id)) {
202
+ store.delete(current.id);
203
+ spawnPoses.delete(current.id);
204
+ constraints.delete(current.id);
205
+ blackboards.delete(current.id);
206
+ }
207
+ }
208
+ for (const entity of entities) {
209
+ store.set(entity.id, {
210
+ id: entity.id,
211
+ name: entity.name,
212
+ position: entity.position,
213
+ rotationY: entity.rotationY,
214
+ rotationX: entity.rotationX,
215
+ rotationZ: entity.rotationZ,
216
+ velocity: entity.velocity,
217
+ role: entity.role,
218
+ movement: entity.movement,
219
+ behaviors: entity.behaviors,
220
+ meta: entity.meta,
221
+ });
222
+ if (!spawnPoses.has(entity.id)) {
223
+ spawnPoses.set(entity.id, { position: entity.position, rotationY: entity.rotationY });
224
+ }
225
+ }
226
+ },
153
227
  spawnPoseOf(id) {
154
228
  return spawnPoses.get(id) ?? null;
155
229
  },
@@ -164,5 +238,6 @@ export function createEntityStore() {
164
238
  store.set(id, current);
165
239
  return true;
166
240
  },
241
+ blackboard,
167
242
  };
168
243
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The forward-axis convention: a generator or scene kind declares which way its "front" faces (a
3
+ * bookcase's open/book face, a building's entrance) once, as data, instead of leaving every placement
4
+ * to hand-tuned `rotationY` trial-and-error. `StudioStage`'s `faceCamera` (`@jgengine/shell/scene/
5
+ * StudioStage`) reads the declared axis to auto-orient a product shot; a placement tool can read the
6
+ * same field to face a freshly dropped asset toward the camera/path by default. `DEFAULT_FORWARD`
7
+ * (+Z) is what a generator/scene-kind gets when it omits `forward` — build your front toward it.
8
+ * @capability forward-axis declared front convention for parametric assets — auto-orient product shots
9
+ */
10
+ export declare const DEFAULT_FORWARD: readonly [number, number, number];
11
+ /**
12
+ * The yaw (radians, around Y) that rotates `forward` so it points from `origin` toward `target`, both
13
+ * XZ points. Pure — no three.js — so `StudioStage.faceCamera` and any future placement tool share one
14
+ * tested formula instead of re-deriving atan2 math per call site. Only `forward`'s X/Z components
15
+ * matter (yaw is a rotation about Y); returns 0 when `origin` and `target` coincide.
16
+ * @internal — consumed through `StudioStage`'s `faceCamera` prop, not called directly by game code.
17
+ */
18
+ export declare function yawToFace(forward: readonly [number, number, number], origin: readonly [number, number], target: readonly [number, number]): number;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The forward-axis convention: a generator or scene kind declares which way its "front" faces (a
3
+ * bookcase's open/book face, a building's entrance) once, as data, instead of leaving every placement
4
+ * to hand-tuned `rotationY` trial-and-error. `StudioStage`'s `faceCamera` (`@jgengine/shell/scene/
5
+ * StudioStage`) reads the declared axis to auto-orient a product shot; a placement tool can read the
6
+ * same field to face a freshly dropped asset toward the camera/path by default. `DEFAULT_FORWARD`
7
+ * (+Z) is what a generator/scene-kind gets when it omits `forward` — build your front toward it.
8
+ * @capability forward-axis declared front convention for parametric assets — auto-orient product shots
9
+ */
10
+ export const DEFAULT_FORWARD = [0, 0, 1];
11
+ /**
12
+ * The yaw (radians, around Y) that rotates `forward` so it points from `origin` toward `target`, both
13
+ * XZ points. Pure — no three.js — so `StudioStage.faceCamera` and any future placement tool share one
14
+ * tested formula instead of re-deriving atan2 math per call site. Only `forward`'s X/Z components
15
+ * matter (yaw is a rotation about Y); returns 0 when `origin` and `target` coincide.
16
+ * @internal — consumed through `StudioStage`'s `faceCamera` prop, not called directly by game code.
17
+ */
18
+ export function yawToFace(forward, origin, target) {
19
+ const dx = target[0] - origin[0];
20
+ const dz = target[1] - origin[1];
21
+ if (dx === 0 && dz === 0)
22
+ return 0;
23
+ const angleToTarget = Math.atan2(dx, dz);
24
+ const angleForward = Math.atan2(forward[0], forward[2]);
25
+ return angleToTarget - angleForward;
26
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Generic named-socket reader for loaded 3D models. Walks a node tree (any object with `.name`,
3
+ * `.position`, and `.children` — structurally satisfied by `THREE.Object3D`) and collects the local
4
+ * offsets of nodes whose name marks an attachment point. Genre-agnostic: wire anchors on a pylon,
5
+ * muzzle/hand mounts on a character, hardpoints on a ship, seat/decal slots on furniture — anything
6
+ * an artist tags with an empty in the GLB. Pure data (no three.js import), so it lives in core.
7
+ *
8
+ * @capability model-sockets named attachment points read from a model
9
+ */
10
+ /** Minimal shape of a model node this reader walks — structurally satisfied by `THREE.Object3D`. */
11
+ export interface ModelNode {
12
+ name: string;
13
+ position: {
14
+ x: number;
15
+ y: number;
16
+ z: number;
17
+ };
18
+ children?: readonly ModelNode[];
19
+ }
20
+ /** One resolved socket: its node name and local-space offset from the model origin. */
21
+ export interface ModelSocket {
22
+ name: string;
23
+ offset: readonly [number, number, number];
24
+ }
25
+ /** Default socket-name matcher: "socket", "wire", "attach", "anchor", "mount", "hardpoint" (any case). */
26
+ export declare const SOCKET_PATTERN: RegExp;
27
+ /**
28
+ * Depth-first collect every socket-named node's local offset, sorted by descending Y then ascending X
29
+ * so socket indices are stable across loads (top first, left-to-right). Empty when the model tags
30
+ * none — callers then fall back to computed offsets. Pass a custom `pattern` for a bespoke naming
31
+ * convention.
32
+ */
33
+ export declare function readNamedSockets(root: ModelNode, pattern?: RegExp): ModelSocket[];
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Generic named-socket reader for loaded 3D models. Walks a node tree (any object with `.name`,
3
+ * `.position`, and `.children` — structurally satisfied by `THREE.Object3D`) and collects the local
4
+ * offsets of nodes whose name marks an attachment point. Genre-agnostic: wire anchors on a pylon,
5
+ * muzzle/hand mounts on a character, hardpoints on a ship, seat/decal slots on furniture — anything
6
+ * an artist tags with an empty in the GLB. Pure data (no three.js import), so it lives in core.
7
+ *
8
+ * @capability model-sockets named attachment points read from a model
9
+ */
10
+ /** Default socket-name matcher: "socket", "wire", "attach", "anchor", "mount", "hardpoint" (any case). */
11
+ export const SOCKET_PATTERN = /socket|wire|attach|anchor|mount|hardpoint/i;
12
+ /**
13
+ * Depth-first collect every socket-named node's local offset, sorted by descending Y then ascending X
14
+ * so socket indices are stable across loads (top first, left-to-right). Empty when the model tags
15
+ * none — callers then fall back to computed offsets. Pass a custom `pattern` for a bespoke naming
16
+ * convention.
17
+ */
18
+ export function readNamedSockets(root, pattern = SOCKET_PATTERN) {
19
+ const found = [];
20
+ const walk = (node) => {
21
+ if (pattern.test(node.name))
22
+ found.push({ name: node.name, offset: [node.position.x, node.position.y, node.position.z] });
23
+ for (const child of node.children ?? [])
24
+ walk(child);
25
+ };
26
+ walk(root);
27
+ found.sort((a, b) => b.offset[1] - a.offset[1] || a.offset[0] - b.offset[0]);
28
+ return found;
29
+ }
@@ -24,6 +24,8 @@ declare function intersectAabb(origin: EntityPosition, direction: EntityPosition
24
24
  distance: number;
25
25
  normal: EntityPosition;
26
26
  } | null;
27
+ /** @internal */
27
28
  export declare function raycastObjects(source: ObjectRaycastSource, input: ObjectRaycastInput): ObjectRaycastHit | null;
29
+ /** @internal */
28
30
  export declare function raycastObjectsAll(source: ObjectRaycastSource, input: ObjectRaycastInput): ObjectRaycastHit[];
29
31
  export { intersectAabb, normalize as normalizeDirection };
@@ -102,6 +102,7 @@ function resolveCandidates(source, origin, direction, maxDistance, halfExtents)
102
102
  const bounds = raySegmentBounds(origin, direction, maxDistance, halfExtents);
103
103
  return source.inBox(bounds.min, bounds.max);
104
104
  }
105
+ /** @internal */
105
106
  export function raycastObjects(source, input) {
106
107
  const direction = normalize(input.direction);
107
108
  if (direction[0] === 0 && direction[1] === 0 && direction[2] === 0)
@@ -120,6 +121,7 @@ export function raycastObjects(source, input) {
120
121
  }
121
122
  return nearest;
122
123
  }
124
+ /** @internal */
123
125
  export function raycastObjectsAll(source, input) {
124
126
  const direction = normalize(input.direction);
125
127
  if (direction[0] === 0 && direction[1] === 0 && direction[2] === 0)
@@ -31,10 +31,14 @@ export interface ObjectStore {
31
31
  setVisual(instanceId: string, visual: ObjectVisual | undefined): boolean;
32
32
  get(instanceId: string): SceneObject | null;
33
33
  list(filter?: ObjectListFilter): readonly SceneObject[];
34
+ /** Stable-identity list of all placed object ids; identity changes only on place/remove, not on move/rotate/setVisual. Pair with {@link subscribeMembership} for membership-only React subscriptions (#625). */
35
+ ids(): readonly string[];
34
36
  at(x: number, y: number, z: number, tolerance?: number): SceneObject[];
35
37
  inBox(min: EntityPosition, max: EntityPosition): readonly SceneObject[];
36
38
  clear(): void;
37
39
  subscribe(listener: () => void): () => void;
40
+ /** Notified only when the object set changes (place/remove), never on move/rotate/setVisual — markers read live poses imperatively. */
41
+ subscribeMembership(listener: () => void): () => void;
38
42
  snapshot(): readonly SceneObject[];
39
43
  }
40
44
  export declare function createObjectStore(): ObjectStore;
@@ -112,6 +112,9 @@ export function createObjectStore() {
112
112
  return all;
113
113
  return all.filter((object) => object.parentSpace === filter.parentSpace);
114
114
  },
115
+ ids() {
116
+ return store.keysSnapshot();
117
+ },
115
118
  at(x, y, z, tolerance = 0) {
116
119
  const minCx = cellIndexOf(x - tolerance);
117
120
  const maxCx = cellIndexOf(x + tolerance);
@@ -180,6 +183,9 @@ export function createObjectStore() {
180
183
  subscribe(listener) {
181
184
  return store.subscribe(listener);
182
185
  },
186
+ subscribeMembership(listener) {
187
+ return store.subscribeMembership(listener);
188
+ },
183
189
  snapshot() {
184
190
  return store.arraySnapshot();
185
191
  },
@@ -17,6 +17,10 @@ export interface PossessionDeps {
17
17
  entities: PossessionEntities;
18
18
  events?: PossessionEvents;
19
19
  }
20
+ export interface PossessionSnapshot {
21
+ owned: Record<string, readonly string[]>;
22
+ active: Record<string, string>;
23
+ }
20
24
  export interface Possession {
21
25
  own(userId: string, entityId: string): void;
22
26
  disown(userId: string, entityId: string): void;
@@ -26,5 +30,9 @@ export interface Possession {
26
30
  possess(userId: string, entityId: string): {
27
31
  reason: string;
28
32
  } | null;
33
+ /** Snapshot every user's owned entities and active pawn for a whole-world save. */
34
+ snapshotAll(): PossessionSnapshot;
35
+ /** Restore every user's owned entities and active pawn from a {@link snapshotAll} payload. Entity roles are restored by the entity snapshot, not re-applied here. */
36
+ hydrateAll(state: PossessionSnapshot): void;
29
37
  }
30
38
  export declare function createPossession(deps: PossessionDeps): Possession;
@@ -47,5 +47,19 @@ export function createPossession(deps) {
47
47
  deps.events?.emit("possession.swapped", { userId, entityId, previousEntityId });
48
48
  return null;
49
49
  },
50
+ snapshotAll() {
51
+ const ownedOut = {};
52
+ for (const [userId, set] of owned)
53
+ ownedOut[userId] = Array.from(set);
54
+ return { owned: ownedOut, active: Object.fromEntries(activeByUser) };
55
+ },
56
+ hydrateAll(state) {
57
+ owned.clear();
58
+ for (const [userId, ids] of Object.entries(state.owned))
59
+ owned.set(userId, new Set(ids));
60
+ activeByUser.clear();
61
+ for (const [userId, entityId] of Object.entries(state.active))
62
+ activeByUser.set(userId, entityId);
63
+ },
50
64
  };
51
65
  }
@@ -18,6 +18,9 @@ export interface Roster {
18
18
  setEquipped(userId: string, entryId: string, equipped: boolean): RosterEntry | null;
19
19
  snapshot(userId: string): readonly RosterEntry[];
20
20
  hydrate(userId: string, entries: readonly RosterEntry[]): void;
21
+ /** Whole-store capture across every owner — the world-save/replication seam (per-owner `snapshot` can't enumerate owners). */
22
+ snapshotAll(): Record<string, readonly RosterEntry[]>;
23
+ hydrateAll(data: Record<string, readonly RosterEntry[]>): void;
21
24
  }
22
25
  export interface RosterDeps {
23
26
  now?: () => number;
@@ -53,5 +53,17 @@ export function createRoster(deps = {}) {
53
53
  hydrate(userId, entries) {
54
54
  rosters.set(userId, new Map(entries.map((entry) => [entry.id, entry])));
55
55
  },
56
+ snapshotAll() {
57
+ const out = {};
58
+ for (const [userId, entries] of rosters)
59
+ out[userId] = Array.from(entries.values());
60
+ return out;
61
+ },
62
+ hydrateAll(data) {
63
+ rosters.clear();
64
+ for (const [userId, entries] of Object.entries(data)) {
65
+ rosters.set(userId, new Map(entries.map((entry) => [entry.id, entry])));
66
+ }
67
+ },
56
68
  };
57
69
  }