@jgengine/core 0.10.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 (607) hide show
  1. package/CHANGELOG.md +13 -2
  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 +7 -2
  21. package/dist/ai/spawnDirector.js +18 -15
  22. package/dist/ai/spawnPoint.d.ts +3 -1
  23. package/dist/ai/spawnPoint.js +3 -1
  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/authoring.d.ts +1 -0
  35. package/dist/authoring.js +1 -0
  36. package/dist/board/laneBoard.d.ts +13 -0
  37. package/dist/board/laneBoard.js +13 -0
  38. package/dist/board/timelineBoard.d.ts +10 -0
  39. package/dist/board/timelineBoard.js +10 -0
  40. package/dist/combat/abilityKit.d.ts +18 -0
  41. package/dist/combat/abilityKit.js +24 -9
  42. package/dist/combat/animationState.d.ts +5 -0
  43. package/dist/combat/animationState.js +5 -0
  44. package/dist/combat/breakMeters.d.ts +10 -0
  45. package/dist/combat/breakMeters.js +10 -0
  46. package/dist/combat/castRunner.d.ts +5 -0
  47. package/dist/combat/castRunner.js +5 -0
  48. package/dist/combat/comboPoints.d.ts +5 -0
  49. package/dist/combat/comboPoints.js +5 -0
  50. package/dist/combat/comboString.d.ts +5 -0
  51. package/dist/combat/comboString.js +5 -0
  52. package/dist/combat/damageInterceptors.d.ts +192 -0
  53. package/dist/combat/damageInterceptors.js +251 -0
  54. package/dist/combat/damageMatchup.d.ts +68 -0
  55. package/dist/combat/damageMatchup.js +42 -0
  56. package/dist/combat/damageResolution.d.ts +63 -0
  57. package/dist/combat/damageResolution.js +50 -0
  58. package/dist/combat/death.d.ts +7 -1
  59. package/dist/combat/death.js +5 -0
  60. package/dist/combat/deathReason.d.ts +14 -0
  61. package/dist/combat/deathReason.js +1 -0
  62. package/dist/combat/defensiveWindow.d.ts +5 -0
  63. package/dist/combat/defensiveWindow.js +5 -0
  64. package/dist/combat/dotField.d.ts +5 -1
  65. package/dist/combat/dotField.js +5 -1
  66. package/dist/combat/downed.d.ts +5 -0
  67. package/dist/combat/downed.js +5 -0
  68. package/dist/combat/effects.d.ts +5 -0
  69. package/dist/combat/effects.js +5 -0
  70. package/dist/combat/encounterSequence.d.ts +258 -0
  71. package/dist/combat/encounterSequence.js +426 -0
  72. package/dist/combat/hitReaction.d.ts +57 -1
  73. package/dist/combat/hitReaction.js +45 -5
  74. package/dist/combat/magazine.d.ts +54 -0
  75. package/dist/combat/magazine.js +96 -0
  76. package/dist/combat/projectiles.d.ts +5 -0
  77. package/dist/combat/projectiles.js +32 -14
  78. package/dist/combat/receivedDamage.d.ts +117 -0
  79. package/dist/combat/receivedDamage.js +92 -0
  80. package/dist/combat/regenShield.d.ts +5 -1
  81. package/dist/combat/regenShield.js +5 -1
  82. package/dist/combat/renderCues.d.ts +51 -0
  83. package/dist/combat/renderCues.js +44 -0
  84. package/dist/combat/resourcePool.d.ts +5 -0
  85. package/dist/combat/resourcePool.js +5 -0
  86. package/dist/combat/rewardAllocation.d.ts +121 -0
  87. package/dist/combat/rewardAllocation.js +251 -0
  88. package/dist/combat/shotOrigin.d.ts +18 -1
  89. package/dist/combat/shotOrigin.js +39 -0
  90. package/dist/combat/statusApplication.d.ts +96 -0
  91. package/dist/combat/statusApplication.js +81 -0
  92. package/dist/combat/telegraph.d.ts +11 -2
  93. package/dist/combat/telegraph.js +11 -2
  94. package/dist/combat/thresholdCrossings.d.ts +85 -0
  95. package/dist/combat/thresholdCrossings.js +116 -0
  96. package/dist/combat.d.ts +34 -0
  97. package/dist/combat.js +34 -0
  98. package/dist/commands/commandRegistry.d.ts +11 -0
  99. package/dist/commands/commandRegistry.js +9 -2
  100. package/dist/crafting/crop.d.ts +18 -0
  101. package/dist/crafting/crop.js +18 -0
  102. package/dist/crafting/production.d.ts +5 -0
  103. package/dist/crafting/production.js +5 -0
  104. package/dist/devtools/rewriteTunables.d.ts +17 -0
  105. package/dist/devtools/rewriteTunables.js +276 -0
  106. package/dist/devtools/saveEndpoint.d.ts +46 -0
  107. package/dist/devtools/saveEndpoint.js +48 -0
  108. package/dist/devtools/transformTunables.d.ts +3 -0
  109. package/dist/devtools/transformTunables.js +3 -0
  110. package/dist/devtools/tunableSchema.d.ts +31 -0
  111. package/dist/devtools/tunableSchema.js +31 -0
  112. package/dist/economy/currency.d.ts +12 -1
  113. package/dist/economy/currency.js +12 -1
  114. package/dist/economy/listingBook.d.ts +91 -0
  115. package/dist/economy/listingBook.js +144 -0
  116. package/dist/economy/resourceLedger.d.ts +222 -0
  117. package/dist/economy/resourceLedger.js +353 -0
  118. package/dist/economy/sharedWallet.d.ts +14 -0
  119. package/dist/economy/sharedWallet.js +14 -0
  120. package/dist/economy/techTree.d.ts +12 -0
  121. package/dist/economy/techTree.js +12 -0
  122. package/dist/economy/wallet.d.ts +26 -2
  123. package/dist/economy/wallet.js +35 -6
  124. package/dist/editor/commands.d.ts +190 -7
  125. package/dist/editor/commands.js +727 -55
  126. package/dist/editor/document.d.ts +159 -13
  127. package/dist/editor/document.js +750 -19
  128. package/dist/editor/grid.d.ts +229 -0
  129. package/dist/editor/grid.js +366 -0
  130. package/dist/editor/gridAdapters.d.ts +80 -0
  131. package/dist/editor/gridAdapters.js +134 -0
  132. package/dist/editor/index.d.ts +73 -6
  133. package/dist/editor/index.js +6 -2
  134. package/dist/editor/liveSync.d.ts +127 -0
  135. package/dist/editor/liveSync.js +249 -0
  136. package/dist/editor/runtimeInspector.d.ts +88 -0
  137. package/dist/editor/runtimeInspector.js +239 -0
  138. package/dist/editor/types.d.ts +107 -1
  139. package/dist/faction/reputation.d.ts +5 -0
  140. package/dist/faction/reputation.js +5 -0
  141. package/dist/format/distance.d.ts +17 -0
  142. package/dist/format/distance.js +18 -0
  143. package/dist/format/duration.d.ts +27 -0
  144. package/dist/format/duration.js +45 -0
  145. package/dist/format/speed.d.ts +17 -0
  146. package/dist/format/speed.js +25 -0
  147. package/dist/game/connectedPlayers.d.ts +6 -4
  148. package/dist/game/connectedPlayers.js +2 -2
  149. package/dist/game/cosmetics.d.ts +9 -0
  150. package/dist/game/cosmetics.js +16 -0
  151. package/dist/game/defineGame.d.ts +100 -2
  152. package/dist/game/defineGame.js +39 -2
  153. package/dist/game/defineSystem.d.ts +88 -0
  154. package/dist/game/defineSystem.js +45 -0
  155. package/dist/game/dialogue.d.ts +33 -0
  156. package/dist/game/dialogue.js +21 -0
  157. package/dist/game/events.d.ts +35 -13
  158. package/dist/game/events.js +5 -0
  159. package/dist/game/feed.d.ts +33 -0
  160. package/dist/game/feed.js +35 -2
  161. package/dist/game/gamePhase.d.ts +11 -0
  162. package/dist/game/gamePhase.js +16 -0
  163. package/dist/game/leaderboard.d.ts +5 -0
  164. package/dist/game/leaderboard.js +5 -0
  165. package/dist/game/loadout.d.ts +5 -0
  166. package/dist/game/loadout.js +5 -0
  167. package/dist/game/lootFilter.d.ts +2 -0
  168. package/dist/game/lootFilter.js +2 -0
  169. package/dist/game/lootPipeline.d.ts +164 -0
  170. package/dist/game/lootPipeline.js +216 -0
  171. package/dist/game/lootTable.d.ts +19 -2
  172. package/dist/game/lootTable.js +15 -5
  173. package/dist/game/objectives.d.ts +43 -0
  174. package/dist/game/objectives.js +36 -0
  175. package/dist/game/paramLayers.d.ts +148 -0
  176. package/dist/game/paramLayers.js +185 -0
  177. package/dist/game/ping.d.ts +5 -0
  178. package/dist/game/ping.js +5 -0
  179. package/dist/game/playableGame.d.ts +92 -7
  180. package/dist/game/quest.d.ts +8 -0
  181. package/dist/game/quest.js +29 -0
  182. package/dist/game/race.d.ts +141 -0
  183. package/dist/game/race.js +169 -0
  184. package/dist/game/recordBook.d.ts +3 -1
  185. package/dist/game/recordBook.js +4 -1
  186. package/dist/game/ruleSelection.d.ts +75 -0
  187. package/dist/game/ruleSelection.js +127 -0
  188. package/dist/game/runDraft.d.ts +5 -0
  189. package/dist/game/runDraft.js +5 -0
  190. package/dist/game/saveStore.d.ts +111 -0
  191. package/dist/game/saveStore.js +312 -0
  192. package/dist/game/snapshotHistory.d.ts +67 -0
  193. package/dist/game/snapshotHistory.js +95 -0
  194. package/dist/game/social.d.ts +38 -1
  195. package/dist/game/social.js +71 -0
  196. package/dist/game/spawnPoints.d.ts +5 -0
  197. package/dist/game/spawnPoints.js +5 -0
  198. package/dist/game/systemRuntime.d.ts +50 -0
  199. package/dist/game/systemRuntime.js +157 -0
  200. package/dist/game/systemSchedule.d.ts +72 -0
  201. package/dist/game/systemSchedule.js +242 -0
  202. package/dist/game/toasts.d.ts +43 -0
  203. package/dist/game/toasts.js +44 -0
  204. package/dist/game/trade.d.ts +10 -0
  205. package/dist/game/trade.js +10 -0
  206. package/dist/game/unlocks.d.ts +8 -0
  207. package/dist/game/unlocks.js +16 -0
  208. package/dist/game/vfxInstance.d.ts +138 -0
  209. package/dist/game/vfxInstance.js +96 -0
  210. package/dist/game/worldItem.d.ts +17 -4
  211. package/dist/game/worldItem.js +17 -4
  212. package/dist/gameplay.d.ts +91 -0
  213. package/dist/gameplay.js +91 -0
  214. package/dist/index.d.ts +5 -14
  215. package/dist/index.js +5 -14
  216. package/dist/input/actionBindings.d.ts +23 -6
  217. package/dist/input/actionBindings.js +23 -6
  218. package/dist/input/axisInput.d.ts +7 -2
  219. package/dist/input/axisInput.js +7 -2
  220. package/dist/input/controlGroups.d.ts +67 -0
  221. package/dist/input/controlGroups.js +41 -0
  222. package/dist/input/touchScheme.d.ts +82 -6
  223. package/dist/input/touchScheme.js +123 -10
  224. package/dist/interaction/lockpick.d.ts +61 -0
  225. package/dist/interaction/lockpick.js +168 -0
  226. package/dist/interaction/proximityPrompt.d.ts +2 -0
  227. package/dist/interaction/proximityPrompt.js +2 -0
  228. package/dist/interaction/qte.d.ts +5 -0
  229. package/dist/interaction/qte.js +5 -0
  230. package/dist/interaction/skillCheck.d.ts +5 -0
  231. package/dist/interaction/skillCheck.js +5 -0
  232. package/dist/inventory/inventoryModel.d.ts +12 -0
  233. package/dist/inventory/inventoryModel.js +12 -0
  234. package/dist/inventory/shapedGrid.d.ts +16 -0
  235. package/dist/inventory/shapedGrid.js +16 -0
  236. package/dist/inventory/slotModel.d.ts +10 -0
  237. package/dist/inventory/slotModel.js +10 -0
  238. package/dist/item/durability.d.ts +5 -0
  239. package/dist/item/durability.js +5 -0
  240. package/dist/item/itemIdentity.d.ts +171 -0
  241. package/dist/item/itemIdentity.js +138 -0
  242. package/dist/item/itemInstanceRegistry.d.ts +32 -0
  243. package/dist/item/itemInstanceRegistry.js +34 -0
  244. package/dist/item/itemgen.d.ts +163 -0
  245. package/dist/item/itemgen.js +151 -0
  246. package/dist/item/modularItem.d.ts +5 -0
  247. package/dist/item/modularItem.js +5 -0
  248. package/dist/item/use.d.ts +5 -0
  249. package/dist/item/use.js +5 -0
  250. package/dist/item/useBehavior.d.ts +142 -0
  251. package/dist/item/useBehavior.js +105 -0
  252. package/dist/item/weapon.d.ts +5 -0
  253. package/dist/item/weapon.js +5 -0
  254. package/dist/math/scalar.d.ts +25 -0
  255. package/dist/math/scalar.js +47 -0
  256. package/dist/meta/changelog.d.ts +4 -1
  257. package/dist/meta/changelog.js +16 -2
  258. package/dist/movement/avoidance.d.ts +45 -0
  259. package/dist/movement/avoidance.js +123 -0
  260. package/dist/movement/cameraRig.d.ts +8 -0
  261. package/dist/movement/cameraRig.js +8 -0
  262. package/dist/movement/dash.d.ts +11 -0
  263. package/dist/movement/dash.js +11 -0
  264. package/dist/movement/formation.d.ts +135 -0
  265. package/dist/movement/formation.js +194 -0
  266. package/dist/movement/glideModel.d.ts +5 -0
  267. package/dist/movement/glideModel.js +5 -0
  268. package/dist/movement/grappleSwing.d.ts +5 -0
  269. package/dist/movement/grappleSwing.js +5 -0
  270. package/dist/movement/leaderTrail.d.ts +5 -0
  271. package/dist/movement/leaderTrail.js +5 -0
  272. package/dist/movement/movementModel.d.ts +35 -8
  273. package/dist/movement/movementModel.js +42 -14
  274. package/dist/movement/playerMovement.js +65 -10
  275. package/dist/movement/poseState.d.ts +13 -0
  276. package/dist/movement/poseState.js +16 -0
  277. package/dist/movement/steering.d.ts +8 -0
  278. package/dist/movement/steering.js +18 -0
  279. package/dist/multiplayer/combatSnapshot.d.ts +3 -0
  280. package/dist/multiplayer/combatSnapshot.js +3 -0
  281. package/dist/multiplayer/lagCompensation.d.ts +5 -0
  282. package/dist/multiplayer/lagCompensation.js +5 -0
  283. package/dist/multiplayer/presenceModel.d.ts +9 -1
  284. package/dist/multiplayer/presenceModel.js +9 -1
  285. package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
  286. package/dist/multiplayer/simultaneousCommit.js +3 -0
  287. package/dist/multiplayer.d.ts +11 -0
  288. package/dist/multiplayer.js +11 -0
  289. package/dist/nav/pathFollow.d.ts +57 -0
  290. package/dist/nav/pathFollow.js +109 -0
  291. package/dist/orders/orderKinds.d.ts +156 -0
  292. package/dist/orders/orderKinds.js +197 -0
  293. package/dist/orders/orderQueue.d.ts +208 -0
  294. package/dist/orders/orderQueue.js +211 -0
  295. package/dist/physics/drivableVehicle.d.ts +29 -0
  296. package/dist/physics/drivableVehicle.js +16 -0
  297. package/dist/physics/kinematicVehicle.d.ts +21 -1
  298. package/dist/physics/kinematicVehicle.js +23 -8
  299. package/dist/physics/physicsWorld.d.ts +24 -12
  300. package/dist/physics/physicsWorld.js +11 -5
  301. package/dist/physics/radialImpulse.d.ts +25 -0
  302. package/dist/physics/radialImpulse.js +27 -0
  303. package/dist/procedural.d.ts +3 -0
  304. package/dist/procedural.js +3 -0
  305. package/dist/progression/statGraph.d.ts +116 -0
  306. package/dist/progression/statGraph.js +318 -0
  307. package/dist/puzzle/cellGrid.d.ts +9 -0
  308. package/dist/puzzle/cellGrid.js +9 -0
  309. package/dist/puzzle/fallingPiece.d.ts +9 -0
  310. package/dist/puzzle/fallingPiece.js +9 -0
  311. package/dist/puzzle/nonogram.d.ts +39 -0
  312. package/dist/puzzle/nonogram.js +136 -0
  313. package/dist/random/nameGen.d.ts +5 -0
  314. package/dist/random/nameGen.js +5 -0
  315. package/dist/random/pick.d.ts +8 -0
  316. package/dist/random/pick.js +31 -0
  317. package/dist/random/rng.d.ts +22 -0
  318. package/dist/random/rng.js +28 -8
  319. package/dist/random/seedLink.d.ts +4 -0
  320. package/dist/random/seedLink.js +4 -0
  321. package/dist/relation/keyedValues.d.ts +54 -0
  322. package/dist/relation/keyedValues.js +115 -0
  323. package/dist/relation/thresholds.d.ts +62 -0
  324. package/dist/relation/thresholds.js +62 -0
  325. package/dist/render/color.d.ts +12 -0
  326. package/dist/render/color.js +26 -0
  327. package/dist/render/lookPreset.d.ts +41 -0
  328. package/dist/render/lookPreset.js +29 -0
  329. package/dist/render/postProcessing.d.ts +20 -0
  330. package/dist/render/postProcessing.js +21 -1
  331. package/dist/rules/predicate.d.ts +53 -0
  332. package/dist/rules/predicate.js +64 -0
  333. package/dist/rules/ruleEffects.d.ts +38 -0
  334. package/dist/rules/ruleEffects.js +37 -0
  335. package/dist/rules/triggeredRules.d.ts +160 -0
  336. package/dist/rules/triggeredRules.js +241 -0
  337. package/dist/runtime/adapter.d.ts +42 -3
  338. package/dist/runtime/adapter.js +44 -1
  339. package/dist/runtime/cameraDirector.d.ts +1 -0
  340. package/dist/runtime/cameraDirector.js +1 -0
  341. package/dist/runtime/commandRunner.d.ts +1 -0
  342. package/dist/runtime/commandRunner.js +1 -0
  343. package/dist/runtime/context/combatFx.d.ts +23 -0
  344. package/dist/runtime/context/combatFx.js +161 -0
  345. package/dist/runtime/context/registries.d.ts +13 -0
  346. package/dist/runtime/context/registries.js +84 -0
  347. package/dist/runtime/context/worldItems.d.ts +21 -0
  348. package/dist/runtime/context/worldItems.js +37 -0
  349. package/dist/runtime/descriptors/baseline.d.ts +48 -0
  350. package/dist/runtime/descriptors/baseline.js +134 -0
  351. package/dist/runtime/descriptors/features.d.ts +74 -0
  352. package/dist/runtime/descriptors/features.js +281 -0
  353. package/dist/runtime/gameContext.d.ts +114 -13
  354. package/dist/runtime/gameContext.js +303 -395
  355. package/dist/runtime/gameRuntime.d.ts +1 -0
  356. package/dist/runtime/gameRuntime.js +1 -0
  357. package/dist/runtime/headlessRunner.d.ts +60 -0
  358. package/dist/runtime/headlessRunner.js +44 -0
  359. package/dist/runtime/hostPersistence.d.ts +12 -0
  360. package/dist/runtime/hostPersistence.js +12 -0
  361. package/dist/runtime/hostedGameRunner.d.ts +8 -3
  362. package/dist/runtime/hostedGameRunner.js +26 -3
  363. package/dist/runtime/hostedWorldSession.d.ts +12 -4
  364. package/dist/runtime/hostedWorldSession.js +11 -4
  365. package/dist/runtime/inputSnapshot.d.ts +8 -3
  366. package/dist/runtime/inputSnapshot.js +6 -2
  367. package/dist/runtime/motionIntents.d.ts +11 -2
  368. package/dist/runtime/motionIntents.js +16 -2
  369. package/dist/runtime/perContext.d.ts +15 -0
  370. package/dist/runtime/perContext.js +21 -0
  371. package/dist/runtime/runtimeSave.d.ts +79 -0
  372. package/dist/runtime/runtimeSave.js +105 -0
  373. package/dist/runtime/save.d.ts +4 -0
  374. package/dist/runtime/save.js +4 -0
  375. package/dist/runtime/snapshot.d.ts +7 -0
  376. package/dist/runtime/snapshot.js +7 -0
  377. package/dist/runtime/visibility.d.ts +2 -1
  378. package/dist/runtime/visibility.js +2 -1
  379. package/dist/runtime/worldChannel.d.ts +7 -3
  380. package/dist/runtime/worldChannel.js +51 -6
  381. package/dist/runtime/worldMirror.d.ts +14 -2
  382. package/dist/runtime/worldMirror.js +15 -2
  383. package/dist/runtime/worldProjection.d.ts +47 -0
  384. package/dist/runtime/worldProjection.js +52 -0
  385. package/dist/runtime/worldReplication.d.ts +30 -7
  386. package/dist/runtime/worldReplication.js +41 -9
  387. package/dist/runtime/worldSnapshot.d.ts +30 -3
  388. package/dist/runtime/worldSnapshot.js +20 -5
  389. package/dist/scene/assetCatalog.d.ts +21 -0
  390. package/dist/scene/assetCatalog.js +4 -0
  391. package/dist/scene/assetDiagnostics.d.ts +69 -0
  392. package/dist/scene/assetDiagnostics.js +110 -0
  393. package/dist/scene/assetGenerator.d.ts +65 -0
  394. package/dist/scene/assetGenerator.js +64 -0
  395. package/dist/scene/assetSpace.d.ts +137 -0
  396. package/dist/scene/assetSpace.js +259 -0
  397. package/dist/scene/authoredTriggers.d.ts +169 -0
  398. package/dist/scene/authoredTriggers.js +340 -0
  399. package/dist/scene/behaviorRuntime.d.ts +75 -0
  400. package/dist/scene/behaviorRuntime.js +217 -0
  401. package/dist/scene/behaviors.d.ts +14 -2
  402. package/dist/scene/behaviors.js +7 -2
  403. package/dist/scene/bodyBind.d.ts +60 -0
  404. package/dist/scene/bodyBind.js +51 -0
  405. package/dist/scene/builtinSceneKinds.d.ts +5 -0
  406. package/dist/scene/builtinSceneKinds.js +62 -0
  407. package/dist/scene/colliders.d.ts +13 -1
  408. package/dist/scene/colliders.js +37 -1
  409. package/dist/scene/entityStats.d.ts +11 -2
  410. package/dist/scene/entityStats.js +11 -2
  411. package/dist/scene/entityStore.d.ts +12 -1
  412. package/dist/scene/entityStore.js +15 -0
  413. package/dist/scene/facing.d.ts +18 -0
  414. package/dist/scene/facing.js +26 -0
  415. package/dist/scene/modelSockets.d.ts +33 -0
  416. package/dist/scene/modelSockets.js +29 -0
  417. package/dist/scene/objectQuery.d.ts +2 -0
  418. package/dist/scene/objectQuery.js +2 -0
  419. package/dist/scene/objectStore.d.ts +4 -0
  420. package/dist/scene/objectStore.js +6 -0
  421. package/dist/scene/possession.d.ts +8 -0
  422. package/dist/scene/possession.js +14 -0
  423. package/dist/scene/roster.d.ts +3 -0
  424. package/dist/scene/roster.js +12 -0
  425. package/dist/scene/sceneKinds.d.ts +240 -0
  426. package/dist/scene/sceneKinds.js +214 -0
  427. package/dist/scene/sceneOwnership.d.ts +169 -0
  428. package/dist/scene/sceneOwnership.js +179 -0
  429. package/dist/scene/selectionBookmarks.d.ts +93 -0
  430. package/dist/scene/selectionBookmarks.js +122 -0
  431. package/dist/scene/vehicleSeat.d.ts +68 -0
  432. package/dist/scene/vehicleSeat.js +59 -0
  433. package/dist/sensor/concealment.d.ts +3 -0
  434. package/dist/sensor/concealment.js +3 -0
  435. package/dist/sensor/freezeMonitor.d.ts +1 -0
  436. package/dist/sensor/freezeMonitor.js +1 -0
  437. package/dist/sensor/frustumSensor.d.ts +7 -3
  438. package/dist/sensor/frustumSensor.js +7 -3
  439. package/dist/sensor/hiddenStateProbe.d.ts +5 -2
  440. package/dist/sensor/hiddenStateProbe.js +5 -2
  441. package/dist/sensor/recordingBuffer.d.ts +2 -1
  442. package/dist/sensor/recordingBuffer.js +2 -1
  443. package/dist/sensor/replayLoop.d.ts +6 -2
  444. package/dist/sensor/replayLoop.js +6 -2
  445. package/dist/sensor/revealQuery.d.ts +2 -1
  446. package/dist/sensor/revealQuery.js +2 -1
  447. package/dist/sensor/visionCone.d.ts +10 -3
  448. package/dist/sensor/visionCone.js +10 -3
  449. package/dist/session/contestedChannel.d.ts +1 -0
  450. package/dist/session/contestedChannel.js +1 -0
  451. package/dist/session/extraction.d.ts +1 -0
  452. package/dist/session/extraction.js +1 -0
  453. package/dist/session/roles.d.ts +6 -0
  454. package/dist/session/roles.js +6 -0
  455. package/dist/session/roundState.d.ts +8 -0
  456. package/dist/session/roundState.js +2 -0
  457. package/dist/settings/settingsModel.d.ts +1 -0
  458. package/dist/settings/settingsModel.js +1 -0
  459. package/dist/stats/accumulatorMeter.d.ts +6 -0
  460. package/dist/stats/accumulatorMeter.js +6 -0
  461. package/dist/stats/eventMeter.d.ts +5 -0
  462. package/dist/stats/eventMeter.js +5 -0
  463. package/dist/stats/rollCheck.d.ts +5 -0
  464. package/dist/stats/rollCheck.js +5 -0
  465. package/dist/stats/statModifiers.d.ts +5 -0
  466. package/dist/stats/statModifiers.js +5 -0
  467. package/dist/store/defineKeyedStore.d.ts +38 -0
  468. package/dist/store/defineKeyedStore.js +42 -0
  469. package/dist/store/defineStore.d.ts +33 -0
  470. package/dist/store/defineStore.js +35 -0
  471. package/dist/store/observableKeyedStore.d.ts +5 -0
  472. package/dist/store/observableKeyedStore.js +34 -2
  473. package/dist/survival/decayMeter.d.ts +55 -0
  474. package/dist/survival/decayMeter.js +130 -55
  475. package/dist/survival/moodle.d.ts +2 -0
  476. package/dist/survival/regionHealth.d.ts +6 -0
  477. package/dist/survival/regionHealth.js +5 -0
  478. package/dist/tactics/fallingGrid.d.ts +4 -2
  479. package/dist/tactics/fallingGrid.js +4 -2
  480. package/dist/tactics/predictiveQuery.d.ts +3 -0
  481. package/dist/tactics/predictiveQuery.js +3 -0
  482. package/dist/tactics/snapshot.d.ts +2 -0
  483. package/dist/tactics/snapshot.js +2 -0
  484. package/dist/tactics/surface.d.ts +1 -0
  485. package/dist/tactics/surface.js +1 -0
  486. package/dist/tactics/tacticalGrid.d.ts +1 -0
  487. package/dist/tactics/tacticalGrid.js +1 -0
  488. package/dist/time/beatClock.d.ts +14 -4
  489. package/dist/time/beatClock.js +14 -4
  490. package/dist/time/calendarClock.d.ts +3 -0
  491. package/dist/time/calendarClock.js +3 -0
  492. package/dist/time/idleProgress.d.ts +4 -0
  493. package/dist/time/idleProgress.js +4 -0
  494. package/dist/time/simClock.d.ts +2 -0
  495. package/dist/time/simClock.js +20 -5
  496. package/dist/ui/actionModel.d.ts +110 -0
  497. package/dist/ui/actionModel.js +159 -0
  498. package/dist/ui/gameLayout.d.ts +30 -11
  499. package/dist/ui/gameLayout.js +30 -11
  500. package/dist/ui/hudDocument.d.ts +114 -0
  501. package/dist/ui/hudDocument.js +220 -0
  502. package/dist/ui/hudLayout.d.ts +33 -1
  503. package/dist/ui/hudLayout.js +204 -17
  504. package/dist/ui/selectionModel.d.ts +92 -0
  505. package/dist/ui/selectionModel.js +88 -0
  506. package/dist/ui/tooltipModel.d.ts +63 -0
  507. package/dist/ui/tooltipModel.js +82 -0
  508. package/dist/ui.d.ts +15 -0
  509. package/dist/ui.js +15 -0
  510. package/dist/visibility/bounds.d.ts +8 -1
  511. package/dist/visibility/bounds.js +8 -1
  512. package/dist/visibility/frustum.d.ts +12 -3
  513. package/dist/visibility/frustum.js +12 -3
  514. package/dist/work/jobQueue.d.ts +201 -0
  515. package/dist/work/jobQueue.js +253 -0
  516. package/dist/work/unitTraining.d.ts +58 -0
  517. package/dist/work/unitTraining.js +52 -0
  518. package/dist/world/authoredObjects.d.ts +58 -0
  519. package/dist/world/authoredObjects.js +69 -0
  520. package/dist/world/buildingGenerator.d.ts +18 -0
  521. package/dist/world/buildingGenerator.js +62 -0
  522. package/dist/world/buildings.d.ts +5 -0
  523. package/dist/world/buildings.js +5 -0
  524. package/dist/world/catenary.d.ts +22 -0
  525. package/dist/world/catenary.js +69 -0
  526. package/dist/world/features.d.ts +115 -7
  527. package/dist/world/features.js +56 -5
  528. package/dist/world/footprintGrid.d.ts +59 -0
  529. package/dist/world/footprintGrid.js +141 -0
  530. package/dist/world/geometry.d.ts +64 -0
  531. package/dist/world/geometry.js +94 -0
  532. package/dist/world/grassKind.d.ts +51 -0
  533. package/dist/world/grassKind.js +101 -0
  534. package/dist/world/pathInstances.d.ts +27 -0
  535. package/dist/world/pathInstances.js +27 -0
  536. package/dist/world/pathTerrain.d.ts +80 -0
  537. package/dist/world/pathTerrain.js +142 -0
  538. package/dist/world/placeAsset.d.ts +81 -0
  539. package/dist/world/placeAsset.js +77 -0
  540. package/dist/world/placement.d.ts +4 -0
  541. package/dist/world/placement.js +4 -0
  542. package/dist/world/placementController.d.ts +6 -0
  543. package/dist/world/placementController.js +6 -0
  544. package/dist/world/polyline.d.ts +34 -0
  545. package/dist/world/polyline.js +81 -0
  546. package/dist/world/roads.d.ts +8 -0
  547. package/dist/world/roads.js +38 -0
  548. package/dist/world/scatterRegion.d.ts +164 -0
  549. package/dist/world/scatterRegion.js +409 -0
  550. package/dist/world/sceneShapes.d.ts +43 -0
  551. package/dist/world/sceneShapes.js +1 -0
  552. package/dist/world/segment.d.ts +27 -0
  553. package/dist/world/segment.js +43 -0
  554. package/dist/world/soilKind.d.ts +48 -0
  555. package/dist/world/soilKind.js +92 -0
  556. package/dist/world/spatialSample.d.ts +241 -0
  557. package/dist/world/spatialSample.js +465 -0
  558. package/dist/world/terraform.d.ts +213 -1
  559. package/dist/world/terraform.js +655 -20
  560. package/dist/world/terrain.d.ts +119 -20
  561. package/dist/world/terrain.js +247 -41
  562. package/dist/world/terrainGuides.d.ts +182 -0
  563. package/dist/world/terrainGuides.js +343 -0
  564. package/dist/world/vec2.d.ts +81 -0
  565. package/dist/world/vec2.js +128 -0
  566. package/dist/world/vec3.d.ts +49 -0
  567. package/dist/world/vec3.js +76 -0
  568. package/dist/world/vegetation.d.ts +71 -0
  569. package/dist/world/vegetation.js +151 -0
  570. package/dist/world/visibilityField.d.ts +154 -0
  571. package/dist/world/visibilityField.js +271 -0
  572. package/dist/world/volumetricClouds.d.ts +52 -0
  573. package/dist/world/volumetricClouds.js +43 -0
  574. package/dist/world/walls.d.ts +9 -0
  575. package/dist/world/walls.js +9 -0
  576. package/dist/world/waterKind.d.ts +55 -0
  577. package/dist/world/waterKind.js +99 -0
  578. package/dist/world.d.ts +132 -0
  579. package/dist/world.js +132 -0
  580. package/package.json +32 -8
  581. package/skills/jgengine/SKILL.md +51 -0
  582. package/skills/jgengine/api.md +434 -0
  583. package/skills/jgengine/capabilities.md +29 -0
  584. package/skills/jgengine/reference-cartridge.md +72 -0
  585. package/skills/jgengine-combat/SKILL.md +34 -0
  586. package/skills/jgengine-combat/api.md +549 -0
  587. package/skills/jgengine-combat/capabilities.md +169 -0
  588. package/skills/jgengine-combat/reference.md +98 -0
  589. package/skills/jgengine-gameplay/SKILL.md +39 -0
  590. package/skills/jgengine-gameplay/api.md +1794 -0
  591. package/skills/jgengine-gameplay/capabilities.md +378 -0
  592. package/skills/jgengine-gameplay/reference-systems.md +60 -0
  593. package/skills/jgengine-world/SKILL.md +38 -0
  594. package/skills/jgengine-world/api.md +2652 -0
  595. package/skills/jgengine-world/capabilities.md +370 -0
  596. package/skills/jgengine-world/reference.md +222 -0
  597. package/dist/cartridge/runtime.d.ts +0 -15
  598. package/dist/cartridge/runtime.js +0 -556
  599. package/dist/cartridge/spec.d.ts +0 -188
  600. package/dist/cartridge/spec.js +0 -19
  601. package/dist/cartridge/validate.d.ts +0 -2
  602. package/dist/cartridge/validate.js +0 -78
  603. package/dist/store/engineStore.d.ts +0 -22
  604. package/dist/store/engineStore.js +0 -50
  605. package/dist/store/features.d.ts +0 -10
  606. package/dist/store/features.js +0 -23
  607. package/llms.txt +0 -5389
@@ -9,6 +9,13 @@ import type { WorldSnapshot } from "./worldSnapshot.js";
9
9
  */
10
10
  export interface WorldDiff {
11
11
  revision: number;
12
+ /**
13
+ * The revision this diff was computed against — `sinceRevision` echoed back. A {@link WorldMirror} only applies
14
+ * a diff whose `baseRevision` matches its own current revision exactly; a mismatch means frames were skipped and
15
+ * the mirror must resync from a fresh baseline instead of silently drifting. Absent on a diff built by an older
16
+ * producer — treated as legacy and always applied, matching pre-revision-checking behavior.
17
+ */
18
+ baseRevision?: number;
12
19
  entities: readonly SceneEntity[];
13
20
  removedEntities: readonly string[];
14
21
  stats: Record<string, StatValueMap>;
@@ -17,15 +24,27 @@ export interface WorldDiff {
17
24
  removedStore: readonly string[];
18
25
  /** Changed whole-module snapshots keyed by module name — everything a client can't reconstruct from deltas. */
19
26
  modules: WorldSnapshot;
27
+ /** Module keys present in a prior baseline that no longer exist — a client drops them wholesale on apply. */
28
+ removedModules: readonly string[];
29
+ }
30
+ /**
31
+ * Optional acceleration for {@link createWorldReplicator}: a monotone world-dirty counter (aggregated from
32
+ * each {@link SnapshotModule.version}). When it hasn't advanced since the last commit nothing mutated, so the
33
+ * replicator skips re-reading and re-serializing the whole world — the change-detection short-circuit item #28
34
+ * asks for. Omit it (or pass a snapshot-only source) to keep the original full-re-serialize-per-commit behavior.
35
+ */
36
+ export interface WorldReplicatorOptions {
37
+ worldVersion?: () => number;
20
38
  }
21
39
  /**
22
40
  * Turns successive full {@link WorldSnapshot}s into per-client {@link WorldDiff}s. Each `commit()` re-reads the
23
41
  * world, stamps every item that changed with the new revision, and remembers removals; `diff(sinceRevision)`
24
42
  * then replays exactly the items stamped after that revision. Everything the tracker holds is JSON — the same
25
43
  * shape that rides the wire — so a diff is inherently serializable. Change-detection is a full re-serialize per
26
- * commit; dirty-hint acceleration is a later optimization behind the same seam.
27
- */
28
- export declare function createWorldReplicator(takeSnapshot: () => WorldSnapshot): {
44
+ * commit unless {@link WorldReplicatorOptions.worldVersion} lets an unchanged tick short-circuit before it.
45
+ * @internal
46
+ */
47
+ export declare function createWorldReplicator(takeSnapshot: () => WorldSnapshot, options?: WorldReplicatorOptions): {
29
48
  commit: () => number;
30
49
  diff: (sinceRevision: number) => WorldDiff;
31
50
  revision: () => number;
@@ -35,12 +54,16 @@ export type WorldReplicator = ReturnType<typeof createWorldReplicator>;
35
54
  /**
36
55
  * Diff two full {@link WorldSnapshot}s directly, stamping the result at `revision` — the stateless counterpart of
37
56
  * {@link createWorldReplicator} for hosts that persist snapshots rather than keep a live tracker (Convex reconstructs
38
- * per invocation). `applyWorldDiff(prev, diffSnapshots(prev, next, r))` reproduces `next`.
39
- */
40
- export declare function diffSnapshots(prev: WorldSnapshot, next: WorldSnapshot, revision: number): WorldDiff;
57
+ * per invocation). `applyWorldDiff(prev, diffSnapshots(prev, next, r))` reproduces `next`. `baseRevision`, when the
58
+ * caller knows the revision `prev` was stamped at, lets a {@link WorldMirror} verify continuity the same way a
59
+ * `createWorldReplicator` diff does; omitted, the diff is legacy/always-apply.
60
+ * @internal
61
+ */
62
+ export declare function diffSnapshots(prev: WorldSnapshot, next: WorldSnapshot, revision: number, baseRevision?: number): WorldDiff;
41
63
  /**
42
64
  * Fold a {@link WorldDiff} onto a prior {@link WorldSnapshot} baseline, returning the next full snapshot — the
43
65
  * client-side inverse of {@link createWorldReplicator}. Pure data in, pure data out: upserts changed entities,
44
66
  * stats and store keys, drops the removed ones, and replaces changed module snapshots wholesale.
45
- */
67
+ * @internal
68
+ */
46
69
  export declare function applyWorldDiff(baseline: WorldSnapshot, diff: WorldDiff): WorldSnapshot;
@@ -4,9 +4,12 @@ const CORE_KEYS = new Set(["entities", "stats", "store"]);
4
4
  * world, stamps every item that changed with the new revision, and remembers removals; `diff(sinceRevision)`
5
5
  * then replays exactly the items stamped after that revision. Everything the tracker holds is JSON — the same
6
6
  * shape that rides the wire — so a diff is inherently serializable. Change-detection is a full re-serialize per
7
- * commit; dirty-hint acceleration is a later optimization behind the same seam.
8
- */
9
- export function createWorldReplicator(takeSnapshot) {
7
+ * commit unless {@link WorldReplicatorOptions.worldVersion} lets an unchanged tick short-circuit before it.
8
+ * @internal
9
+ */
10
+ export function createWorldReplicator(takeSnapshot, options = {}) {
11
+ const worldVersion = options.worldVersion;
12
+ let committedVersion;
10
13
  let revision = 0;
11
14
  const entities = new Map();
12
15
  const removedEntities = new Map();
@@ -15,6 +18,7 @@ export function createWorldReplicator(takeSnapshot) {
15
18
  const store = new Map();
16
19
  const removedStore = new Map();
17
20
  const modules = new Map();
21
+ const removedModules = new Map();
18
22
  function diffMap(live, tracked, removed, nextRevision) {
19
23
  let changed = false;
20
24
  for (const [key, json] of live) {
@@ -35,6 +39,12 @@ export function createWorldReplicator(takeSnapshot) {
35
39
  return changed;
36
40
  }
37
41
  function commit() {
42
+ if (worldVersion !== undefined) {
43
+ const current = worldVersion();
44
+ if (committedVersion !== undefined && current === committedVersion)
45
+ return revision;
46
+ committedVersion = current;
47
+ }
38
48
  const snapshot = takeSnapshot();
39
49
  const nextRevision = revision + 1;
40
50
  const liveEntities = new Map();
@@ -58,7 +68,7 @@ export function createWorldReplicator(takeSnapshot) {
58
68
  let changed = diffMap(liveEntities, entities, removedEntities, nextRevision);
59
69
  changed = diffMap(liveStats, stats, removedStats, nextRevision) || changed;
60
70
  changed = diffMap(liveStore, store, removedStore, nextRevision) || changed;
61
- changed = diffMap(liveModules, modules, new Map(), nextRevision) || changed;
71
+ changed = diffMap(liveModules, modules, removedModules, nextRevision) || changed;
62
72
  if (changed)
63
73
  revision = nextRevision;
64
74
  return revision;
@@ -86,6 +96,7 @@ export function createWorldReplicator(takeSnapshot) {
86
96
  }
87
97
  return {
88
98
  revision,
99
+ baseRevision: sinceRevision,
89
100
  entities: changedEntities,
90
101
  removedEntities: keysAfter(removedEntities, sinceRevision),
91
102
  stats: changedStats,
@@ -93,6 +104,7 @@ export function createWorldReplicator(takeSnapshot) {
93
104
  store: changedStore,
94
105
  removedStore: keysAfter(removedStore, sinceRevision),
95
106
  modules: changedModules,
107
+ removedModules: keysAfter(removedModules, sinceRevision),
96
108
  };
97
109
  }
98
110
  return { commit, diff, revision: () => revision };
@@ -108,9 +120,12 @@ function keysAfter(map, sinceRevision) {
108
120
  /**
109
121
  * Diff two full {@link WorldSnapshot}s directly, stamping the result at `revision` — the stateless counterpart of
110
122
  * {@link createWorldReplicator} for hosts that persist snapshots rather than keep a live tracker (Convex reconstructs
111
- * per invocation). `applyWorldDiff(prev, diffSnapshots(prev, next, r))` reproduces `next`.
112
- */
113
- export function diffSnapshots(prev, next, revision) {
123
+ * per invocation). `applyWorldDiff(prev, diffSnapshots(prev, next, r))` reproduces `next`. `baseRevision`, when the
124
+ * caller knows the revision `prev` was stamped at, lets a {@link WorldMirror} verify continuity the same way a
125
+ * `createWorldReplicator` diff does; omitted, the diff is legacy/always-apply.
126
+ * @internal
127
+ */
128
+ export function diffSnapshots(prev, next, revision, baseRevision) {
114
129
  const prevEntities = new Map();
115
130
  for (const entity of (prev["entities"] ?? [])) {
116
131
  prevEntities.set(entity.id, JSON.stringify(entity));
@@ -143,20 +158,35 @@ export function diffSnapshots(prev, next, revision) {
143
158
  }
144
159
  const removedStore = [...prevStore.keys()].filter((key) => !nextStore.has(key));
145
160
  const modules = {};
161
+ const nextModuleKeys = new Set();
146
162
  for (const [key, value] of Object.entries(next)) {
147
163
  if (CORE_KEYS.has(key))
148
164
  continue;
165
+ nextModuleKeys.add(key);
149
166
  const json = JSON.stringify(value ?? null);
150
167
  if (JSON.stringify(prev[key] ?? null) !== json)
151
168
  modules[key] = JSON.parse(json);
152
169
  }
153
- return { revision, entities, removedEntities, stats, removedStats, store, removedStore, modules };
170
+ const removedModules = Object.keys(prev).filter((key) => !CORE_KEYS.has(key) && !nextModuleKeys.has(key));
171
+ return {
172
+ revision,
173
+ ...(baseRevision === undefined ? {} : { baseRevision }),
174
+ entities,
175
+ removedEntities,
176
+ stats,
177
+ removedStats,
178
+ store,
179
+ removedStore,
180
+ modules,
181
+ removedModules,
182
+ };
154
183
  }
155
184
  /**
156
185
  * Fold a {@link WorldDiff} onto a prior {@link WorldSnapshot} baseline, returning the next full snapshot — the
157
186
  * client-side inverse of {@link createWorldReplicator}. Pure data in, pure data out: upserts changed entities,
158
187
  * stats and store keys, drops the removed ones, and replaces changed module snapshots wholesale.
159
- */
188
+ * @internal
189
+ */
160
190
  export function applyWorldDiff(baseline, diff) {
161
191
  const next = { ...baseline };
162
192
  const entityById = new Map();
@@ -181,5 +211,7 @@ export function applyWorldDiff(baseline, diff) {
181
211
  next["store"] = Array.from(storeByKey.entries());
182
212
  for (const [key, value] of Object.entries(diff.modules))
183
213
  next[key] = value;
214
+ for (const key of diff.removedModules)
215
+ delete next[key];
184
216
  return next;
185
217
  }
@@ -1,17 +1,44 @@
1
+ /** Who a host→client snapshot is being projected for — the identity a {@link SnapshotModule.project} filters against. */
2
+ export interface SnapshotViewer {
3
+ readonly userId: string;
4
+ }
1
5
  /**
2
6
  * The replication seam for host-authoritative shared worlds: the opt-in feature manifest *is* the
3
7
  * replication schema. Each live subsystem a game opts into registers a {@link SnapshotModule} keyed
4
8
  * by name; the host serializes exactly the registered set into a {@link WorldSnapshot} and a client
5
9
  * hydrates the same keys back. Adding a replicated subsystem is a registration, never a new branch.
10
+ *
11
+ * Two optional members carry per-viewer projection and change detection *through the same contract*,
12
+ * so a feature opts into either without the engine growing a per-feature branch:
13
+ * - {@link project} narrows this module's snapshot to what one viewer may see (private state, area of
14
+ * interest). Absent → the module is world-public and every client receives it verbatim (the default).
15
+ * - {@link version} is a monotone counter the host reads to skip re-serializing an unchanged module.
6
16
  */
7
17
  export interface SnapshotModule<T = unknown> {
8
18
  readonly key: string;
9
19
  snapshot(): T;
10
20
  hydrate(data: T): void;
21
+ /**
22
+ * Narrow this module's full snapshot to what `viewer` is allowed to see — return the same shape
23
+ * carrying only the visible subset (drop other players' private state, cull entities outside the
24
+ * viewer's area of interest). `world` is the whole unprojected baseline, so a module can cross-
25
+ * reference another (e.g. drop stats for entities the viewer can't see). Absent → world-public: the
26
+ * full value is sent to every viewer.
27
+ */
28
+ project?(data: T, viewer: SnapshotViewer, world: WorldSnapshot): T;
29
+ /** Monotone change counter; unchanged between host commits means this module didn't mutate and need not re-serialize. */
30
+ version?(): number;
11
31
  }
12
32
  /** Full world baseline keyed by {@link SnapshotModule.key} — one entry per opted-in subsystem. */
13
33
  export type WorldSnapshot = Record<string, unknown>;
14
- /** Serialize every registered module into one keyed baseline — the host→client full-world send. */
15
- export declare function composeWorldSnapshot(modules: readonly SnapshotModule[]): WorldSnapshot;
16
- /** Hydrate every registered module whose key is present in `snapshot`; keys absent from it are left untouched. */
34
+ /**
35
+ * Serialize every registered module into one keyed baseline — the host→client full-world send. When a
36
+ * `viewer` is supplied, each module that implements {@link SnapshotModule.project} narrows its value to
37
+ * what that viewer may see; modules without a projector are sent verbatim.
38
+ * @internal
39
+ */
40
+ export declare function composeWorldSnapshot(modules: readonly SnapshotModule[], viewer?: SnapshotViewer): WorldSnapshot;
41
+ /** Hydrate every registered module whose key is present in `snapshot`; keys absent from it are left untouched.
42
+ * @internal
43
+ */
17
44
  export declare function applyWorldSnapshot(modules: readonly SnapshotModule[], snapshot: WorldSnapshot): void;
@@ -1,11 +1,26 @@
1
- /** Serialize every registered module into one keyed baseline — the host→client full-world send. */
2
- export function composeWorldSnapshot(modules) {
3
- const snapshot = {};
1
+ /**
2
+ * Serialize every registered module into one keyed baseline — the host→client full-world send. When a
3
+ * `viewer` is supplied, each module that implements {@link SnapshotModule.project} narrows its value to
4
+ * what that viewer may see; modules without a projector are sent verbatim.
5
+ * @internal
6
+ */
7
+ export function composeWorldSnapshot(modules, viewer) {
8
+ const raw = {};
4
9
  for (const module of modules)
5
- snapshot[module.key] = module.snapshot();
10
+ raw[module.key] = module.snapshot();
11
+ if (viewer === undefined)
12
+ return raw;
13
+ const snapshot = {};
14
+ for (const module of modules) {
15
+ const value = raw[module.key];
16
+ snapshot[module.key] =
17
+ module.project !== undefined ? module.project(value, viewer, raw) : value;
18
+ }
6
19
  return snapshot;
7
20
  }
8
- /** Hydrate every registered module whose key is present in `snapshot`; keys absent from it are left untouched. */
21
+ /** Hydrate every registered module whose key is present in `snapshot`; keys absent from it are left untouched.
22
+ * @internal
23
+ */
9
24
  export function applyWorldSnapshot(modules, snapshot) {
10
25
  for (const module of modules) {
11
26
  if (Object.prototype.hasOwnProperty.call(snapshot, module.key)) {
@@ -1,3 +1,4 @@
1
+ import type { AssetSpace } from "./assetSpace.js";
1
2
  /** Measured horizontal footprint, footprint center, and lowest Y of a model in model space. */
2
3
  export interface ModelDims {
3
4
  footprint: {
@@ -14,7 +15,27 @@ export interface ModelAssetRef {
14
15
  url: string;
15
16
  /** Measured at asset reindex: horizontal footprint, footprint center, and lowest Y in model space (pre-scale). Lets the shell auto-center and ground-snap corner-pivot kit models. */
16
17
  dims?: ModelDims;
18
+ /** Authored asset-space metadata — canonical facing (degrees), source-unit scale, footprint, anchor, bounds, and rotation policy. The upstream owner of placement corrections; see {@link "scene/assetSpace".AssetSpace}. */
19
+ space?: AssetSpace;
17
20
  }
21
+ /**
22
+ * A catalog entry backed by a registered {@link registerAssetGenerator} instead of a GLB URL — a
23
+ * slider-driven parametric prop (bookcase, building). `defaults` seeds a fresh placement's params.
24
+ * Placed instances persist `{ assetId, params, seed }` in the scene and re-resolve at runtime.
25
+ */
26
+ export interface GeneratorAssetRef {
27
+ kind: "generator";
28
+ /** Id of the registered generator this asset resolves through. */
29
+ generatorId: string;
30
+ /** Default params stamped onto a fresh placement's meta. */
31
+ defaults?: Record<string, unknown>;
32
+ /** Authored asset-space metadata — canonical facing (degrees), footprint, anchor, bounds, and rotation policy; see {@link "scene/assetSpace".AssetSpace}. */
33
+ space?: AssetSpace;
34
+ }
35
+ /** A catalog entry: a static GLB model, or a parametric generator. */
36
+ export type AssetRef = ModelAssetRef | GeneratorAssetRef;
37
+ /** True when a catalog entry is a parametric generator rather than a static GLB. @internal */
38
+ export declare function isGeneratorAsset(ref: AssetRef): ref is GeneratorAssetRef;
18
39
  export interface AssetCatalog<TMeta extends ModelAssetRef = ModelAssetRef> {
19
40
  register(id: string, asset: TMeta): void;
20
41
  resolve(id: string): TMeta | null;
@@ -1,3 +1,7 @@
1
+ /** True when a catalog entry is a parametric generator rather than a static GLB. @internal */
2
+ export function isGeneratorAsset(ref) {
3
+ return ref.kind === "generator";
4
+ }
1
5
  export function createAssetCatalog() {
2
6
  const assets = new Map();
3
7
  return {
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Pure, zero-dependency classification of a model-asset fetch before it reaches
3
+ * a GLTF parser. Runtime loaders hand the raw response (status, content type,
4
+ * and the first bytes) to {@link classifyAssetResponse} so a missing or
5
+ * mis-served file surfaces as an actionable diagnostic naming the broken asset
6
+ * contract, instead of the opaque "Unexpected token < in JSON" parse error a
7
+ * dev-server HTML fallback otherwise produces. No `fetch`, DOM, or three.js
8
+ * dependency lives here — callers supply the already-read bytes.
9
+ */
10
+ /**
11
+ * How a model-asset fetch resolved. `ok` means the bytes are a parseable GLB or
12
+ * glTF-JSON; every other kind is a distinct failure a loader should report
13
+ * rather than parse: `missing` (HTTP error / no bytes), `html` (a dev-server
14
+ * fallback page served in place of the file), `corrupt` (bytes present but not a
15
+ * recognizable model), `unsupported` (a recognizable but non-model format).
16
+ */
17
+ export type AssetLoadKind = "ok" | "missing" | "html" | "corrupt" | "unsupported";
18
+ /** The signature read from a response's leading bytes, independent of HTTP metadata. @internal */
19
+ export type AssetByteSignature = "glb" | "gltf-json" | "html" | "png" | "jpeg" | "zip" | "unknown" | "empty";
20
+ /**
21
+ * A probe of a model-asset fetch: the URL, an optional logical asset id for the
22
+ * diagnostic, and whatever the caller managed to read. Any field may be absent
23
+ * (e.g. a network error yields no `status` or `bytes`); the classifier degrades
24
+ * gracefully.
25
+ */
26
+ export interface AssetResponseProbe {
27
+ url: string;
28
+ /** Logical catalog id / alias behind the URL, surfaced in the diagnostic message when known. */
29
+ logicalId?: string;
30
+ /** HTTP status code; `0` or `>= 400` is treated as missing. Omit when the fetch never completed. */
31
+ status?: number;
32
+ statusText?: string;
33
+ /** `Content-Type` response header, lower-cased or not — matched case-insensitively. */
34
+ contentType?: string;
35
+ /** The leading bytes of the body (a few hundred is plenty); their signature decides GLB vs HTML vs corrupt. */
36
+ bytes?: Uint8Array;
37
+ }
38
+ /** The verdict for one model-asset fetch: its {@link AssetLoadKind} plus a ready-to-log message. */
39
+ export interface AssetLoadDiagnosis {
40
+ kind: AssetLoadKind;
41
+ /** True only for `kind: "ok"` — safe to hand the bytes to a GLTF parser. */
42
+ ok: boolean;
43
+ url: string;
44
+ logicalId?: string;
45
+ byteSignature: AssetByteSignature;
46
+ /** Human-readable, actionable one-liner naming the asset, the URL, and the likely fix. */
47
+ message: string;
48
+ }
49
+ /** GLB little-endian magic — the ASCII "glTF" at byte 0 of a binary glTF container. @internal */
50
+ export declare const GLB_MAGIC_ASCII = "glTF";
51
+ /**
52
+ * Classify the leading bytes of a response body by their format signature, with
53
+ * no HTTP context. Recognizes GLB (`glTF` magic), glTF-JSON (a leading `{`), an
54
+ * HTML fallback page (`<!doctype`, `<html`, or a bare `<`), and a few common
55
+ * non-model binaries (PNG, JPEG, ZIP) so they can be reported as unsupported
56
+ * rather than corrupt.
57
+ */
58
+ export declare function readByteSignature(bytes: Uint8Array): AssetByteSignature;
59
+ /**
60
+ * Turn a {@link AssetResponseProbe} into an {@link AssetLoadDiagnosis}. HTTP
61
+ * status is checked first (a `>= 400` or `0` status is `missing`), then the
62
+ * `Content-Type` and byte signature decide between an HTML fallback, a
63
+ * parseable model (`ok`), an unsupported-but-recognizable format, and otherwise
64
+ * corrupt bytes. The returned `message` always names the asset and URL and, for
65
+ * failures, points at the likely fix (provision the pack, check the serving path).
66
+ *
67
+ * @capability asset-load-diagnostics classify a model fetch (missing / HTML fallback / corrupt / unsupported) before parsing
68
+ */
69
+ export declare function classifyAssetResponse(probe: AssetResponseProbe): AssetLoadDiagnosis;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Pure, zero-dependency classification of a model-asset fetch before it reaches
3
+ * a GLTF parser. Runtime loaders hand the raw response (status, content type,
4
+ * and the first bytes) to {@link classifyAssetResponse} so a missing or
5
+ * mis-served file surfaces as an actionable diagnostic naming the broken asset
6
+ * contract, instead of the opaque "Unexpected token < in JSON" parse error a
7
+ * dev-server HTML fallback otherwise produces. No `fetch`, DOM, or three.js
8
+ * dependency lives here — callers supply the already-read bytes.
9
+ */
10
+ /** GLB little-endian magic — the ASCII "glTF" at byte 0 of a binary glTF container. @internal */
11
+ export const GLB_MAGIC_ASCII = "glTF";
12
+ function startsWithAscii(bytes, ascii) {
13
+ if (bytes.length < ascii.length)
14
+ return false;
15
+ for (let i = 0; i < ascii.length; i += 1) {
16
+ if (bytes[i] !== ascii.charCodeAt(i))
17
+ return false;
18
+ }
19
+ return true;
20
+ }
21
+ /** Skip a UTF-8 BOM and leading ASCII whitespace, returning the index of the first meaningful byte. */
22
+ function firstNonBlank(bytes) {
23
+ let i = 0;
24
+ if (bytes.length >= 3 && bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf)
25
+ i = 3;
26
+ while (i < bytes.length) {
27
+ const b = bytes[i];
28
+ // space, tab, CR, LF
29
+ if (b === 0x20 || b === 0x09 || b === 0x0d || b === 0x0a)
30
+ i += 1;
31
+ else
32
+ break;
33
+ }
34
+ return i;
35
+ }
36
+ /**
37
+ * Classify the leading bytes of a response body by their format signature, with
38
+ * no HTTP context. Recognizes GLB (`glTF` magic), glTF-JSON (a leading `{`), an
39
+ * HTML fallback page (`<!doctype`, `<html`, or a bare `<`), and a few common
40
+ * non-model binaries (PNG, JPEG, ZIP) so they can be reported as unsupported
41
+ * rather than corrupt.
42
+ */
43
+ export function readByteSignature(bytes) {
44
+ if (bytes.length === 0)
45
+ return "empty";
46
+ if (startsWithAscii(bytes, GLB_MAGIC_ASCII))
47
+ return "glb";
48
+ if (bytes.length >= 8 && bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4e && bytes[3] === 0x47) {
49
+ return "png";
50
+ }
51
+ if (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff)
52
+ return "jpeg";
53
+ if (bytes.length >= 4 && bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04) {
54
+ return "zip";
55
+ }
56
+ const start = firstNonBlank(bytes);
57
+ const head = bytes[start];
58
+ if (head === undefined)
59
+ return "empty";
60
+ // '<' — an HTML document served where a model was expected.
61
+ if (head === 0x3c)
62
+ return "html";
63
+ // '{' — glTF-JSON (the non-binary .gltf form) is a parseable model.
64
+ if (head === 0x7b)
65
+ return "gltf-json";
66
+ return "unknown";
67
+ }
68
+ function describe(logicalId, url) {
69
+ return logicalId === undefined ? `"${url}"` : `"${logicalId}" (${url})`;
70
+ }
71
+ /**
72
+ * Turn a {@link AssetResponseProbe} into an {@link AssetLoadDiagnosis}. HTTP
73
+ * status is checked first (a `>= 400` or `0` status is `missing`), then the
74
+ * `Content-Type` and byte signature decide between an HTML fallback, a
75
+ * parseable model (`ok`), an unsupported-but-recognizable format, and otherwise
76
+ * corrupt bytes. The returned `message` always names the asset and URL and, for
77
+ * failures, points at the likely fix (provision the pack, check the serving path).
78
+ *
79
+ * @capability asset-load-diagnostics classify a model fetch (missing / HTML fallback / corrupt / unsupported) before parsing
80
+ */
81
+ export function classifyAssetResponse(probe) {
82
+ const { url, logicalId, status, statusText, contentType, bytes } = probe;
83
+ const signature = bytes === undefined ? "empty" : readByteSignature(bytes);
84
+ const who = describe(logicalId, url);
85
+ const finish = (kind, message) => ({
86
+ kind,
87
+ ok: kind === "ok",
88
+ url,
89
+ ...(logicalId === undefined ? {} : { logicalId }),
90
+ byteSignature: signature,
91
+ message,
92
+ });
93
+ if (status !== undefined && (status === 0 || status >= 400)) {
94
+ const suffix = statusText === undefined || statusText.length === 0 ? "" : ` ${statusText}`;
95
+ return finish("missing", `Asset ${who} did not load: HTTP ${status}${suffix}. The file is not being served — provision the pack (e.g. \`assets pull <source>\`) or check the model path.`);
96
+ }
97
+ const htmlContentType = contentType !== undefined && contentType.toLowerCase().includes("text/html");
98
+ if (signature === "html" || (htmlContentType && signature !== "glb" && signature !== "gltf-json")) {
99
+ return finish("html", `Asset ${who} resolved to an HTML page, not a model — the dev server returned its fallback document because the file is missing. Provision the pack (\`assets pull <source>\`) so the bytes exist under the served path.`);
100
+ }
101
+ if (signature === "glb" || signature === "gltf-json")
102
+ return finish("ok", `Asset ${who} loaded (${signature}).`);
103
+ if (signature === "png" || signature === "jpeg" || signature === "zip") {
104
+ return finish("unsupported", `Asset ${who} is a ${signature} file, not a GLB/glTF model — the reference points at the wrong file or the wrong loader is being used.`);
105
+ }
106
+ if (signature === "empty") {
107
+ return finish("corrupt", `Asset ${who} returned an empty body — the file exists but has no bytes. Re-provision the pack or remove the reference.`);
108
+ }
109
+ return finish("corrupt", `Asset ${who} is not a recognizable GLB/glTF model (leading bytes do not match any known signature). The file is likely truncated or corrupt — re-provision the pack.`);
110
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The generator-asset seam: register a parametric asset generator (`generate(params, seed) → parts`)
3
+ * so a slider-driven prop (a bookcase with width/shelves/book-density, a building with floors/bays)
4
+ * lives in the catalog alongside static GLBs. A placed instance stores only `{ assetId, params, seed }`
5
+ * — the geometry is re-resolved at runtime, never baked. Schema drives the inspector via #809. The
6
+ * generic seam is engine; concrete generators (building, bookcase) are adopters registered from
7
+ * game/example code — the building generator is the one engine adopter, as a proof it composes.
8
+ *
9
+ * @capability asset-generator seeded parametric geometry registered as a placeable asset
10
+ */
11
+ import { type ParamSchema, type ParsedParams } from "./sceneKinds.js";
12
+ /** One generated primitive part — a box/panel placed in the asset's local space. */
13
+ export interface GeneratedPart {
14
+ id: string;
15
+ /** Optional semantic tag (shelf, board, book, wall, window …) for materials/inspection. */
16
+ kind?: string;
17
+ /** Local-space center. */
18
+ position: readonly [number, number, number];
19
+ /** Full box dimensions (w, h, d) in meters. */
20
+ size: readonly [number, number, number];
21
+ rotationY?: number;
22
+ /** Hex color; the renderer falls back to a neutral material when absent. */
23
+ color?: string;
24
+ }
25
+ /** A resolved generator asset: its parts plus the overall local-space bounds (min/max corners). */
26
+ export interface GeneratedAsset {
27
+ parts: GeneratedPart[];
28
+ bounds: {
29
+ min: readonly [number, number, number];
30
+ max: readonly [number, number, number];
31
+ };
32
+ /**
33
+ * The declared local-space direction the asset's "front" faces (a bookcase's open/book face, a
34
+ * building's entrance) — so a camera rig or placement tool can orient it without hand-tuned
35
+ * `rotationY`. Omit to use the convention default, +Z (`DEFAULT_FORWARD` in `./facing`); every
36
+ * generator should build its front toward +Z unless it declares otherwise.
37
+ */
38
+ forward?: readonly [number, number, number];
39
+ }
40
+ /** A registered asset generator — schema drives the inspector; `generate` is a pure seeded function. */
41
+ export interface AssetGeneratorDefinition {
42
+ id: string;
43
+ label: string;
44
+ schema: ParamSchema;
45
+ /** Deterministic geometry from validated params + a seed string. Same inputs → same parts. */
46
+ generate: (params: ParsedParams, seed: string) => GeneratedAsset;
47
+ }
48
+ /** Register a parametric asset generator. Idempotent per id (last wins); call at module load. */
49
+ export declare function registerAssetGenerator(definition: AssetGeneratorDefinition): void;
50
+ /** The registered generator for an id, or undefined. @internal */
51
+ export declare function getAssetGenerator(id: string): AssetGeneratorDefinition | undefined;
52
+ /** Every registered generator, in registration order. @internal */
53
+ export declare function listAssetGenerators(): AssetGeneratorDefinition[];
54
+ /**
55
+ * Compute bounds from parts (each part is an axis-aligned box at its center) — a helper generators
56
+ * return so callers can frame/ground the asset without re-deriving it.
57
+ */
58
+ export declare function partsBounds(parts: readonly GeneratedPart[]): GeneratedAsset["bounds"];
59
+ /**
60
+ * Re-resolve a placed generator instance from its stored `meta` (`{ assetId, seed, ...params }`): look
61
+ * up the generator, parse its params off `meta` against the schema, and generate. Returns null when
62
+ * `assetId` names no registered generator. This is what a runtime renderer calls per placed instance.
63
+ * @internal
64
+ */
65
+ export declare function resolveGeneratorAsset(meta: Record<string, unknown> | undefined): GeneratedAsset | null;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The generator-asset seam: register a parametric asset generator (`generate(params, seed) → parts`)
3
+ * so a slider-driven prop (a bookcase with width/shelves/book-density, a building with floors/bays)
4
+ * lives in the catalog alongside static GLBs. A placed instance stores only `{ assetId, params, seed }`
5
+ * — the geometry is re-resolved at runtime, never baked. Schema drives the inspector via #809. The
6
+ * generic seam is engine; concrete generators (building, bookcase) are adopters registered from
7
+ * game/example code — the building generator is the one engine adopter, as a proof it composes.
8
+ *
9
+ * @capability asset-generator seeded parametric geometry registered as a placeable asset
10
+ */
11
+ import { parseParams } from "./sceneKinds.js";
12
+ const generators = new Map();
13
+ /** Register a parametric asset generator. Idempotent per id (last wins); call at module load. */
14
+ export function registerAssetGenerator(definition) {
15
+ generators.set(definition.id, definition);
16
+ }
17
+ /** The registered generator for an id, or undefined. @internal */
18
+ export function getAssetGenerator(id) {
19
+ return generators.get(id);
20
+ }
21
+ /** Every registered generator, in registration order. @internal */
22
+ export function listAssetGenerators() {
23
+ return [...generators.values()];
24
+ }
25
+ /**
26
+ * Compute bounds from parts (each part is an axis-aligned box at its center) — a helper generators
27
+ * return so callers can frame/ground the asset without re-deriving it.
28
+ */
29
+ export function partsBounds(parts) {
30
+ if (parts.length === 0)
31
+ return { min: [0, 0, 0], max: [0, 0, 0] };
32
+ let minX = Infinity;
33
+ let minY = Infinity;
34
+ let minZ = Infinity;
35
+ let maxX = -Infinity;
36
+ let maxY = -Infinity;
37
+ let maxZ = -Infinity;
38
+ for (const part of parts) {
39
+ minX = Math.min(minX, part.position[0] - part.size[0] / 2);
40
+ minY = Math.min(minY, part.position[1] - part.size[1] / 2);
41
+ minZ = Math.min(minZ, part.position[2] - part.size[2] / 2);
42
+ maxX = Math.max(maxX, part.position[0] + part.size[0] / 2);
43
+ maxY = Math.max(maxY, part.position[1] + part.size[1] / 2);
44
+ maxZ = Math.max(maxZ, part.position[2] + part.size[2] / 2);
45
+ }
46
+ return { min: [minX, minY, minZ], max: [maxX, maxY, maxZ] };
47
+ }
48
+ /**
49
+ * Re-resolve a placed generator instance from its stored `meta` (`{ assetId, seed, ...params }`): look
50
+ * up the generator, parse its params off `meta` against the schema, and generate. Returns null when
51
+ * `assetId` names no registered generator. This is what a runtime renderer calls per placed instance.
52
+ * @internal
53
+ */
54
+ export function resolveGeneratorAsset(meta) {
55
+ const assetId = typeof meta?.["assetId"] === "string" ? meta["assetId"] : undefined;
56
+ if (assetId === undefined)
57
+ return null;
58
+ const generator = generators.get(assetId);
59
+ if (generator === undefined)
60
+ return null;
61
+ const seed = typeof meta?.["seed"] === "string" ? meta["seed"] : assetId;
62
+ const params = parseParams(generator.schema, meta);
63
+ return generator.generate(params, seed);
64
+ }