@jgengine/core 0.10.0 → 0.12.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 (727) hide show
  1. package/CHANGELOG.md +39 -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/populationDirector.d.ts +103 -0
  21. package/dist/ai/populationDirector.js +190 -0
  22. package/dist/ai/pursuit.d.ts +56 -0
  23. package/dist/ai/pursuit.js +53 -0
  24. package/dist/ai/spawnDirector.d.ts +7 -2
  25. package/dist/ai/spawnDirector.js +18 -15
  26. package/dist/ai/spawnPoint.d.ts +3 -1
  27. package/dist/ai/spawnPoint.js +3 -1
  28. package/dist/ai/targetAcquisition.d.ts +84 -0
  29. package/dist/ai/targetAcquisition.js +92 -0
  30. package/dist/anim/easing.d.ts +19 -0
  31. package/dist/anim/easing.js +19 -0
  32. package/dist/anim/oscillator.d.ts +12 -0
  33. package/dist/anim/oscillator.js +25 -0
  34. package/dist/area/areaEffectField.d.ts +127 -0
  35. package/dist/area/areaEffectField.js +175 -0
  36. package/dist/area/stackPolicy.d.ts +47 -0
  37. package/dist/area/stackPolicy.js +99 -0
  38. package/dist/authoring.d.ts +2 -1
  39. package/dist/authoring.js +2 -1
  40. package/dist/board/laneBoard.d.ts +13 -0
  41. package/dist/board/laneBoard.js +13 -0
  42. package/dist/board/timelineBoard.d.ts +10 -0
  43. package/dist/board/timelineBoard.js +10 -0
  44. package/dist/combat/abilityKit.d.ts +18 -0
  45. package/dist/combat/abilityKit.js +24 -9
  46. package/dist/combat/animationState.d.ts +5 -0
  47. package/dist/combat/animationState.js +5 -0
  48. package/dist/combat/breakMeters.d.ts +10 -0
  49. package/dist/combat/breakMeters.js +10 -0
  50. package/dist/combat/castRunner.d.ts +5 -0
  51. package/dist/combat/castRunner.js +5 -0
  52. package/dist/combat/comboPoints.d.ts +5 -0
  53. package/dist/combat/comboPoints.js +5 -0
  54. package/dist/combat/comboString.d.ts +5 -0
  55. package/dist/combat/comboString.js +5 -0
  56. package/dist/combat/damageInterceptors.d.ts +192 -0
  57. package/dist/combat/damageInterceptors.js +251 -0
  58. package/dist/combat/damageMatchup.d.ts +68 -0
  59. package/dist/combat/damageMatchup.js +42 -0
  60. package/dist/combat/damageResolution.d.ts +63 -0
  61. package/dist/combat/damageResolution.js +50 -0
  62. package/dist/combat/death.d.ts +7 -1
  63. package/dist/combat/death.js +5 -0
  64. package/dist/combat/deathReason.d.ts +14 -0
  65. package/dist/combat/deathReason.js +1 -0
  66. package/dist/combat/defensiveWindow.d.ts +5 -0
  67. package/dist/combat/defensiveWindow.js +5 -0
  68. package/dist/combat/dotField.d.ts +5 -1
  69. package/dist/combat/dotField.js +5 -1
  70. package/dist/combat/downed.d.ts +5 -0
  71. package/dist/combat/downed.js +5 -0
  72. package/dist/combat/effects.d.ts +5 -0
  73. package/dist/combat/effects.js +5 -0
  74. package/dist/combat/encounterSequence.d.ts +258 -0
  75. package/dist/combat/encounterSequence.js +426 -0
  76. package/dist/combat/hitReaction.d.ts +57 -1
  77. package/dist/combat/hitReaction.js +45 -5
  78. package/dist/combat/magazine.d.ts +54 -0
  79. package/dist/combat/magazine.js +96 -0
  80. package/dist/combat/projectiles.d.ts +5 -0
  81. package/dist/combat/projectiles.js +32 -14
  82. package/dist/combat/receivedDamage.d.ts +117 -0
  83. package/dist/combat/receivedDamage.js +92 -0
  84. package/dist/combat/regenShield.d.ts +5 -1
  85. package/dist/combat/regenShield.js +5 -1
  86. package/dist/combat/renderCues.d.ts +51 -0
  87. package/dist/combat/renderCues.js +44 -0
  88. package/dist/combat/resourcePool.d.ts +5 -0
  89. package/dist/combat/resourcePool.js +5 -0
  90. package/dist/combat/rewardAllocation.d.ts +121 -0
  91. package/dist/combat/rewardAllocation.js +251 -0
  92. package/dist/combat/shotOrigin.d.ts +18 -1
  93. package/dist/combat/shotOrigin.js +39 -0
  94. package/dist/combat/statusApplication.d.ts +96 -0
  95. package/dist/combat/statusApplication.js +81 -0
  96. package/dist/combat/telegraph.d.ts +11 -2
  97. package/dist/combat/telegraph.js +11 -2
  98. package/dist/combat/thresholdCrossings.d.ts +85 -0
  99. package/dist/combat/thresholdCrossings.js +116 -0
  100. package/dist/combat.d.ts +35 -0
  101. package/dist/combat.js +35 -0
  102. package/dist/commands/commandRegistry.d.ts +11 -0
  103. package/dist/commands/commandRegistry.js +9 -2
  104. package/dist/crafting/crop.d.ts +18 -0
  105. package/dist/crafting/crop.js +18 -0
  106. package/dist/crafting/production.d.ts +5 -0
  107. package/dist/crafting/production.js +5 -0
  108. package/dist/devtools/controls.d.ts +38 -0
  109. package/dist/devtools/controls.js +181 -0
  110. package/dist/devtools/devtools.d.ts +5 -197
  111. package/dist/devtools/devtools.js +38 -774
  112. package/dist/devtools/discover.d.ts +32 -0
  113. package/dist/devtools/discover.js +240 -0
  114. package/dist/devtools/fallbackSeams.d.ts +50 -0
  115. package/dist/devtools/fallbackSeams.js +111 -0
  116. package/dist/devtools/frame.d.ts +15 -0
  117. package/dist/devtools/frame.js +247 -0
  118. package/dist/devtools/logs.d.ts +15 -0
  119. package/dist/devtools/logs.js +86 -0
  120. package/dist/devtools/overrides.d.ts +16 -0
  121. package/dist/devtools/overrides.js +66 -0
  122. package/dist/devtools/rewriteTunables.d.ts +17 -0
  123. package/dist/devtools/rewriteTunables.js +276 -0
  124. package/dist/devtools/saveEndpoint.d.ts +46 -0
  125. package/dist/devtools/saveEndpoint.js +48 -0
  126. package/dist/devtools/transformTunables.d.ts +3 -0
  127. package/dist/devtools/transformTunables.js +3 -0
  128. package/dist/devtools/tunableSchema.d.ts +31 -0
  129. package/dist/devtools/tunableSchema.js +31 -0
  130. package/dist/devtools/types.d.ts +212 -0
  131. package/dist/devtools/types.js +1 -0
  132. package/dist/economy/auctionBook.d.ts +122 -0
  133. package/dist/economy/auctionBook.js +213 -0
  134. package/dist/economy/currency.d.ts +12 -1
  135. package/dist/economy/currency.js +12 -1
  136. package/dist/economy/listingBook.d.ts +91 -0
  137. package/dist/economy/listingBook.js +144 -0
  138. package/dist/economy/priceHistory.d.ts +44 -0
  139. package/dist/economy/priceHistory.js +89 -0
  140. package/dist/economy/resourceLedger.d.ts +222 -0
  141. package/dist/economy/resourceLedger.js +353 -0
  142. package/dist/economy/sharedWallet.d.ts +14 -0
  143. package/dist/economy/sharedWallet.js +14 -0
  144. package/dist/economy/techTree.d.ts +12 -0
  145. package/dist/economy/techTree.js +12 -0
  146. package/dist/economy/unlockPoints.d.ts +92 -0
  147. package/dist/economy/unlockPoints.js +103 -0
  148. package/dist/economy/wallet.d.ts +26 -2
  149. package/dist/economy/wallet.js +35 -6
  150. package/dist/editor/commandApply.d.ts +5 -0
  151. package/dist/editor/commandApply.js +755 -0
  152. package/dist/editor/commands.d.ts +235 -7
  153. package/dist/editor/commands.js +82 -124
  154. package/dist/editor/directives.d.ts +94 -0
  155. package/dist/editor/directives.js +206 -0
  156. package/dist/editor/document.d.ts +194 -13
  157. package/dist/editor/document.js +1166 -19
  158. package/dist/editor/entityCatalog.d.ts +42 -0
  159. package/dist/editor/entityCatalog.js +101 -0
  160. package/dist/editor/environment.d.ts +74 -0
  161. package/dist/editor/environment.js +169 -0
  162. package/dist/editor/grid.d.ts +229 -0
  163. package/dist/editor/grid.js +366 -0
  164. package/dist/editor/gridAdapters.d.ts +80 -0
  165. package/dist/editor/gridAdapters.js +134 -0
  166. package/dist/editor/index.d.ts +98 -6
  167. package/dist/editor/index.js +13 -2
  168. package/dist/editor/liveSync.d.ts +127 -0
  169. package/dist/editor/liveSync.js +249 -0
  170. package/dist/editor/minimap.d.ts +31 -0
  171. package/dist/editor/minimap.js +73 -0
  172. package/dist/editor/runtimeInspector.d.ts +88 -0
  173. package/dist/editor/runtimeInspector.js +239 -0
  174. package/dist/editor/streamer.d.ts +66 -0
  175. package/dist/editor/streamer.js +68 -0
  176. package/dist/editor/types.d.ts +250 -1
  177. package/dist/editor/world.d.ts +136 -0
  178. package/dist/editor/world.js +303 -0
  179. package/dist/faction/reputation.d.ts +5 -0
  180. package/dist/faction/reputation.js +5 -0
  181. package/dist/format/distance.d.ts +17 -0
  182. package/dist/format/distance.js +18 -0
  183. package/dist/format/duration.d.ts +27 -0
  184. package/dist/format/duration.js +45 -0
  185. package/dist/format/speed.d.ts +17 -0
  186. package/dist/format/speed.js +25 -0
  187. package/dist/game/breeding.d.ts +161 -0
  188. package/dist/game/breeding.js +181 -0
  189. package/dist/game/cameraConfig.d.ts +451 -0
  190. package/dist/game/cameraConfig.js +1 -0
  191. package/dist/game/connectedPlayers.d.ts +6 -4
  192. package/dist/game/connectedPlayers.js +2 -2
  193. package/dist/game/cosmetics.d.ts +9 -0
  194. package/dist/game/cosmetics.js +16 -0
  195. package/dist/game/defineGame.d.ts +110 -5
  196. package/dist/game/defineGame.js +49 -4
  197. package/dist/game/defineSystem.d.ts +90 -0
  198. package/dist/game/defineSystem.js +47 -0
  199. package/dist/game/dialogue.d.ts +33 -0
  200. package/dist/game/dialogue.js +21 -0
  201. package/dist/game/events.d.ts +63 -13
  202. package/dist/game/events.js +5 -0
  203. package/dist/game/feed.d.ts +33 -0
  204. package/dist/game/feed.js +35 -2
  205. package/dist/game/gamePhase.d.ts +11 -0
  206. package/dist/game/gamePhase.js +16 -0
  207. package/dist/game/leaderboard.d.ts +5 -0
  208. package/dist/game/leaderboard.js +5 -0
  209. package/dist/game/loadout.d.ts +5 -0
  210. package/dist/game/loadout.js +5 -0
  211. package/dist/game/lootFilter.d.ts +2 -0
  212. package/dist/game/lootFilter.js +2 -0
  213. package/dist/game/lootPipeline.d.ts +164 -0
  214. package/dist/game/lootPipeline.js +216 -0
  215. package/dist/game/lootTable.d.ts +19 -2
  216. package/dist/game/lootTable.js +15 -5
  217. package/dist/game/objectives.d.ts +43 -0
  218. package/dist/game/objectives.js +36 -0
  219. package/dist/game/paramLayers.d.ts +148 -0
  220. package/dist/game/paramLayers.js +185 -0
  221. package/dist/game/ping.d.ts +5 -0
  222. package/dist/game/ping.js +5 -0
  223. package/dist/game/playableGame.d.ts +116 -432
  224. package/dist/game/playableGame.js +1 -1
  225. package/dist/game/progression.d.ts +35 -0
  226. package/dist/game/progression.js +19 -0
  227. package/dist/game/quest.d.ts +8 -0
  228. package/dist/game/quest.js +30 -3
  229. package/dist/game/race.d.ts +141 -0
  230. package/dist/game/race.js +169 -0
  231. package/dist/game/recordBook.d.ts +3 -1
  232. package/dist/game/recordBook.js +4 -1
  233. package/dist/game/ruleSelection.d.ts +75 -0
  234. package/dist/game/ruleSelection.js +127 -0
  235. package/dist/game/runDraft.d.ts +5 -0
  236. package/dist/game/runDraft.js +5 -0
  237. package/dist/game/saveStore.d.ts +111 -0
  238. package/dist/game/saveStore.js +312 -0
  239. package/dist/game/snapshotHistory.d.ts +67 -0
  240. package/dist/game/snapshotHistory.js +95 -0
  241. package/dist/game/social.d.ts +38 -1
  242. package/dist/game/social.js +71 -0
  243. package/dist/game/spawnPoints.d.ts +5 -0
  244. package/dist/game/spawnPoints.js +5 -0
  245. package/dist/game/systemRuntime.d.ts +50 -0
  246. package/dist/game/systemRuntime.js +157 -0
  247. package/dist/game/systemSchedule.d.ts +72 -0
  248. package/dist/game/systemSchedule.js +242 -0
  249. package/dist/game/toasts.d.ts +43 -0
  250. package/dist/game/toasts.js +44 -0
  251. package/dist/game/trade.d.ts +10 -0
  252. package/dist/game/trade.js +10 -0
  253. package/dist/game/tribe.d.ts +184 -0
  254. package/dist/game/tribe.js +432 -0
  255. package/dist/game/unlocks.d.ts +8 -0
  256. package/dist/game/unlocks.js +16 -0
  257. package/dist/game/vfxInstance.d.ts +138 -0
  258. package/dist/game/vfxInstance.js +96 -0
  259. package/dist/game/worldItem.d.ts +17 -4
  260. package/dist/game/worldItem.js +17 -4
  261. package/dist/gameplay.d.ts +93 -0
  262. package/dist/gameplay.js +93 -0
  263. package/dist/index.d.ts +5 -14
  264. package/dist/index.js +5 -14
  265. package/dist/input/actionBindings.d.ts +23 -6
  266. package/dist/input/actionBindings.js +23 -6
  267. package/dist/input/axisInput.d.ts +7 -2
  268. package/dist/input/axisInput.js +7 -2
  269. package/dist/input/controlGroups.d.ts +67 -0
  270. package/dist/input/controlGroups.js +41 -0
  271. package/dist/input/touchScheme.d.ts +82 -6
  272. package/dist/input/touchScheme.js +123 -10
  273. package/dist/interaction/lockpick.d.ts +61 -0
  274. package/dist/interaction/lockpick.js +168 -0
  275. package/dist/interaction/proximityPrompt.d.ts +2 -0
  276. package/dist/interaction/proximityPrompt.js +2 -0
  277. package/dist/interaction/qte.d.ts +5 -0
  278. package/dist/interaction/qte.js +5 -0
  279. package/dist/interaction/skillCheck.d.ts +5 -0
  280. package/dist/interaction/skillCheck.js +5 -0
  281. package/dist/inventory/encumbrance.d.ts +69 -0
  282. package/dist/inventory/encumbrance.js +68 -0
  283. package/dist/inventory/inventoryModel.d.ts +12 -0
  284. package/dist/inventory/inventoryModel.js +12 -0
  285. package/dist/inventory/shapedGrid.d.ts +16 -0
  286. package/dist/inventory/shapedGrid.js +16 -0
  287. package/dist/inventory/slotModel.d.ts +10 -0
  288. package/dist/inventory/slotModel.js +10 -0
  289. package/dist/item/durability.d.ts +5 -0
  290. package/dist/item/durability.js +6 -3
  291. package/dist/item/itemIdentity.d.ts +171 -0
  292. package/dist/item/itemIdentity.js +138 -0
  293. package/dist/item/itemInstanceRegistry.d.ts +32 -0
  294. package/dist/item/itemInstanceRegistry.js +34 -0
  295. package/dist/item/itemgen.d.ts +163 -0
  296. package/dist/item/itemgen.js +151 -0
  297. package/dist/item/modularItem.d.ts +5 -0
  298. package/dist/item/modularItem.js +5 -0
  299. package/dist/item/use.d.ts +5 -0
  300. package/dist/item/use.js +5 -0
  301. package/dist/item/useBehavior.d.ts +142 -0
  302. package/dist/item/useBehavior.js +105 -0
  303. package/dist/item/weapon.d.ts +5 -0
  304. package/dist/item/weapon.js +5 -0
  305. package/dist/math/scalar.d.ts +25 -0
  306. package/dist/math/scalar.js +47 -0
  307. package/dist/meta/changelog.d.ts +4 -1
  308. package/dist/meta/changelog.js +39 -2
  309. package/dist/movement/avoidance.d.ts +45 -0
  310. package/dist/movement/avoidance.js +123 -0
  311. package/dist/movement/cameraRig.d.ts +8 -0
  312. package/dist/movement/cameraRig.js +8 -0
  313. package/dist/movement/dash.d.ts +11 -0
  314. package/dist/movement/dash.js +11 -0
  315. package/dist/movement/formation.d.ts +135 -0
  316. package/dist/movement/formation.js +194 -0
  317. package/dist/movement/glideModel.d.ts +5 -0
  318. package/dist/movement/glideModel.js +5 -0
  319. package/dist/movement/grappleSwing.d.ts +5 -0
  320. package/dist/movement/grappleSwing.js +5 -0
  321. package/dist/movement/leaderTrail.d.ts +5 -0
  322. package/dist/movement/leaderTrail.js +5 -0
  323. package/dist/movement/movementModel.d.ts +50 -9
  324. package/dist/movement/movementModel.js +75 -29
  325. package/dist/movement/playerMovement.js +167 -12
  326. package/dist/movement/poseState.d.ts +13 -0
  327. package/dist/movement/poseState.js +16 -0
  328. package/dist/movement/steering.d.ts +8 -0
  329. package/dist/movement/steering.js +18 -0
  330. package/dist/multiplayer/combatSnapshot.d.ts +3 -0
  331. package/dist/multiplayer/combatSnapshot.js +16 -8
  332. package/dist/multiplayer/lagCompensation.d.ts +5 -0
  333. package/dist/multiplayer/lagCompensation.js +5 -0
  334. package/dist/multiplayer/presenceModel.d.ts +11 -1
  335. package/dist/multiplayer/presenceModel.js +17 -1
  336. package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
  337. package/dist/multiplayer/simultaneousCommit.js +3 -0
  338. package/dist/multiplayer.d.ts +11 -0
  339. package/dist/multiplayer.js +11 -0
  340. package/dist/nav/pathFollow.d.ts +57 -0
  341. package/dist/nav/pathFollow.js +109 -0
  342. package/dist/orders/orderKinds.d.ts +156 -0
  343. package/dist/orders/orderKinds.js +197 -0
  344. package/dist/orders/orderQueue.d.ts +208 -0
  345. package/dist/orders/orderQueue.js +211 -0
  346. package/dist/physics/drivableVehicle.d.ts +31 -0
  347. package/dist/physics/drivableVehicle.js +16 -0
  348. package/dist/physics/flightDynamics.d.ts +82 -0
  349. package/dist/physics/flightDynamics.js +165 -0
  350. package/dist/physics/gravityField.d.ts +25 -0
  351. package/dist/physics/gravityField.js +41 -0
  352. package/dist/physics/kinematicVehicle.d.ts +108 -1
  353. package/dist/physics/kinematicVehicle.js +212 -15
  354. package/dist/physics/physicsWorld.d.ts +50 -12
  355. package/dist/physics/physicsWorld.js +120 -122
  356. package/dist/physics/radialImpulse.d.ts +25 -0
  357. package/dist/physics/radialImpulse.js +27 -0
  358. package/dist/physics/vehicleObstacles.d.ts +44 -0
  359. package/dist/physics/vehicleObstacles.js +115 -0
  360. package/dist/procedural.d.ts +3 -0
  361. package/dist/procedural.js +3 -0
  362. package/dist/progression/statGraph.d.ts +116 -0
  363. package/dist/progression/statGraph.js +318 -0
  364. package/dist/puzzle/cellGrid.d.ts +9 -0
  365. package/dist/puzzle/cellGrid.js +9 -0
  366. package/dist/puzzle/fallingPiece.d.ts +9 -0
  367. package/dist/puzzle/fallingPiece.js +9 -0
  368. package/dist/puzzle/nonogram.d.ts +39 -0
  369. package/dist/puzzle/nonogram.js +136 -0
  370. package/dist/random/nameGen.d.ts +5 -0
  371. package/dist/random/nameGen.js +5 -0
  372. package/dist/random/pick.d.ts +8 -0
  373. package/dist/random/pick.js +31 -0
  374. package/dist/random/rng.d.ts +26 -1
  375. package/dist/random/rng.js +32 -9
  376. package/dist/random/seedLink.d.ts +4 -0
  377. package/dist/random/seedLink.js +4 -0
  378. package/dist/relation/keyedValues.d.ts +54 -0
  379. package/dist/relation/keyedValues.js +115 -0
  380. package/dist/relation/thresholds.d.ts +62 -0
  381. package/dist/relation/thresholds.js +62 -0
  382. package/dist/render/color.d.ts +12 -0
  383. package/dist/render/color.js +26 -0
  384. package/dist/render/lookPreset.d.ts +41 -0
  385. package/dist/render/lookPreset.js +29 -0
  386. package/dist/render/postProcessing.d.ts +20 -0
  387. package/dist/render/postProcessing.js +21 -1
  388. package/dist/rules/predicate.d.ts +53 -0
  389. package/dist/rules/predicate.js +64 -0
  390. package/dist/rules/ruleEffects.d.ts +38 -0
  391. package/dist/rules/ruleEffects.js +37 -0
  392. package/dist/rules/triggeredRules.d.ts +160 -0
  393. package/dist/rules/triggeredRules.js +241 -0
  394. package/dist/runtime/adapter.d.ts +55 -3
  395. package/dist/runtime/adapter.js +57 -1
  396. package/dist/runtime/cameraDirector.d.ts +1 -0
  397. package/dist/runtime/cameraDirector.js +1 -0
  398. package/dist/runtime/commandRunner.d.ts +1 -0
  399. package/dist/runtime/commandRunner.js +1 -0
  400. package/dist/runtime/context/combat.d.ts +51 -0
  401. package/dist/runtime/context/combat.js +130 -0
  402. package/dist/runtime/context/combatFx.d.ts +23 -0
  403. package/dist/runtime/context/combatFx.js +161 -0
  404. package/dist/runtime/context/deathLoot.d.ts +30 -0
  405. package/dist/runtime/context/deathLoot.js +39 -0
  406. package/dist/runtime/context/player.d.ts +48 -0
  407. package/dist/runtime/context/player.js +125 -0
  408. package/dist/runtime/context/registries.d.ts +13 -0
  409. package/dist/runtime/context/registries.js +84 -0
  410. package/dist/runtime/context/scene.d.ts +59 -0
  411. package/dist/runtime/context/scene.js +291 -0
  412. package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
  413. package/dist/runtime/context/snapshotCodecs.js +26 -0
  414. package/dist/runtime/context/worldItems.d.ts +21 -0
  415. package/dist/runtime/context/worldItems.js +37 -0
  416. package/dist/runtime/descriptors/baseline.d.ts +48 -0
  417. package/dist/runtime/descriptors/baseline.js +157 -0
  418. package/dist/runtime/descriptors/features.d.ts +79 -0
  419. package/dist/runtime/descriptors/features.js +299 -0
  420. package/dist/runtime/gameContext.d.ts +2 -327
  421. package/dist/runtime/gameContext.js +273 -778
  422. package/dist/runtime/gameContextTypes.d.ts +467 -0
  423. package/dist/runtime/gameContextTypes.js +1 -0
  424. package/dist/runtime/gameRuntime.d.ts +1 -0
  425. package/dist/runtime/gameRuntime.js +1 -0
  426. package/dist/runtime/headlessRunner.d.ts +62 -0
  427. package/dist/runtime/headlessRunner.js +45 -0
  428. package/dist/runtime/hostPersistence.d.ts +12 -0
  429. package/dist/runtime/hostPersistence.js +12 -0
  430. package/dist/runtime/hostPolicy.d.ts +51 -0
  431. package/dist/runtime/hostPolicy.js +68 -0
  432. package/dist/runtime/hostedGameRunner.d.ts +11 -4
  433. package/dist/runtime/hostedGameRunner.js +27 -3
  434. package/dist/runtime/hostedWorldSession.d.ts +15 -5
  435. package/dist/runtime/hostedWorldSession.js +12 -4
  436. package/dist/runtime/inputSnapshot.d.ts +8 -3
  437. package/dist/runtime/inputSnapshot.js +6 -2
  438. package/dist/runtime/motionIntents.d.ts +11 -2
  439. package/dist/runtime/motionIntents.js +16 -2
  440. package/dist/runtime/perContext.d.ts +15 -0
  441. package/dist/runtime/perContext.js +21 -0
  442. package/dist/runtime/runtimeSave.d.ts +79 -0
  443. package/dist/runtime/runtimeSave.js +105 -0
  444. package/dist/runtime/save.d.ts +4 -0
  445. package/dist/runtime/save.js +4 -0
  446. package/dist/runtime/snapshot.d.ts +7 -0
  447. package/dist/runtime/snapshot.js +7 -0
  448. package/dist/runtime/visibility.d.ts +2 -1
  449. package/dist/runtime/visibility.js +2 -1
  450. package/dist/runtime/worldChannel.d.ts +7 -3
  451. package/dist/runtime/worldChannel.js +51 -6
  452. package/dist/runtime/worldMirror.d.ts +14 -2
  453. package/dist/runtime/worldMirror.js +15 -2
  454. package/dist/runtime/worldProjection.d.ts +47 -0
  455. package/dist/runtime/worldProjection.js +52 -0
  456. package/dist/runtime/worldReplication.d.ts +30 -7
  457. package/dist/runtime/worldReplication.js +41 -9
  458. package/dist/runtime/worldSnapshot.d.ts +42 -3
  459. package/dist/runtime/worldSnapshot.js +34 -7
  460. package/dist/scene/assetCatalog.d.ts +26 -0
  461. package/dist/scene/assetCatalog.js +4 -0
  462. package/dist/scene/assetDiagnostics.d.ts +69 -0
  463. package/dist/scene/assetDiagnostics.js +110 -0
  464. package/dist/scene/assetGenerator.d.ts +65 -0
  465. package/dist/scene/assetGenerator.js +64 -0
  466. package/dist/scene/assetSpace.d.ts +137 -0
  467. package/dist/scene/assetSpace.js +257 -0
  468. package/dist/scene/authoredTriggers.d.ts +219 -0
  469. package/dist/scene/authoredTriggers.js +454 -0
  470. package/dist/scene/behaviorRuntime.d.ts +75 -0
  471. package/dist/scene/behaviorRuntime.js +217 -0
  472. package/dist/scene/behaviors.d.ts +14 -2
  473. package/dist/scene/behaviors.js +7 -2
  474. package/dist/scene/bodyBind.d.ts +60 -0
  475. package/dist/scene/bodyBind.js +51 -0
  476. package/dist/scene/builtinSceneKinds.d.ts +5 -0
  477. package/dist/scene/builtinSceneKinds.js +67 -0
  478. package/dist/scene/colliders.d.ts +71 -1
  479. package/dist/scene/colliders.js +145 -1
  480. package/dist/scene/collisionMesh.d.ts +94 -0
  481. package/dist/scene/collisionMesh.js +699 -0
  482. package/dist/scene/companion.d.ts +147 -0
  483. package/dist/scene/companion.js +193 -0
  484. package/dist/scene/entityStats.d.ts +18 -11
  485. package/dist/scene/entityStats.js +21 -16
  486. package/dist/scene/entityStore.d.ts +12 -1
  487. package/dist/scene/entityStore.js +15 -0
  488. package/dist/scene/facing.d.ts +18 -0
  489. package/dist/scene/facing.js +26 -0
  490. package/dist/scene/modelSockets.d.ts +33 -0
  491. package/dist/scene/modelSockets.js +29 -0
  492. package/dist/scene/objectQuery.d.ts +2 -0
  493. package/dist/scene/objectQuery.js +2 -0
  494. package/dist/scene/objectStore.d.ts +4 -0
  495. package/dist/scene/objectStore.js +6 -0
  496. package/dist/scene/possession.d.ts +8 -0
  497. package/dist/scene/possession.js +14 -0
  498. package/dist/scene/roster.d.ts +3 -0
  499. package/dist/scene/roster.js +12 -0
  500. package/dist/scene/sceneKinds.d.ts +256 -0
  501. package/dist/scene/sceneKinds.js +218 -0
  502. package/dist/scene/sceneOwnership.d.ts +169 -0
  503. package/dist/scene/sceneOwnership.js +179 -0
  504. package/dist/scene/sceneRaycast.js +15 -0
  505. package/dist/scene/selectionBookmarks.d.ts +93 -0
  506. package/dist/scene/selectionBookmarks.js +122 -0
  507. package/dist/scene/vehicleSeat.d.ts +68 -0
  508. package/dist/scene/vehicleSeat.js +59 -0
  509. package/dist/sensor/concealment.d.ts +3 -0
  510. package/dist/sensor/concealment.js +3 -0
  511. package/dist/sensor/freezeMonitor.d.ts +1 -0
  512. package/dist/sensor/freezeMonitor.js +1 -0
  513. package/dist/sensor/frustumSensor.d.ts +7 -3
  514. package/dist/sensor/frustumSensor.js +7 -3
  515. package/dist/sensor/hiddenStateProbe.d.ts +5 -2
  516. package/dist/sensor/hiddenStateProbe.js +5 -2
  517. package/dist/sensor/recordingBuffer.d.ts +2 -1
  518. package/dist/sensor/recordingBuffer.js +2 -1
  519. package/dist/sensor/replayLoop.d.ts +6 -2
  520. package/dist/sensor/replayLoop.js +6 -2
  521. package/dist/sensor/revealQuery.d.ts +2 -1
  522. package/dist/sensor/revealQuery.js +2 -1
  523. package/dist/sensor/visionCone.d.ts +10 -3
  524. package/dist/sensor/visionCone.js +10 -3
  525. package/dist/session/contestedChannel.d.ts +1 -0
  526. package/dist/session/contestedChannel.js +1 -0
  527. package/dist/session/extraction.d.ts +1 -0
  528. package/dist/session/extraction.js +1 -0
  529. package/dist/session/roles.d.ts +6 -0
  530. package/dist/session/roles.js +6 -0
  531. package/dist/session/roundState.d.ts +8 -0
  532. package/dist/session/roundState.js +2 -0
  533. package/dist/settings/settingsModel.d.ts +1 -0
  534. package/dist/settings/settingsModel.js +1 -0
  535. package/dist/stats/accumulatorMeter.d.ts +6 -0
  536. package/dist/stats/accumulatorMeter.js +6 -0
  537. package/dist/stats/eventMeter.d.ts +5 -0
  538. package/dist/stats/eventMeter.js +5 -0
  539. package/dist/stats/rollCheck.d.ts +5 -0
  540. package/dist/stats/rollCheck.js +5 -0
  541. package/dist/stats/spawnLevelStats.d.ts +110 -0
  542. package/dist/stats/spawnLevelStats.js +140 -0
  543. package/dist/stats/statModifiers.d.ts +5 -0
  544. package/dist/stats/statModifiers.js +5 -0
  545. package/dist/stats/statPool.d.ts +70 -0
  546. package/dist/stats/statPool.js +59 -0
  547. package/dist/store/changeSignal.d.ts +3 -0
  548. package/dist/store/changeSignal.js +2 -0
  549. package/dist/store/defineKeyedStore.d.ts +38 -0
  550. package/dist/store/defineKeyedStore.js +42 -0
  551. package/dist/store/defineStore.d.ts +33 -0
  552. package/dist/store/defineStore.js +35 -0
  553. package/dist/store/observableKeyedStore.d.ts +7 -0
  554. package/dist/store/observableKeyedStore.js +35 -2
  555. package/dist/survival/decayMeter.d.ts +55 -0
  556. package/dist/survival/decayMeter.js +130 -57
  557. package/dist/survival/moodle.d.ts +2 -0
  558. package/dist/survival/regionHealth.d.ts +6 -0
  559. package/dist/survival/regionHealth.js +6 -3
  560. package/dist/tactics/fallingGrid.d.ts +4 -2
  561. package/dist/tactics/fallingGrid.js +4 -2
  562. package/dist/tactics/predictiveQuery.d.ts +3 -0
  563. package/dist/tactics/predictiveQuery.js +3 -0
  564. package/dist/tactics/snapshot.d.ts +2 -0
  565. package/dist/tactics/snapshot.js +2 -0
  566. package/dist/tactics/surface.d.ts +1 -0
  567. package/dist/tactics/surface.js +1 -0
  568. package/dist/tactics/tacticalGrid.d.ts +1 -0
  569. package/dist/tactics/tacticalGrid.js +1 -0
  570. package/dist/time/beatClock.d.ts +14 -4
  571. package/dist/time/beatClock.js +14 -4
  572. package/dist/time/calendarClock.d.ts +3 -0
  573. package/dist/time/calendarClock.js +3 -0
  574. package/dist/time/idleProgress.d.ts +4 -0
  575. package/dist/time/idleProgress.js +4 -0
  576. package/dist/time/simClock.d.ts +2 -0
  577. package/dist/time/simClock.js +20 -5
  578. package/dist/ui/actionModel.d.ts +110 -0
  579. package/dist/ui/actionModel.js +159 -0
  580. package/dist/ui/gameLayout.d.ts +30 -11
  581. package/dist/ui/gameLayout.js +30 -11
  582. package/dist/ui/hudDocument.d.ts +114 -0
  583. package/dist/ui/hudDocument.js +220 -0
  584. package/dist/ui/hudLayout.d.ts +38 -1
  585. package/dist/ui/hudLayout.js +220 -17
  586. package/dist/ui/selectionModel.d.ts +92 -0
  587. package/dist/ui/selectionModel.js +88 -0
  588. package/dist/ui/tooltipModel.d.ts +63 -0
  589. package/dist/ui/tooltipModel.js +82 -0
  590. package/dist/ui.d.ts +15 -0
  591. package/dist/ui.js +15 -0
  592. package/dist/visibility/bounds.d.ts +8 -1
  593. package/dist/visibility/bounds.js +8 -1
  594. package/dist/visibility/frustum.d.ts +12 -3
  595. package/dist/visibility/frustum.js +12 -3
  596. package/dist/work/jobQueue.d.ts +201 -0
  597. package/dist/work/jobQueue.js +253 -0
  598. package/dist/work/unitTraining.d.ts +58 -0
  599. package/dist/work/unitTraining.js +52 -0
  600. package/dist/world/authoredEntities.d.ts +29 -0
  601. package/dist/world/authoredEntities.js +29 -0
  602. package/dist/world/authoredObjects.d.ts +72 -0
  603. package/dist/world/authoredObjects.js +81 -0
  604. package/dist/world/authoredSpawn.d.ts +39 -0
  605. package/dist/world/authoredSpawn.js +37 -0
  606. package/dist/world/buildSockets.d.ts +152 -0
  607. package/dist/world/buildSockets.js +188 -0
  608. package/dist/world/buildingGenerator.d.ts +18 -0
  609. package/dist/world/buildingGenerator.js +62 -0
  610. package/dist/world/buildings.d.ts +5 -0
  611. package/dist/world/buildings.js +5 -0
  612. package/dist/world/catenary.d.ts +22 -0
  613. package/dist/world/catenary.js +69 -0
  614. package/dist/world/cityBlocks.d.ts +152 -0
  615. package/dist/world/cityBlocks.js +670 -0
  616. package/dist/world/cityContent.d.ts +77 -0
  617. package/dist/world/cityContent.js +261 -0
  618. package/dist/world/cityGeometry.d.ts +114 -0
  619. package/dist/world/cityGeometry.js +573 -0
  620. package/dist/world/cityKind.d.ts +314 -0
  621. package/dist/world/cityKind.js +1578 -0
  622. package/dist/world/features.d.ts +133 -10
  623. package/dist/world/features.js +66 -6
  624. package/dist/world/footprintGrid.d.ts +59 -0
  625. package/dist/world/footprintGrid.js +141 -0
  626. package/dist/world/geometry.d.ts +64 -0
  627. package/dist/world/geometry.js +94 -0
  628. package/dist/world/grassKind.d.ts +51 -0
  629. package/dist/world/grassKind.js +101 -0
  630. package/dist/world/markers.d.ts +50 -4
  631. package/dist/world/markers.js +49 -0
  632. package/dist/world/massing.js +1 -1
  633. package/dist/world/minimapBake.d.ts +78 -0
  634. package/dist/world/minimapBake.js +208 -0
  635. package/dist/world/minimapTrack.d.ts +17 -0
  636. package/dist/world/minimapTrack.js +22 -0
  637. package/dist/world/pathInstances.d.ts +27 -0
  638. package/dist/world/pathInstances.js +27 -0
  639. package/dist/world/pathNetwork.d.ts +159 -0
  640. package/dist/world/pathNetwork.js +684 -0
  641. package/dist/world/pathTerrain.d.ts +80 -0
  642. package/dist/world/pathTerrain.js +142 -0
  643. package/dist/world/place.d.ts +166 -0
  644. package/dist/world/place.js +96 -0
  645. package/dist/world/placeAsset.d.ts +81 -0
  646. package/dist/world/placeAsset.js +79 -0
  647. package/dist/world/placement.d.ts +4 -0
  648. package/dist/world/placement.js +4 -0
  649. package/dist/world/placementController.d.ts +6 -0
  650. package/dist/world/placementController.js +6 -0
  651. package/dist/world/poleLineKind.d.ts +40 -0
  652. package/dist/world/poleLineKind.js +97 -0
  653. package/dist/world/polyline.d.ts +34 -0
  654. package/dist/world/polyline.js +88 -0
  655. package/dist/world/resourceNode.d.ts +109 -0
  656. package/dist/world/resourceNode.js +140 -0
  657. package/dist/world/roads.d.ts +8 -0
  658. package/dist/world/roads.js +38 -0
  659. package/dist/world/scatter.js +2 -20
  660. package/dist/world/scatterRegion.d.ts +164 -0
  661. package/dist/world/scatterRegion.js +409 -0
  662. package/dist/world/sceneShapes.d.ts +43 -0
  663. package/dist/world/sceneShapes.js +1 -0
  664. package/dist/world/segment.d.ts +27 -0
  665. package/dist/world/segment.js +43 -0
  666. package/dist/world/soilKind.d.ts +48 -0
  667. package/dist/world/soilKind.js +92 -0
  668. package/dist/world/spatialSample.d.ts +241 -0
  669. package/dist/world/spatialSample.js +465 -0
  670. package/dist/world/streets.d.ts +29 -0
  671. package/dist/world/streets.js +55 -0
  672. package/dist/world/terraform.d.ts +213 -1
  673. package/dist/world/terraform.js +627 -22
  674. package/dist/world/terrain.d.ts +164 -20
  675. package/dist/world/terrain.js +325 -41
  676. package/dist/world/terrainGuides.d.ts +182 -0
  677. package/dist/world/terrainGuides.js +343 -0
  678. package/dist/world/vec2.d.ts +81 -0
  679. package/dist/world/vec2.js +128 -0
  680. package/dist/world/vec3.d.ts +49 -0
  681. package/dist/world/vec3.js +76 -0
  682. package/dist/world/vegetation.d.ts +71 -0
  683. package/dist/world/vegetation.js +151 -0
  684. package/dist/world/visibilityField.d.ts +154 -0
  685. package/dist/world/visibilityField.js +271 -0
  686. package/dist/world/volumetricClouds.d.ts +52 -0
  687. package/dist/world/volumetricClouds.js +43 -0
  688. package/dist/world/walls.d.ts +9 -0
  689. package/dist/world/walls.js +9 -0
  690. package/dist/world/waterKind.d.ts +55 -0
  691. package/dist/world/waterKind.js +99 -0
  692. package/dist/world.d.ts +141 -0
  693. package/dist/world.js +141 -0
  694. package/package.json +32 -8
  695. package/skills/game-design/SKILL.md +28 -0
  696. package/skills/game-design/agents/openai.yaml +4 -0
  697. package/skills/game-design/references/application-playbook.md +170 -0
  698. package/skills/game-design/references/field-guide.md +288 -0
  699. package/skills/jgengine/SKILL.md +54 -0
  700. package/skills/jgengine/api.md +527 -0
  701. package/skills/jgengine/capabilities.md +131 -0
  702. package/skills/jgengine/recipes/minimal-game.md +88 -0
  703. package/skills/jgengine-combat/SKILL.md +38 -0
  704. package/skills/jgengine-combat/api.md +585 -0
  705. package/skills/jgengine-combat/capabilities.md +213 -0
  706. package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
  707. package/skills/jgengine-combat/reference.md +108 -0
  708. package/skills/jgengine-gameplay/SKILL.md +39 -0
  709. package/skills/jgengine-gameplay/api.md +1920 -0
  710. package/skills/jgengine-gameplay/capabilities.md +454 -0
  711. package/skills/jgengine-gameplay/reference-systems.md +56 -0
  712. package/skills/jgengine-world/SKILL.md +51 -0
  713. package/skills/jgengine-world/api.md +3056 -0
  714. package/skills/jgengine-world/capabilities.md +476 -0
  715. package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
  716. package/skills/jgengine-world/reference.md +261 -0
  717. package/dist/cartridge/runtime.d.ts +0 -15
  718. package/dist/cartridge/runtime.js +0 -556
  719. package/dist/cartridge/spec.d.ts +0 -188
  720. package/dist/cartridge/spec.js +0 -19
  721. package/dist/cartridge/validate.d.ts +0 -2
  722. package/dist/cartridge/validate.js +0 -78
  723. package/dist/store/engineStore.d.ts +0 -22
  724. package/dist/store/engineStore.js +0 -50
  725. package/dist/store/features.d.ts +0 -10
  726. package/dist/store/features.js +0 -23
  727. package/llms.txt +0 -5389
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Deterministic creature breeding & genetics — a genre-agnostic engine primitive for
3
+ * taming/husbandry games. Everything here operates over plain serializable records so a
4
+ * genome round-trips through save/load and multiplayer sync, and every random decision is
5
+ * driven by an injected `rng: () => number` (values in `[0, 1)`) so identical inputs and an
6
+ * identical rng stream always produce the identical offspring.
7
+ *
8
+ * The lifecycle it models:
9
+ * - **inheritance** — each stat is drawn independently from the higher or lower parent,
10
+ * - **mutation** — a bounded number of rolls that boost a stat, bump a heritable lineage
11
+ * counter, and optionally flag a cosmetic/color mutation, gated by a soft cap,
12
+ * - **imprint** — a rearing bonus accrued by fulfilling care requests over maturation,
13
+ * - **incubation & maturation** — temperature-gated gestation viability and stage resolution.
14
+ *
15
+ * No species tables, coordinates, or game content live here; callers supply their own stat
16
+ * ids and tuning.
17
+ */
18
+ const DEFAULT_HIGHER_STAT_CHANCE = 0.55;
19
+ const DEFAULT_MUTATION_ROLLS = 3;
20
+ const DEFAULT_MUTATION_CHANCE = 0.025;
21
+ const DEFAULT_MUTATION_DELTA = 2;
22
+ const DEFAULT_COLOR_MUTATION_CHANCE = 0.5;
23
+ const DEFAULT_SOFT_CAP_THRESHOLD = 20;
24
+ const DEFAULT_REDUCED_FACTOR = 0.5;
25
+ function clamp01(x) {
26
+ return x < 0 ? 0 : x > 1 ? 1 : x;
27
+ }
28
+ /**
29
+ * Per-roll mutation chance after applying the soft cap to both parents. Exposed so callers
30
+ * and tests can inspect the exact gating rule without breeding.
31
+ *
32
+ * @internal
33
+ */
34
+ function effectiveMutationChance(a, b, config) {
35
+ const base = config.mutationChance ?? DEFAULT_MUTATION_CHANCE;
36
+ const cap = config.mutationSoftCap;
37
+ const threshold = cap?.threshold ?? DEFAULT_SOFT_CAP_THRESHOLD;
38
+ const scope = cap?.scope ?? "both";
39
+ const mode = cap?.mode ?? "block";
40
+ const aOver = a.mutationCount > threshold;
41
+ const bOver = b.mutationCount > threshold;
42
+ const capped = scope === "both" ? aOver && bOver : aOver || bOver;
43
+ if (!capped)
44
+ return base;
45
+ return mode === "reduce" ? base * (cap?.reducedFactor ?? DEFAULT_REDUCED_FACTOR) : 0;
46
+ }
47
+ /**
48
+ * Breed one offspring from two parents. For each stat present in either parent (iterated in
49
+ * sorted id order for a stable rng stream) the offspring independently inherits the higher
50
+ * parent's value with probability `higherStatChance` (default `0.55`), else the lower — a
51
+ * per-stat coin flip, so a strong parent does not guarantee a strong child. Then up to
52
+ * `mutationRolls` mutation rolls fire at the soft-capped chance; each success adds
53
+ * `mutationDelta` to a random stat, bumps the heritable `mutationCount`, and is flagged
54
+ * cosmetic with probability `colorMutationChance`. Lineage counters carry as the max of the
55
+ * two parents plus the new mutations, keeping them monotonic and heritable.
56
+ *
57
+ * Deterministic: the same parents, config, and rng sequence yield byte-identical results.
58
+ *
59
+ * @capability creature-breeding deterministic stat inheritance, mutation, and lineage genetics for taming games
60
+ */
61
+ export function breedOffspring(parentA, parentB, rng, config = {}) {
62
+ const higherChance = config.higherStatChance ?? DEFAULT_HIGHER_STAT_CHANCE;
63
+ const rolls = Math.max(0, Math.floor(config.mutationRolls ?? DEFAULT_MUTATION_ROLLS));
64
+ const delta = config.mutationDelta ?? DEFAULT_MUTATION_DELTA;
65
+ const colorChance = config.colorMutationChance ?? DEFAULT_COLOR_MUTATION_CHANCE;
66
+ // Stable union of stat ids so the rng stream does not depend on object key order.
67
+ const statIds = Array.from(new Set([...Object.keys(parentA.stats), ...Object.keys(parentB.stats)])).sort();
68
+ const stats = {};
69
+ for (const id of statIds) {
70
+ const av = parentA.stats[id];
71
+ const bv = parentB.stats[id];
72
+ // A stat missing on one side behaves as if both parents shared the present value:
73
+ // one rng draw is still consumed so adding a stat to a parent cannot shift the stream.
74
+ const present = av ?? bv ?? 0;
75
+ const high = av === undefined || bv === undefined ? present : Math.max(av, bv);
76
+ const low = av === undefined || bv === undefined ? present : Math.min(av, bv);
77
+ stats[id] = rng() < higherChance ? high : low;
78
+ }
79
+ const chance = effectiveMutationChance(parentA, parentB, config);
80
+ const mutations = [];
81
+ let newMutations = 0;
82
+ let newColor = 0;
83
+ for (let i = 0; i < rolls; i++) {
84
+ if (rng() >= chance)
85
+ continue;
86
+ newMutations += 1;
87
+ let stat = "";
88
+ if (statIds.length > 0) {
89
+ const index = Math.min(statIds.length - 1, Math.floor(rng() * statIds.length));
90
+ stat = statIds[index];
91
+ stats[stat] = (stats[stat] ?? 0) + delta;
92
+ }
93
+ const color = rng() < colorChance;
94
+ if (color)
95
+ newColor += 1;
96
+ mutations.push({ stat, delta: stat === "" ? 0 : delta, color });
97
+ }
98
+ const genome = {
99
+ stats,
100
+ mutationCount: Math.max(parentA.mutationCount, parentB.mutationCount) + newMutations,
101
+ colorMutationCount: Math.max(parentA.colorMutationCount, parentB.colorMutationCount) + newColor,
102
+ };
103
+ return { genome, mutations };
104
+ }
105
+ const DEFAULT_STAT_BONUS = 0.2;
106
+ const DEFAULT_HANDLER_BONUS = 0.3;
107
+ /**
108
+ * Imprint gained per fulfilled care request when `requestCount` requests are scheduled over
109
+ * the maturation window: `1 / requestCount`, so fulfilling every request reaches full (1.0)
110
+ * imprint. Returns `0` for a non-positive request count.
111
+ *
112
+ * @capability imprint-increment per-care-request imprint gain across a maturation schedule
113
+ */
114
+ export function imprintIncrementPerRequest(requestCount) {
115
+ return requestCount > 0 ? 1 / requestCount : 0;
116
+ }
117
+ /**
118
+ * Apply the imprint rearing bonus to a stat block. Every stat is scaled by
119
+ * `1 + statBonusAtFull * imprint`; when `asOwner` is set, the imprinting handler additionally
120
+ * gets `1 + handlerBonusAtFull * imprint`. `imprint` is a 0..1 fraction (clamped) and scales
121
+ * both bonuses linearly, so half-imprint yields half the bonus. Returns a fresh stat block.
122
+ *
123
+ * @capability imprint-bonus apply imprint stat and handler bonuses at an imprint fraction
124
+ */
125
+ export function applyImprintBonus(stats, imprint, config = {}, options = {}) {
126
+ const fraction = clamp01(imprint);
127
+ const statBonus = config.statBonusAtFull ?? DEFAULT_STAT_BONUS;
128
+ const handlerBonus = config.handlerBonusAtFull ?? DEFAULT_HANDLER_BONUS;
129
+ let multiplier = 1 + statBonus * fraction;
130
+ if (options.asOwner)
131
+ multiplier *= 1 + handlerBonus * fraction;
132
+ const out = {};
133
+ for (const id of Object.keys(stats))
134
+ out[id] = stats[id] * multiplier;
135
+ return out;
136
+ }
137
+ /**
138
+ * Advance incubation one tick. While `temperature` is within `[minTemp, maxTemp]` the embryo
139
+ * makes progress (`elapsed += dt`) and keeps its health; outside the range it makes no
140
+ * progress and loses `healthLossPerTick * dt` health (clamped at `0`). Pure — returns a new
141
+ * state, never mutates the input.
142
+ *
143
+ * @capability incubation-tick advance egg incubation health inside/outside its temperature range
144
+ */
145
+ export function tickIncubation(state, temperature, dt, config) {
146
+ if (dt <= 0)
147
+ return { health: state.health, elapsed: state.elapsed };
148
+ const inRange = temperature >= config.minTemp && temperature <= config.maxTemp;
149
+ if (inRange)
150
+ return { health: state.health, elapsed: state.elapsed + dt };
151
+ const loss = (config.healthLossPerTick ?? 1) * dt;
152
+ return { health: Math.max(0, state.health - loss), elapsed: state.elapsed };
153
+ }
154
+ /**
155
+ * True while the incubation still has health to hatch.
156
+ *
157
+ * @capability incubation-viability test whether an egg incubation still has health to hatch
158
+ */
159
+ export function incubationViable(state) {
160
+ return state.health > 0;
161
+ }
162
+ /**
163
+ * Resolve the maturation stage for an elapsed time against a duration. Computes the clamped
164
+ * `elapsed / duration` fraction and returns the id of the last stage whose `at` threshold has
165
+ * been reached (boundaries inclusive). Stages need not be pre-sorted. Returns `""` when no
166
+ * stage qualifies (e.g. an empty list or all thresholds above the current fraction).
167
+ *
168
+ * @capability maturation-stage resolve the baby/juvenile/adolescent/adult stage from elapsed maturation
169
+ */
170
+ export function maturationStage(elapsed, duration, stages) {
171
+ const fraction = duration > 0 ? clamp01(elapsed / duration) : 1;
172
+ let bestId = "";
173
+ let bestAt = -Infinity;
174
+ for (const stage of stages) {
175
+ if (stage.at <= fraction && stage.at >= bestAt) {
176
+ bestAt = stage.at;
177
+ bestId = stage.id;
178
+ }
179
+ }
180
+ return bestId;
181
+ }
@@ -0,0 +1,451 @@
1
+ export interface CameraFollowState {
2
+ entityId: string;
3
+ target: {
4
+ x: number;
5
+ y: number;
6
+ z: number;
7
+ };
8
+ camera: {
9
+ x: number;
10
+ y: number;
11
+ z: number;
12
+ };
13
+ distance: number;
14
+ }
15
+ export interface FirstPersonCameraConfig {
16
+ /** Camera height above the followed entity's origin. Default 1.6. */
17
+ eyeHeight?: number;
18
+ /** Mouse-look radians per pixel of pointer movement. Default 0.0025. */
19
+ sensitivity?: number;
20
+ /** Clamp on look pitch in radians (± from horizon). Default 1.45. */
21
+ maxPitch?: number;
22
+ /** Show the centered crosshair overlay. Default true. */
23
+ reticle?: boolean;
24
+ /** Render a viewmodel in view: the built-in three-mesh gun, or `PlayableGame.viewmodel` when set (#542). `false` renders no viewmodel regardless of `PlayableGame.viewmodel`. Default true. */
25
+ viewmodel?: boolean;
26
+ }
27
+ /**
28
+ * Which camera rig the shell mounts. Every rig accepts `followEntityId: null`
29
+ * (avatar-less games — city-builders, card games, auto-battlers — still get a
30
+ * camera). Rigs are tuned through their config block below, never by writing
31
+ * camera positions from `onTick`.
32
+ * - `orbit` — third-person chase (the historical default; `perspective: "third"`).
33
+ * - `first` — pointer-lock mouse-look (`perspective: "first"`).
34
+ * - `topDown` — fixed height/pitch/yaw with decoupled follow (ARPG iso, top-down).
35
+ * - `rts` — free-pan / edge-scroll / rotate / zoom, optional follow.
36
+ * - `shoulder` — over-the-shoulder with ADS transition + shoulder swap.
37
+ * - `lockOn` — yaw bound to the player→target vector; move axis becomes strafe.
38
+ * - `chase` — speed-reactive vehicle chase (speed→FOV, spring arm, shake) + cockpit/hood/rear views.
39
+ * - `observer` — detached spectator/photo cam bound to any entity or fixed point; never reads player input.
40
+ * - `turntable` — slow auto-orbit of a fixed point: a rotating display stand for a scene. The friendly, flat spelling of `observer`'s point-orbit mode; providing `camera.turntable` selects it without an explicit `rig`.
41
+ * - `sideScroll` — fixed lateral follow (2.5D platformer/beat-'em-up side view); reads no player input.
42
+ * - `inspection` — model-viewer / editor rig (#207.7, #866): middle-drag pan, right-drag orbit, scroll zoom toward a configurable anchor; orbits a fixed point, reads no player/entity input.
43
+ * - `none` — no camera rig is mounted; use for HUD-only presentations or a game that manages its own camera.
44
+ */
45
+ export type CameraRigKind = "orbit" | "first" | "topDown" | "rts" | "shoulder" | "lockOn" | "chase" | "observer" | "turntable" | "sideScroll" | "inspection" | "none";
46
+ /** Canvas camera projection. "orthographic" renders a flat 2D-style view (side-scrollers, falling-block puzzles) — pair with `rig: "sideScroll"`; default "perspective". */
47
+ export type CameraProjection = "perspective" | "orthographic";
48
+ /** Fixed lateral 2.5D follow (side-on platformer cam): the camera sits perpendicular to the travel axis, tracks the followed entity, and never reads player look input. */
49
+ export interface SideScrollCameraConfig {
50
+ /** World axis the action travels along; the camera watches from the perpendicular side. Default "x". */
51
+ axis?: "x" | "z";
52
+ /** Camera distance from the followed entity along the perpendicular axis. Default 10. */
53
+ distance?: number;
54
+ /** Camera height above the followed entity. Default 3. */
55
+ height?: number;
56
+ /** Height of the look point above the entity. Default 1. */
57
+ lookHeight?: number;
58
+ /** Per-second smoothing factor for the follow (0 hard-locks). Default 8. */
59
+ followSmoothing?: number;
60
+ fov?: number;
61
+ }
62
+ /** Fixed top-down / isometric rig (#23) — height/pitch/yaw + decoupled follow. */
63
+ export interface TopDownCameraConfig {
64
+ /** Camera height above the follow point. Default 18. */
65
+ height?: number;
66
+ /** Elevation of the camera above the ground plane in radians (PI/2 = straight down, near 0 = grazing; values below 0.05 clamp to 0.05). Default ~1.02 (~58°, ARPG iso). */
67
+ pitch?: number;
68
+ /** Fixed azimuth in radians; ~PI/4 reads as isometric, 0 as straight top-down. Default PI/4. */
69
+ yaw?: number;
70
+ /** Horizontal look offset applied to the follow point. */
71
+ targetOffset?: {
72
+ x?: number;
73
+ y?: number;
74
+ z?: number;
75
+ };
76
+ /** Exponential follow smoothing (higher = snappier, decoupled from any orbit drag). Default 8. */
77
+ followSmoothing?: number;
78
+ /** Scroll zoom bounds as a height multiplier. */
79
+ zoom?: {
80
+ min?: number;
81
+ max?: number;
82
+ speed?: number;
83
+ };
84
+ }
85
+ /** Free-pan / edge-scroll RTS rig (#24) — pan/rotate/zoom independent of any avatar. */
86
+ export interface RtsCameraConfig extends TopDownCameraConfig {
87
+ /** WASD / arrow pan speed in world units per second. Default 24. */
88
+ panSpeed?: number;
89
+ /** Edge-scroll when the pointer nears a screen edge; number sets the margin fraction. Default true. */
90
+ edgeScroll?: boolean | {
91
+ margin?: number;
92
+ speed?: number;
93
+ };
94
+ /** Yaw rotate speed (radians/sec) for rotate keys / middle-drag. Default 1.4. */
95
+ rotateSpeed?: number;
96
+ /** World-space clamp for the pan center. */
97
+ bounds?: {
98
+ minX?: number;
99
+ maxX?: number;
100
+ minZ?: number;
101
+ maxZ?: number;
102
+ };
103
+ /** Start centered on this world point when there is no follow target. */
104
+ start?: {
105
+ x?: number;
106
+ z?: number;
107
+ };
108
+ /** Read WASD/arrow pan, edge-scroll, Q/E rotate, and wheel zoom. `false` sits static at the start/bounds position — a backdrop camera, no input at all. Default true. */
109
+ pan?: boolean;
110
+ }
111
+ /** Over-the-shoulder combat rig (#25) — offset, ADS, shoulder swap, decoupled reticle. */
112
+ export interface ShoulderCameraConfig {
113
+ /** Lateral shoulder offset (world units, sign flips on swap). Default 0.6. */
114
+ shoulderOffset?: number;
115
+ /** Vertical offset above the follow point. Default 1.6. */
116
+ heightOffset?: number;
117
+ /** Boom distance behind the shoulder. Default 3.2. */
118
+ distance?: number;
119
+ /** Starting shoulder side. Default "right". */
120
+ side?: "left" | "right";
121
+ /** Aim-down-sights framing, blended in while `aim` is held. */
122
+ ads?: {
123
+ distance?: number;
124
+ shoulderOffset?: number;
125
+ fov?: number;
126
+ heightOffset?: number;
127
+ };
128
+ /** ADS blend speed (higher = snappier). Default 10. */
129
+ adsTransitionSpeed?: number;
130
+ /** Screen-space reticle offset (fraction of viewport), decoupled from camera center. */
131
+ reticleOffset?: {
132
+ x?: number;
133
+ y?: number;
134
+ };
135
+ /** Mouse-look sensitivity (radians per pixel). Default 0.0025. */
136
+ sensitivity?: number;
137
+ /** Base field of view. Default 55. */
138
+ fov?: number;
139
+ }
140
+ /** Lock-on / strafe rig (#26) — yaw bound to player→target, move axis becomes strafe. */
141
+ export interface LockOnCameraConfig {
142
+ /** Target instance id; when omitted the rig reads the follower's current `getTarget`. */
143
+ targetEntityId?: string;
144
+ /** Boom distance behind the player, away from the target. Default 5. */
145
+ distance?: number;
146
+ /** Camera height above the follow point. Default 2.4. */
147
+ height?: number;
148
+ /** Height of the framed look point above the midpoint. Default 1.2. */
149
+ lookHeight?: number;
150
+ /** 0 frames the player, 1 frames the target, 0.5 the midpoint. Default 0.5. */
151
+ framingBias?: number;
152
+ /** Exponential yaw smoothing toward the player→target vector. Default 9. */
153
+ yawSmoothing?: number;
154
+ }
155
+ /** Fixed interior view for the chase rig (#27). */
156
+ export type ChaseView = "chase" | "cockpit" | "hood" | "rear";
157
+ /** Speed-reactive vehicle chase rig (#27) — speed→FOV, spring arm, procedural shake, interior views. */
158
+ export interface ChaseCameraConfig {
159
+ /** Boom distance behind the vehicle. Default 6. */
160
+ distance?: number;
161
+ /** Camera height above the follow point. Default 2.6. */
162
+ height?: number;
163
+ /** Height of the look point above the follow point. Default 1.2. */
164
+ lookHeight?: number;
165
+ /** Spring-arm damping (higher = stiffer, less lag). Default 6. */
166
+ springDamping?: number;
167
+ /** Speed→FOV curve: FOV lerps from `base` to `max` as speed climbs to `speedForMax`. */
168
+ fov?: {
169
+ base?: number;
170
+ max?: number;
171
+ speedForMax?: number;
172
+ };
173
+ /** Procedural shake amplitude per unit of speed (adds to the trauma channel). Default 0.0. */
174
+ shakePerSpeed?: number;
175
+ /** Velocity-lead / predictive follow (#286.9): the rig aims `time` seconds ahead of the target along its velocity, clamped to `max` world units (default 4). */
176
+ lead?: {
177
+ time: number;
178
+ max?: number;
179
+ };
180
+ /** Roll into turns (#286.10): radians of camera roll per rad/s of the target's yaw rate, clamped to `max` (default 0.35), exponentially smoothed by `damping` (default 8). */
181
+ bank?: {
182
+ perYawRate: number;
183
+ max?: number;
184
+ damping?: number;
185
+ };
186
+ /**
187
+ * Drift-lag (#1051): when the target slides, rotate the chase anchor partway from
188
+ * its heading toward its travel (velocity) direction so the player sees the car's
189
+ * side while the framing stays stable. Omitting the block keeps the pure-heading
190
+ * behavior. `blend` (default 0.65) is the max fraction of the slip angle to
191
+ * follow, itself scaled by how far the slip has opened so straight-line driving
192
+ * is untouched; below `minSpeed` (default 4) planar speed the feature is off for
193
+ * parking-lot stability; reversing never swings the camera around. `response`
194
+ * (default 6) drives `1-exp(-response*dt)` smoothing toward the blended yaw.
195
+ */
196
+ velocityYaw?: {
197
+ blend?: number;
198
+ minSpeed?: number;
199
+ response?: number;
200
+ };
201
+ /** Which view to mount. Default "chase". */
202
+ view?: ChaseView;
203
+ /** Local offset for cockpit/hood/rear seats (relative to the vehicle, +z forward). */
204
+ seatOffsets?: {
205
+ cockpit?: {
206
+ x?: number;
207
+ y?: number;
208
+ z?: number;
209
+ };
210
+ hood?: {
211
+ x?: number;
212
+ y?: number;
213
+ z?: number;
214
+ };
215
+ rear?: {
216
+ x?: number;
217
+ y?: number;
218
+ z?: number;
219
+ };
220
+ };
221
+ }
222
+ /** Detached spectator/photo cam (#120) — binds to any entity or fixed point, never reads player input. */
223
+ export interface ObserverCameraConfig {
224
+ /** What the observer looks at. Omit to stay on a fixed point at the origin (or `point`, if given). */
225
+ bind?: {
226
+ kind: "entity";
227
+ entityId: string;
228
+ } | {
229
+ kind: "point";
230
+ position: {
231
+ x: number;
232
+ y: number;
233
+ z: number;
234
+ };
235
+ };
236
+ /** Orbit distance from the bound subject. Default 8. */
237
+ distance?: number;
238
+ /** Camera height above the bound subject. Default 3. */
239
+ height?: number;
240
+ /** Height of the look point above the subject. Default 1.2. */
241
+ lookHeight?: number;
242
+ /** Radians/second of automatic orbit around the subject (CCTV-style sweep); 0 holds a fixed angle. Default 0.2. */
243
+ orbitSpeed?: number;
244
+ /** Starting orbit angle in radians. Default 0. */
245
+ startAngle?: number;
246
+ fov?: number;
247
+ }
248
+ /**
249
+ * Turntable / showcase rig — slowly auto-orbits a fixed world point (no player
250
+ * input), the way a museum turntable rotates an object on display. A flat,
251
+ * self-describing spelling of `observer`'s point-orbit mode: `target` names the
252
+ * point directly instead of `bind: { kind: "point", position }`. Set
253
+ * `camera.turntable` and the rig is inferred — you don't also write `rig`.
254
+ */
255
+ export interface TurntableCameraConfig {
256
+ /** World point the camera circles. Default the world origin. */
257
+ target?: {
258
+ x: number;
259
+ y: number;
260
+ z: number;
261
+ };
262
+ /** Orbit radius from the target. Default 8. */
263
+ distance?: number;
264
+ /** Camera height above the target. Default 3. */
265
+ height?: number;
266
+ /** Height of the look point above the target. Default 1.2. */
267
+ lookHeight?: number;
268
+ /** Radians/second of rotation; 0 holds a fixed angle. Default 0.2. */
269
+ orbitSpeed?: number;
270
+ /** Starting angle in radians. Default 0. */
271
+ startAngle?: number;
272
+ fov?: number;
273
+ }
274
+ /**
275
+ * How scroll-zoom re-anchors the view for the inspection rig (#207.7):
276
+ * - `target` — dolly toward the orbit target (classic OrbitControls behavior).
277
+ * - `cursor` — dolly toward the point under the pointer.
278
+ * - `center` — dolly toward the viewport center; equivalent to `target` for an
279
+ * OrbitControls-driven rig, since the camera always faces `target` and that
280
+ * point already projects to the exact center of the viewport.
281
+ */
282
+ export type InspectionZoomAnchor = "target" | "cursor" | "center";
283
+ /** Model-viewer / inspection rig (#207.7) — orbit + pan + anchored zoom around a fixed point, never reads player input. */
284
+ export interface InspectionCameraConfig {
285
+ /** Where scroll-zoom re-anchors the view. Default "target". */
286
+ anchor?: InspectionZoomAnchor;
287
+ /** Orbit target (the point orbited/panned around). Default origin. */
288
+ target?: {
289
+ x?: number;
290
+ y?: number;
291
+ z?: number;
292
+ };
293
+ /** Camera distance from `target` used to seed the initial camera position when `initialPosition` is unset. Default 6. */
294
+ initialDistance?: number;
295
+ /** Explicit starting camera world position; overrides `initialDistance` when set. */
296
+ initialPosition?: {
297
+ x?: number;
298
+ y?: number;
299
+ z?: number;
300
+ };
301
+ minDistance?: number;
302
+ maxDistance?: number;
303
+ /** Vertical orbit clamp (radians). Unset allows a full pole-to-pole orbit, unlike the tighter default on the classic orbit rig. */
304
+ minPolarAngle?: number;
305
+ maxPolarAngle?: number;
306
+ /** Middle-mouse pan. Default true for this rig. */
307
+ pan?: boolean;
308
+ rotateSpeed?: number;
309
+ zoomSpeed?: number;
310
+ dampingFactor?: number;
311
+ }
312
+ /** One stop on a scripted camera path (#29). */
313
+ export interface CameraKeyframe {
314
+ position: {
315
+ x: number;
316
+ y: number;
317
+ z: number;
318
+ };
319
+ lookAt: {
320
+ x: number;
321
+ y: number;
322
+ z: number;
323
+ };
324
+ fov?: number;
325
+ /** Seconds to travel from the previous keyframe to this one. Default 1. */
326
+ duration?: number;
327
+ /** Interpolation into this keyframe. Default "smooth" (smoothstep ease). */
328
+ ease?: "linear" | "smooth";
329
+ }
330
+ /** Scripted keyframe / path player (#29). When set it overrides the active rig. */
331
+ export interface CinematicCameraConfig {
332
+ keyframes: readonly CameraKeyframe[];
333
+ /** Restart from the first keyframe after the last. Default false. */
334
+ loop?: boolean;
335
+ }
336
+ /** Camera-shake / trauma defaults (#28). Any rig reads the trauma channel; game systems feed it via `cameraShake()`. */
337
+ export interface CameraShakeConfig {
338
+ /** Positional shake amplitude at full trauma (world units). Default 0.5. */
339
+ maxOffset?: number;
340
+ /** Rotational shake amplitude at full trauma (radians). Default 0.06. */
341
+ maxRoll?: number;
342
+ /** Trauma decay per second (fraction). Default 1.6. */
343
+ decayPerSecond?: number;
344
+ /** Trauma→shake exponent; 2 = quadratic falloff so small hits are subtle. Default 2. */
345
+ exponent?: number;
346
+ /** Noise frequency (Hz) of the shake oscillation. Default 24. */
347
+ frequency?: number;
348
+ }
349
+ export declare const CAMERA_FRUSTUM_DEFAULTS: {
350
+ readonly fov: 55;
351
+ readonly near: 0.1;
352
+ readonly far: 300;
353
+ readonly zoom: 50;
354
+ };
355
+ /** Player-facing FOV preference applied across every perspective camera rig. Orthographic projections ignore it. */
356
+ export interface PlayerFovConfig {
357
+ /** Inclusive lower bound for the slider and persisted values. Default 40. */
358
+ min?: number;
359
+ /** Inclusive upper bound for the slider and persisted values. Default 120. */
360
+ max?: number;
361
+ /** Initial FOV when nothing is persisted. Defaults to `frustum.fov` or 55. */
362
+ default?: number;
363
+ /** Persist the preference in localStorage across reloads. Default true. */
364
+ persist?: boolean;
365
+ /** Show the shell FOV slider. Default true for perspective cameras; forced off for orthographic. */
366
+ control?: boolean;
367
+ }
368
+ /** Camera tuning for the shell's rig stack: pick the rig via `rig`, then tune it through its matching config block. All fields optional — the default is the third-person orbit rig. */
369
+ export interface GameCameraConfig {
370
+ /** Selects the rig — the one camera-selection knob. Overrides the legacy `perspective` shorthand. */
371
+ rig?: CameraRigKind;
372
+ /** Canvas camera projection. "orthographic" renders a flat 2D-style view (side-scrollers, falling-block puzzles) — pair with `rig: "sideScroll"`; default perspective. */
373
+ projection?: CameraProjection;
374
+ /** Render frustum overrides applied to the canvas camera. `far` defaults to 300 — raise it for worlds whose content spans more than a few hundred units, or distant scenery silently clips. `zoom` is the orthographic zoom in canvas pixels per world unit, read only when `projection` is "orthographic"; default 50. */
375
+ frustum?: {
376
+ fov?: number;
377
+ near?: number;
378
+ far?: number;
379
+ zoom?: number;
380
+ };
381
+ /** Universal player FOV preference (slider + persistence) for perspective rigs. Ignored when `projection` is `"orthographic"`. */
382
+ playerFov?: PlayerFovConfig;
383
+ /** @deprecated Legacy shorthand for `rig: "orbit" | "first"` — set `rig` instead. "third" mounts the orbit camera (default); "first" mounts pointer-lock mouse-look. */
384
+ perspective?: "third" | "first";
385
+ /** First-person tuning; only read when the rig resolves to "first". */
386
+ firstPerson?: FirstPersonCameraConfig;
387
+ /** Top-down / isometric tuning (#23); read when `rig: "topDown"`. */
388
+ topDown?: TopDownCameraConfig;
389
+ /** Free-pan / edge-scroll RTS tuning (#24); read when `rig: "rts"`. */
390
+ rts?: RtsCameraConfig;
391
+ /** Over-the-shoulder tuning (#25); read when `rig: "shoulder"`. */
392
+ shoulder?: ShoulderCameraConfig;
393
+ /** Lock-on / strafe tuning (#26); read when `rig: "lockOn"`. */
394
+ lockOn?: LockOnCameraConfig;
395
+ /** Vehicle chase tuning (#27); read when `rig: "chase"`. */
396
+ chase?: ChaseCameraConfig;
397
+ /** Detached spectator/photo cam tuning (#120); read when `rig: "observer"`. */
398
+ observer?: ObserverCameraConfig;
399
+ /** Turntable / showcase tuning; setting this selects the `turntable` rig on its own. */
400
+ turntable?: TurntableCameraConfig;
401
+ /** Fixed side-on follow tuning; read when `rig: "sideScroll"`. */
402
+ sideScroll?: SideScrollCameraConfig;
403
+ /** Model-viewer / inspection tuning (#207.7); read when `rig: "inspection"`. */
404
+ inspection?: InspectionCameraConfig;
405
+ /** Camera-shake / trauma channel defaults (#28); read by every rig. */
406
+ shake?: CameraShakeConfig;
407
+ /** Scripted keyframe path (#29); when set, plays over the active rig. */
408
+ cinematic?: CinematicCameraConfig;
409
+ /** Seconds to cross-fade the camera when the rig changes (#29). 0 hard-cuts. Default 0.6. */
410
+ transitionSeconds?: number;
411
+ minDistance?: number;
412
+ maxDistance?: number;
413
+ targetHeight?: number;
414
+ /** Extra offset on top of entity position for the orbit target. */
415
+ targetOffset?: {
416
+ x?: number;
417
+ y?: number;
418
+ z?: number;
419
+ };
420
+ initialDistance?: number;
421
+ initialHeight?: number;
422
+ /** Initial horizontal boom facing (radians): 0 = camera behind on -Z, PI = camera on +Z. Seeds the orbit rig; unset keeps the legacy -Z placement. */
423
+ initialYaw?: number;
424
+ /** Initial boom elevation (radians): 0 = level, positive = camera above the target looking down. Seeds the orbit rig; unset derives elevation from `initialHeight`/`initialDistance`. */
425
+ initialPitch?: number;
426
+ /** Lock orbit radius while the follow target moves (default true in shell). */
427
+ followLock?: boolean;
428
+ /** When false, orbit target stays fixed (cinematic / debug). Default true. */
429
+ followEnabled?: boolean;
430
+ /** Instance id to follow, or null for an avatar-less free camera; defaults to local player in the dev shell. */
431
+ followEntityId?: string | null;
432
+ /** Fired each frame after cameraFollow lock is applied. */
433
+ onCameraFollow?: (state: CameraFollowState) => void;
434
+ rotateSpeed?: number;
435
+ zoomSpeed?: number;
436
+ dampingFactor?: number;
437
+ targetSmoothing?: number;
438
+ dragTargetSmoothing?: number;
439
+ distanceSmoothing?: number;
440
+ /** Vertical look clamp (three.js polar angle, radians): 0 = top-down over the head, PI/2 = level, >PI/2 = look up from below. Widen for top-down or vertical aim; unset keeps the standard chase feel. */
441
+ minPolarAngle?: number;
442
+ maxPolarAngle?: number;
443
+ /** Signed boom-elevation clamp `[min, max]` (radians): min < 0 dips the camera below the target, max > 0 rises overhead. Maps onto `minPolarAngle`/`maxPolarAngle` (polar = PI/2 − pitch); explicit polar fields win. */
444
+ pitchClamp?: readonly [number, number];
445
+ /** Spring-arm occlusion for the orbit rig: pull the camera in past walls/terrain so it never clips inside geometry. Off unless `enabled`. */
446
+ collision?: {
447
+ enabled?: boolean;
448
+ padding?: number;
449
+ minTargetDistance?: number;
450
+ };
451
+ }
@@ -0,0 +1 @@
1
+ export const CAMERA_FRUSTUM_DEFAULTS = { fov: 55, near: 0.1, far: 300, zoom: 50 };
@@ -1,10 +1,10 @@
1
1
  import type { InputFrame } from "../runtime/inputSnapshot.js";
2
- /** A player currently joined to a hosted world — the unit a shared-world loop iterates instead of `ctx.player`. */
2
+ /** A player currently joined to a hosted world — the unit a shared-world loop iterates instead of `ctx.player`. Frozen by the registry (see {@link ConnectedPlayers.get}); fields are `readonly` so a caller can't edit its own copy and assume the change stuck. */
3
3
  export interface ConnectedPlayer {
4
- userId: string;
5
- isNew: boolean;
4
+ readonly userId: string;
5
+ readonly isNew: boolean;
6
6
  /** This player's latest {@link InputFrame}, written by the host each time the client sends input; `null` until the first frame arrives. The per-player movement seam reads it in `onTick`. */
7
- input: InputFrame | null;
7
+ readonly input: InputFrame | null;
8
8
  }
9
9
  /**
10
10
  * The set of players connected to one hosted world. A single-player game uses `ctx.player`; a shared-world loop
@@ -15,7 +15,9 @@ export interface ConnectedPlayers {
15
15
  join(userId: string, isNew: boolean): void;
16
16
  leave(userId: string): boolean;
17
17
  has(userId: string): boolean;
18
+ /** Returns a frozen `ConnectedPlayer` — mutating it (or reassigning `.input`) throws instead of corrupting the registry. */
18
19
  get(userId: string): ConnectedPlayer | null;
20
+ /** Frozen `ConnectedPlayer` entries, same immutability contract as {@link get}. */
19
21
  list(): readonly ConnectedPlayer[];
20
22
  ids(): readonly string[];
21
23
  count(): number;
@@ -3,7 +3,7 @@ export function createConnectedPlayers() {
3
3
  const players = new Map();
4
4
  return {
5
5
  join(userId, isNew) {
6
- players.set(userId, { userId, isNew, input: null });
6
+ players.set(userId, Object.freeze({ userId, isNew, input: null }));
7
7
  },
8
8
  leave: (userId) => players.delete(userId),
9
9
  has: (userId) => players.has(userId),
@@ -14,7 +14,7 @@ export function createConnectedPlayers() {
14
14
  setInput(userId, frame) {
15
15
  const player = players.get(userId);
16
16
  if (player !== undefined)
17
- player.input = frame;
17
+ players.set(userId, Object.freeze({ ...player, input: frame }));
18
18
  },
19
19
  input: (userId) => players.get(userId)?.input ?? null,
20
20
  };