@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,136 @@
1
+ /** Run lengths of the filled cells in a boolean line — the clue a solved line yields.
2
+ * @internal
3
+ */
4
+ export function runLengths(line) {
5
+ const runs = [];
6
+ let run = 0;
7
+ for (const cell of line) {
8
+ if (cell) {
9
+ run += 1;
10
+ }
11
+ else if (run > 0) {
12
+ runs.push(run);
13
+ run = 0;
14
+ }
15
+ }
16
+ if (run > 0)
17
+ runs.push(run);
18
+ return runs;
19
+ }
20
+ /** Row and column clues derived from a solution grid — the puzzle a solved board poses.
21
+ * @internal
22
+ */
23
+ export function deriveClues(solution) {
24
+ const width = solution[0]?.length ?? 0;
25
+ const rows = solution.map((row) => runLengths(row));
26
+ const cols = [];
27
+ for (let c = 0; c < width; c += 1)
28
+ cols.push(runLengths(solution.map((row) => row[c] ?? false)));
29
+ return { rows, cols };
30
+ }
31
+ /**
32
+ * Constraint-propagate one line against its `clue`: intersect every clue-consistent arrangement, forcing a
33
+ * cell `filled` when it is filled in all of them and `empty` when empty in all, leaving the rest `unknown`.
34
+ * Returns the tightened line, or `null` on contradiction (no arrangement fits the current cells) — the
35
+ * per-line deduction step at the heart of every nonogram/picross solver.
36
+ * @internal
37
+ */
38
+ export function solveLine(line, clue) {
39
+ const n = line.length;
40
+ const everFilled = new Array(n).fill(false);
41
+ const everEmpty = new Array(n).fill(false);
42
+ const current = new Array(n).fill(false);
43
+ let arrangements = 0;
44
+ const record = () => {
45
+ arrangements += 1;
46
+ for (let k = 0; k < n; k += 1) {
47
+ if (current[k])
48
+ everFilled[k] = true;
49
+ else
50
+ everEmpty[k] = true;
51
+ }
52
+ };
53
+ const place = (pos, clueIndex) => {
54
+ if (clueIndex === clue.length) {
55
+ for (let k = pos; k < n; k += 1)
56
+ if (line[k] === "filled")
57
+ return;
58
+ record();
59
+ return;
60
+ }
61
+ const len = clue[clueIndex];
62
+ for (let start = pos; start + len <= n; start += 1) {
63
+ let gapHasFilled = false;
64
+ for (let k = pos; k < start; k += 1)
65
+ if (line[k] === "filled") {
66
+ gapHasFilled = true;
67
+ break;
68
+ }
69
+ let runOk = true;
70
+ for (let k = start; k < start + len; k += 1)
71
+ if (line[k] === "empty") {
72
+ runOk = false;
73
+ break;
74
+ }
75
+ const separatorOk = start + len >= n || line[start + len] !== "filled";
76
+ if (!gapHasFilled && runOk && separatorOk) {
77
+ for (let k = start; k < start + len; k += 1)
78
+ current[k] = true;
79
+ place(start + len + 1, clueIndex + 1);
80
+ for (let k = start; k < start + len; k += 1)
81
+ current[k] = false;
82
+ }
83
+ if (line[start] === "filled")
84
+ break;
85
+ }
86
+ };
87
+ place(0, 0);
88
+ if (arrangements === 0)
89
+ return null;
90
+ const out = line.slice();
91
+ for (let k = 0; k < n; k += 1) {
92
+ if (everFilled[k] && !everEmpty[k])
93
+ out[k] = "filled";
94
+ else if (everEmpty[k] && !everFilled[k])
95
+ out[k] = "empty";
96
+ }
97
+ return out;
98
+ }
99
+ /**
100
+ * Solve a nonogram from its row and column clues by iterated line propagation until the board stops
101
+ * changing. `solved` is true iff the board is fully determined without guessing — the standard test for
102
+ * whether a nonogram is fair. Returns `solved: false` with a partial board on contradiction or ambiguity.
103
+ * @internal
104
+ */
105
+ export function solveNonogram(rows, cols) {
106
+ const height = rows.length;
107
+ const width = cols.length;
108
+ const board = Array.from({ length: height }, () => new Array(width).fill("unknown"));
109
+ let changed = true;
110
+ while (changed) {
111
+ changed = false;
112
+ for (let r = 0; r < height; r += 1) {
113
+ const solved = solveLine(board[r], rows[r]);
114
+ if (solved === null)
115
+ return { solved: false, board };
116
+ for (let c = 0; c < width; c += 1)
117
+ if (solved[c] !== board[r][c]) {
118
+ board[r][c] = solved[c];
119
+ changed = true;
120
+ }
121
+ }
122
+ for (let c = 0; c < width; c += 1) {
123
+ const column = board.map((row) => row[c]);
124
+ const solved = solveLine(column, cols[c]);
125
+ if (solved === null)
126
+ return { solved: false, board };
127
+ for (let r = 0; r < height; r += 1)
128
+ if (solved[r] !== board[r][c]) {
129
+ board[r][c] = solved[r];
130
+ changed = true;
131
+ }
132
+ }
133
+ }
134
+ const solved = board.every((row) => row.every((cell) => cell !== "unknown"));
135
+ return { solved, board };
136
+ }
@@ -14,5 +14,10 @@ export interface NameGenerator {
14
14
  name(): string;
15
15
  }
16
16
  export declare function pickFrom(rng: () => number, bank: readonly string[]): string;
17
+ /**
18
+ * Generate procedural names from templates and word banks with an injected random source.
19
+ *
20
+ * @capability name-generator generate procedural names from templates and word banks
21
+ */
17
22
  export declare function createNameGenerator(options: NameGeneratorOptions): NameGenerator;
18
23
  export declare function fillTemplate(template: string, vars: Record<string, () => string> | Record<string, string>): string;
@@ -3,6 +3,11 @@ export function pickFrom(rng, bank) {
3
3
  throw new Error("pickFrom: bank must not be empty");
4
4
  return bank[Math.floor(rng() * bank.length)];
5
5
  }
6
+ /**
7
+ * Generate procedural names from templates and word banks with an injected random source.
8
+ *
9
+ * @capability name-generator generate procedural names from templates and word banks
10
+ */
6
11
  export function createNameGenerator(options) {
7
12
  const { rng, syllables } = options;
8
13
  const minSyllables = Math.max(1, options.minSyllables ?? 2);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Pick one item uniformly at random from `items` using `rng` (a `() => number` in `[0, 1)`); returns undefined when empty.
3
+ *
4
+ * @capability weighted-pick pick one item from a set with an injected random source
5
+ */
6
+ export declare function pickUniform<T>(rng: () => number, items: readonly T[]): T | undefined;
7
+ /** Pick one item with probability proportional to `weightOf(item)`; skips non-positive weights, returns undefined when nothing is eligible. */
8
+ export declare function pickWeighted<T>(rng: () => number, items: readonly T[], weightOf: (item: T) => number): T | undefined;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Pick one item uniformly at random from `items` using `rng` (a `() => number` in `[0, 1)`); returns undefined when empty.
3
+ *
4
+ * @capability weighted-pick pick one item from a set with an injected random source
5
+ */
6
+ export function pickUniform(rng, items) {
7
+ if (items.length === 0)
8
+ return undefined;
9
+ return items[Math.min(items.length - 1, Math.floor(rng() * items.length))];
10
+ }
11
+ /** Pick one item with probability proportional to `weightOf(item)`; skips non-positive weights, returns undefined when nothing is eligible. */
12
+ export function pickWeighted(rng, items, weightOf) {
13
+ let total = 0;
14
+ for (const item of items) {
15
+ const weight = weightOf(item);
16
+ if (weight > 0)
17
+ total += weight;
18
+ }
19
+ if (total <= 0)
20
+ return undefined;
21
+ let roll = rng() * total;
22
+ for (const item of items) {
23
+ const weight = weightOf(item);
24
+ if (weight <= 0)
25
+ continue;
26
+ roll -= weight;
27
+ if (roll <= 0)
28
+ return item;
29
+ }
30
+ return items[items.length - 1];
31
+ }
@@ -1,4 +1,29 @@
1
- /** Deterministic pseudo-random generator seeded from a string or number — same seed, same sequence. */
1
+ /**
2
+ * Deterministic 32-bit FNV-1a hash of a string → unsigned int. Same text, same number, on every
3
+ * platform — the stable seed behind per-id jitter, spread offsets, and content-addressed variation.
4
+ */
5
+ export declare function hashString(text: string): number;
6
+ /**
7
+ * Opaque, serializable PRNG cursor for state machines that must persist their own random stream
8
+ * (a spawn director, a heat/pursuit meter) instead of holding a closure — the state round-trips
9
+ * through save/load and multiplayer sync, so it can't carry a function. Never read or do
10
+ * arithmetic on the raw value directly; thread it through {@link stepRandomSeed} only.
11
+ */
12
+ export type RandomSeed = number & {
13
+ readonly __randomSeed: unique symbol;
14
+ };
15
+ /** Wraps an already-integer seed (e.g. a `config.seed`) as a {@link RandomSeed} — no hashing. */
16
+ export declare function randomSeedFrom(seed: number): RandomSeed;
17
+ /**
18
+ * One step of the {@link seededRng} recurrence in pure (seed in, seed out) form — the same
19
+ * mulberry32-style generator, shared by every state machine that persists its own PRNG cursor
20
+ * instead of closing over a generator.
21
+ */
22
+ export declare function stepRandomSeed(seed: RandomSeed): readonly [value: number, next: RandomSeed];
23
+ /** Deterministic pseudo-random generator seeded from a string or number — same seed, same sequence.
24
+ *
25
+ * @capability seeded-random injected deterministic randomness for game logic — never `Math.random` in a simulation
26
+ */
2
27
  export declare function seededRng(seed: string | number): () => number;
3
28
  /** Derives independent, deterministic {@link seededRng} streams from one base seed, keyed by stream name. */
4
29
  export declare function seededStreams(seed: string | number): (stream: string) => () => number;
@@ -1,5 +1,8 @@
1
- function hashSeed(seed) {
2
- const text = typeof seed === "number" ? seed.toString() : seed;
1
+ /**
2
+ * Deterministic 32-bit FNV-1a hash of a string → unsigned int. Same text, same number, on every
3
+ * platform — the stable seed behind per-id jitter, spread offsets, and content-addressed variation.
4
+ */
5
+ export function hashString(text) {
3
6
  let h = 2166136261 >>> 0;
4
7
  for (let i = 0; i < text.length; i++) {
5
8
  h ^= text.charCodeAt(i);
@@ -7,15 +10,35 @@ function hashSeed(seed) {
7
10
  }
8
11
  return h >>> 0;
9
12
  }
10
- /** Deterministic pseudo-random generator seeded from a string or number — same seed, same sequence. */
13
+ function hashSeed(seed) {
14
+ return hashString(typeof seed === "number" ? seed.toString() : seed);
15
+ }
16
+ /** Wraps an already-integer seed (e.g. a `config.seed`) as a {@link RandomSeed} — no hashing. */
17
+ export function randomSeedFrom(seed) {
18
+ return (seed | 0);
19
+ }
20
+ /**
21
+ * One step of the {@link seededRng} recurrence in pure (seed in, seed out) form — the same
22
+ * mulberry32-style generator, shared by every state machine that persists its own PRNG cursor
23
+ * instead of closing over a generator.
24
+ */
25
+ export function stepRandomSeed(seed) {
26
+ const next = (seed + 0x6d2b79f5) | 0;
27
+ let t = Math.imul(next ^ (next >>> 15), 1 | next);
28
+ t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
29
+ const value = ((t ^ (t >>> 14)) >>> 0) / 4294967296;
30
+ return [value, next];
31
+ }
32
+ /** Deterministic pseudo-random generator seeded from a string or number — same seed, same sequence.
33
+ *
34
+ * @capability seeded-random injected deterministic randomness for game logic — never `Math.random` in a simulation
35
+ */
11
36
  export function seededRng(seed) {
12
- let a = hashSeed(seed) >>> 0;
37
+ let cursor = randomSeedFrom(hashSeed(seed));
13
38
  return () => {
14
- a = (a + 0x6d2b79f5) >>> 0;
15
- let t = a;
16
- t = Math.imul(t ^ (t >>> 15), t | 1);
17
- t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
18
- return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
39
+ const [value, next] = stepRandomSeed(cursor);
40
+ cursor = next;
41
+ return value;
19
42
  };
20
43
  }
21
44
  /** Derives independent, deterministic {@link seededRng} streams from one base seed, keyed by stream name. */
@@ -1,5 +1,9 @@
1
1
  export declare const DEFAULT_SEED_PARAM = "seed";
2
+ /** @internal */
2
3
  export declare function withSeedParam(url: string, seed: string | number, param?: string): string;
4
+ /** @internal */
3
5
  export declare function seedFromSearch(search: string, param?: string): string | null;
6
+ /** @internal */
4
7
  export declare function seedFromUrl(url: string, param?: string): string | null;
8
+ /** @internal */
5
9
  export declare function dailySeed(nowMs: number, salt?: string): string;
@@ -8,6 +8,7 @@ function splitUrl(url) {
8
8
  const query = queryIndex === -1 ? "" : rest.slice(queryIndex + 1);
9
9
  return { base, query, hash };
10
10
  }
11
+ /** @internal */
11
12
  export function withSeedParam(url, seed, param = DEFAULT_SEED_PARAM) {
12
13
  const { base, query, hash } = splitUrl(url);
13
14
  const params = new URLSearchParams(query);
@@ -15,16 +16,19 @@ export function withSeedParam(url, seed, param = DEFAULT_SEED_PARAM) {
15
16
  const queryString = params.toString();
16
17
  return `${base}${queryString ? `?${queryString}` : ""}${hash ? `#${hash}` : ""}`;
17
18
  }
19
+ /** @internal */
18
20
  export function seedFromSearch(search, param = DEFAULT_SEED_PARAM) {
19
21
  const normalized = search.startsWith("?") ? search.slice(1) : search;
20
22
  const params = new URLSearchParams(normalized);
21
23
  const value = params.get(param);
22
24
  return value === null || value === "" ? null : value;
23
25
  }
26
+ /** @internal */
24
27
  export function seedFromUrl(url, param = DEFAULT_SEED_PARAM) {
25
28
  const { query } = splitUrl(url);
26
29
  return seedFromSearch(query, param);
27
30
  }
31
+ /** @internal */
28
32
  export function dailySeed(nowMs, salt) {
29
33
  const date = new Date(nowMs);
30
34
  const year = date.getUTCFullYear().toString().padStart(4, "0");
@@ -0,0 +1,54 @@
1
+ /** Optional inclusive `[min, max]` clamp applied after a write. Omit an edge for unbounded. */
2
+ export interface NumericBounds {
3
+ readonly min?: number;
4
+ readonly max?: number;
5
+ }
6
+ /** Clamp a scalar to `bounds` (identity when `bounds` is omitted). Pure — touches no record. */
7
+ export declare function clampValue(value: number, bounds?: NumericBounds): number;
8
+ /** Current value for `key`, or `fallback` (default `0`) when the record has no entry. */
9
+ export declare function getValue(record: Record<string, number>, key: string, fallback?: number): number;
10
+ /**
11
+ * Set `key` to `value` (clamped to `bounds`), writing the record in place. Returns the stored value.
12
+ *
13
+ * @capability set a bounded keyed value in a caller-owned serializable record
14
+ */
15
+ export declare function setValue(record: Record<string, number>, key: string, value: number, bounds?: NumericBounds): number;
16
+ /** Add `delta` to `key` (clamped to `bounds`), writing the record in place. Returns the stored value. */
17
+ export declare function addValue(record: Record<string, number>, key: string, delta: number, bounds?: NumericBounds): number;
18
+ /**
19
+ * Step `key` toward `target` by at most `maxDelta` without overshooting, then clamp
20
+ * to `bounds`. Writes in place and returns the stored value.
21
+ *
22
+ * @capability move a keyed value toward a target by a bounded step
23
+ */
24
+ export declare function towardValue(record: Record<string, number>, key: string, target: number, maxDelta: number, bounds?: NumericBounds): number;
25
+ /**
26
+ * Decay `key` toward a `rest` value (default `0`) by `rate` per call — the common
27
+ * "relationships cool off" / "heat fades" drift. Thin wrapper over {@link towardValue}.
28
+ */
29
+ export declare function driftValue(record: Record<string, number>, key: string, rate: number, rest?: number, bounds?: NumericBounds): number;
30
+ /** Canonicalizes a two-part relation identity into a single delimiter-safe record key. */
31
+ export interface PairKeyCodec {
32
+ /** `true` when order matters (a→b differs from b→a); `false` sorts the pair first. */
33
+ readonly directed: boolean;
34
+ /** Encode a pair into one record key. Undirected codecs canonicalize by sorting the two ids. */
35
+ key(a: string, b: string): string;
36
+ /** Recover the pair from a key. Undirected keys come back in canonical (sorted) order. */
37
+ parse(key: string): [string, string];
38
+ }
39
+ /** Direction and delimiter policy for {@link createPairKeyCodec}. */
40
+ export interface PairKeyOptions {
41
+ /** `true` for ordered relations (rivalry-from, owes-to); default `false` (mutual). */
42
+ readonly directed?: boolean;
43
+ /** Single-character delimiter between encoded ids (default `"|"`). Collisions are escaped, not forbidden. */
44
+ readonly separator?: string;
45
+ }
46
+ /**
47
+ * Build a pair-key codec for keyed relation values. Ids are escaped before joining,
48
+ * so any id (including ones containing the separator or a backslash) round-trips
49
+ * through {@link PairKeyCodec.key} → {@link PairKeyCodec.parse} without collision.
50
+ * Undirected codecs (the default) canonicalize so `key(a, b) === key(b, a)`.
51
+ *
52
+ * @capability build a serializable directed/undirected pair key that resists delimiter collisions
53
+ */
54
+ export declare function createPairKeyCodec(options?: PairKeyOptions): PairKeyCodec;
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Pure, serialization-friendly numeric operations over a caller-owned record of
3
+ * keyed values, plus delimiter-safe pair-key codecs for directed and undirected
4
+ * relations.
5
+ *
6
+ * No hidden state and no social semantics: the record, its bounds, drift rates,
7
+ * and keys are all caller data. Operations mutate the passed record in place and
8
+ * return the resulting value, so a game keeps one plain `Record<string, number>`
9
+ * it can serialize with `JSON.stringify` and restore verbatim. Pair keys are the
10
+ * injectable canonicalizer — compose `codec.key(a, b)` into any of the ops below.
11
+ */
12
+ import { clamp, moveTowards } from "../math/scalar.js";
13
+ function applyBounds(value, bounds) {
14
+ return clamp(value, bounds?.min ?? Number.NEGATIVE_INFINITY, bounds?.max ?? Number.POSITIVE_INFINITY);
15
+ }
16
+ /** Clamp a scalar to `bounds` (identity when `bounds` is omitted). Pure — touches no record. */
17
+ export function clampValue(value, bounds) {
18
+ return applyBounds(value, bounds);
19
+ }
20
+ /** Current value for `key`, or `fallback` (default `0`) when the record has no entry. */
21
+ export function getValue(record, key, fallback = 0) {
22
+ const stored = record[key];
23
+ return stored === undefined ? fallback : stored;
24
+ }
25
+ /**
26
+ * Set `key` to `value` (clamped to `bounds`), writing the record in place. Returns the stored value.
27
+ *
28
+ * @capability set a bounded keyed value in a caller-owned serializable record
29
+ */
30
+ export function setValue(record, key, value, bounds) {
31
+ const next = applyBounds(value, bounds);
32
+ record[key] = next;
33
+ return next;
34
+ }
35
+ /** Add `delta` to `key` (clamped to `bounds`), writing the record in place. Returns the stored value. */
36
+ export function addValue(record, key, delta, bounds) {
37
+ return setValue(record, key, getValue(record, key) + delta, bounds);
38
+ }
39
+ /**
40
+ * Step `key` toward `target` by at most `maxDelta` without overshooting, then clamp
41
+ * to `bounds`. Writes in place and returns the stored value.
42
+ *
43
+ * @capability move a keyed value toward a target by a bounded step
44
+ */
45
+ export function towardValue(record, key, target, maxDelta, bounds) {
46
+ const step = maxDelta > 0 ? maxDelta : 0;
47
+ return setValue(record, key, moveTowards(getValue(record, key), target, step), bounds);
48
+ }
49
+ /**
50
+ * Decay `key` toward a `rest` value (default `0`) by `rate` per call — the common
51
+ * "relationships cool off" / "heat fades" drift. Thin wrapper over {@link towardValue}.
52
+ */
53
+ export function driftValue(record, key, rate, rest = 0, bounds) {
54
+ return towardValue(record, key, rest, rate, bounds);
55
+ }
56
+ const ESCAPE = "\\";
57
+ function escapeComponent(value, separator) {
58
+ let out = "";
59
+ for (const ch of value) {
60
+ if (ch === ESCAPE || ch === separator)
61
+ out += ESCAPE;
62
+ out += ch;
63
+ }
64
+ return out;
65
+ }
66
+ function splitEscaped(key, separator) {
67
+ const parts = [];
68
+ let current = "";
69
+ let escaped = false;
70
+ for (const ch of key) {
71
+ if (escaped) {
72
+ current += ch;
73
+ escaped = false;
74
+ }
75
+ else if (ch === ESCAPE) {
76
+ escaped = true;
77
+ }
78
+ else if (ch === separator) {
79
+ parts.push(current);
80
+ current = "";
81
+ }
82
+ else {
83
+ current += ch;
84
+ }
85
+ }
86
+ parts.push(current);
87
+ return [parts[0] ?? "", parts[1] ?? ""];
88
+ }
89
+ /**
90
+ * Build a pair-key codec for keyed relation values. Ids are escaped before joining,
91
+ * so any id (including ones containing the separator or a backslash) round-trips
92
+ * through {@link PairKeyCodec.key} → {@link PairKeyCodec.parse} without collision.
93
+ * Undirected codecs (the default) canonicalize so `key(a, b) === key(b, a)`.
94
+ *
95
+ * @capability build a serializable directed/undirected pair key that resists delimiter collisions
96
+ */
97
+ export function createPairKeyCodec(options = {}) {
98
+ const directed = options.directed ?? false;
99
+ const separator = options.separator ?? "|";
100
+ if (separator.length !== 1) {
101
+ throw new Error(`pair-key separator must be a single character, got ${JSON.stringify(separator)}`);
102
+ }
103
+ if (separator === ESCAPE)
104
+ throw new Error("pair-key separator cannot be the escape character '\\'");
105
+ return {
106
+ directed,
107
+ key(a, b) {
108
+ const [first, second] = directed || a <= b ? [a, b] : [b, a];
109
+ return `${escapeComponent(first, separator)}${separator}${escapeComponent(second, separator)}`;
110
+ },
111
+ parse(key) {
112
+ return splitEscaped(key, separator);
113
+ },
114
+ };
115
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Generic threshold-crossing detection over ordered numeric boundaries.
3
+ *
4
+ * Deliberately relationship-agnostic and stateless: the same helper reports
5
+ * reputation-tier transitions, meter milestones, temperature bands, ecosystem
6
+ * pressure, difficulty ramps, or any value moving across labelled cut points.
7
+ * Callers pass `before`/`after` and receive the crossings between them, so the
8
+ * logic never lives inside a ledger or owns hidden state.
9
+ */
10
+ export type ThresholdDirection = "up" | "down";
11
+ /** A labelled cut point on the value axis. `Id` is caller-owned (string, enum, or a policy object). */
12
+ export interface ThresholdBoundary<Id = string> {
13
+ /** Stable identifier reported when this boundary is crossed. */
14
+ readonly id: Id;
15
+ /** Numeric position of the boundary on the value axis. */
16
+ readonly at: number;
17
+ }
18
+ /** A single boundary transition between a `before` and `after` value. */
19
+ export interface ThresholdCrossing<Id = string> {
20
+ readonly id: Id;
21
+ readonly at: number;
22
+ readonly direction: ThresholdDirection;
23
+ }
24
+ /** Exact-boundary and dead-band policy for {@link crossThresholds}. */
25
+ export interface CrossThresholdsOptions {
26
+ /**
27
+ * When true (default) a boundary is *occupied* at `value >= at`; when false it
28
+ * is occupied only at `value > at`. Controls exact-boundary semantics: with the
29
+ * default, landing exactly on `at` counts as an upward crossing and keeps you
30
+ * above on the way down.
31
+ */
32
+ readonly inclusive?: boolean;
33
+ /**
34
+ * Symmetric dead-band (clamped to `>= 0`). An upward crossing of `at` requires
35
+ * reaching `at + hysteresis`; a downward crossing requires falling below
36
+ * `at - hysteresis`. Suppresses flapping when a value oscillates around a
37
+ * boundary. Defaults to `0` (no dead-band).
38
+ */
39
+ readonly hysteresis?: number;
40
+ }
41
+ /**
42
+ * Report every boundary crossed moving from `before` to `after`.
43
+ *
44
+ * Upward moves yield `up` crossings in ascending `at` order; downward moves yield
45
+ * `down` crossings in descending order. Large jumps report every boundary passed;
46
+ * a zero-width move reports nothing. Boundaries need not be pre-sorted.
47
+ *
48
+ * @capability detect fire-once threshold/milestone/tier crossings when a value moves
49
+ */
50
+ export declare function crossThresholds<Id>(boundaries: readonly ThresholdBoundary<Id>[], before: number, after: number, options?: CrossThresholdsOptions): ThresholdCrossing<Id>[];
51
+ /**
52
+ * The highest boundary at-or-below `value` — the band the value currently sits in.
53
+ * Returns `null` when `value` is below every boundary. Boundaries need not be sorted.
54
+ *
55
+ * Tier labels stay caller policy: pass an `Id` object carrying whatever label,
56
+ * relation, or colour the game needs.
57
+ *
58
+ * @capability resolve the current tier/band label for a keyed or scalar value
59
+ */
60
+ export declare function tierAt<Id>(boundaries: readonly ThresholdBoundary<Id>[], value: number, options?: {
61
+ readonly inclusive?: boolean;
62
+ }): ThresholdBoundary<Id> | null;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Generic threshold-crossing detection over ordered numeric boundaries.
3
+ *
4
+ * Deliberately relationship-agnostic and stateless: the same helper reports
5
+ * reputation-tier transitions, meter milestones, temperature bands, ecosystem
6
+ * pressure, difficulty ramps, or any value moving across labelled cut points.
7
+ * Callers pass `before`/`after` and receive the crossings between them, so the
8
+ * logic never lives inside a ledger or owns hidden state.
9
+ */
10
+ /**
11
+ * Report every boundary crossed moving from `before` to `after`.
12
+ *
13
+ * Upward moves yield `up` crossings in ascending `at` order; downward moves yield
14
+ * `down` crossings in descending order. Large jumps report every boundary passed;
15
+ * a zero-width move reports nothing. Boundaries need not be pre-sorted.
16
+ *
17
+ * @capability detect fire-once threshold/milestone/tier crossings when a value moves
18
+ */
19
+ export function crossThresholds(boundaries, before, after, options = {}) {
20
+ if (after === before)
21
+ return [];
22
+ const inclusive = options.inclusive ?? true;
23
+ const margin = options.hysteresis !== undefined && options.hysteresis > 0 ? options.hysteresis : 0;
24
+ const rising = after > before;
25
+ const occupied = (value, edge) => (inclusive ? value >= edge : value > edge);
26
+ const crossings = [];
27
+ for (const boundary of boundaries) {
28
+ if (rising) {
29
+ const edge = boundary.at + margin;
30
+ if (!occupied(before, edge) && occupied(after, edge)) {
31
+ crossings.push({ id: boundary.id, at: boundary.at, direction: "up" });
32
+ }
33
+ }
34
+ else {
35
+ const edge = boundary.at - margin;
36
+ if (occupied(before, edge) && !occupied(after, edge)) {
37
+ crossings.push({ id: boundary.id, at: boundary.at, direction: "down" });
38
+ }
39
+ }
40
+ }
41
+ crossings.sort((a, b) => (rising ? a.at - b.at : b.at - a.at));
42
+ return crossings;
43
+ }
44
+ /**
45
+ * The highest boundary at-or-below `value` — the band the value currently sits in.
46
+ * Returns `null` when `value` is below every boundary. Boundaries need not be sorted.
47
+ *
48
+ * Tier labels stay caller policy: pass an `Id` object carrying whatever label,
49
+ * relation, or colour the game needs.
50
+ *
51
+ * @capability resolve the current tier/band label for a keyed or scalar value
52
+ */
53
+ export function tierAt(boundaries, value, options = {}) {
54
+ const inclusive = options.inclusive ?? true;
55
+ let match = null;
56
+ for (const boundary of boundaries) {
57
+ const occupied = inclusive ? value >= boundary.at : value > boundary.at;
58
+ if (occupied && (match === null || boundary.at > match.at))
59
+ match = boundary;
60
+ }
61
+ return match;
62
+ }
@@ -0,0 +1,12 @@
1
+ /** Split a `#rrggbb` hex color into its `[r, g, b]` channels (0–255).
2
+ * @internal
3
+ */
4
+ export declare function hexToRgb(hex: string): readonly [number, number, number];
5
+ /** Combine `[r, g, b]` channels (0–255, rounded) into a `#rrggbb` hex string.
6
+ * @internal
7
+ */
8
+ export declare function rgbToHex(r: number, g: number, b: number): string;
9
+ /** Interpolate between two `#rrggbb` colors by fraction `t`, clamped to the endpoints.
10
+ * @internal
11
+ */
12
+ export declare function mixHex(from: string, to: string, t: number): string;
@@ -0,0 +1,26 @@
1
+ /** Split a `#rrggbb` hex color into its `[r, g, b]` channels (0–255).
2
+ * @internal
3
+ */
4
+ export function hexToRgb(hex) {
5
+ const value = Number.parseInt(hex.slice(1), 16);
6
+ return [(value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff];
7
+ }
8
+ /** Combine `[r, g, b]` channels (0–255, rounded) into a `#rrggbb` hex string.
9
+ * @internal
10
+ */
11
+ export function rgbToHex(r, g, b) {
12
+ const value = ((Math.round(r) & 0xff) << 16) | ((Math.round(g) & 0xff) << 8) | (Math.round(b) & 0xff);
13
+ return `#${value.toString(16).padStart(6, "0")}`;
14
+ }
15
+ /** Interpolate between two `#rrggbb` colors by fraction `t`, clamped to the endpoints.
16
+ * @internal
17
+ */
18
+ export function mixHex(from, to, t) {
19
+ if (t <= 0)
20
+ return from;
21
+ if (t >= 1)
22
+ return to;
23
+ const [fr, fg, fb] = hexToRgb(from);
24
+ const [tr, tg, tb] = hexToRgb(to);
25
+ return rgbToHex(fr + (tr - fr) * t, fg + (tg - fg) * t, fb + (tb - fb) * t);
26
+ }