@v12-engine/engine 0.0.0-stage → 0.1.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 (341) hide show
  1. package/LICENSE +21 -0
  2. package/dist/abilities/buffs.d.ts +83 -0
  3. package/dist/abilities/castTold.d.ts +12 -0
  4. package/dist/abilities/charges.d.ts +28 -0
  5. package/dist/abilities/dispel.d.ts +9 -0
  6. package/dist/abilities/effectFields.d.ts +10 -0
  7. package/dist/abilities/effects/buff.d.ts +8 -0
  8. package/dist/abilities/effects/core.d.ts +1 -0
  9. package/dist/abilities/effects/damage.d.ts +1 -0
  10. package/dist/abilities/effects/heal.d.ts +2 -0
  11. package/dist/abilities/effects/missile.d.ts +1 -0
  12. package/dist/abilities/effects/moves.d.ts +11 -0
  13. package/dist/abilities/effects/passives.d.ts +15 -0
  14. package/dist/abilities/effects/sight.d.ts +4 -0
  15. package/dist/abilities/effects/spawn.d.ts +2 -0
  16. package/dist/abilities/effects/timed.d.ts +4 -0
  17. package/dist/abilities/effects/trade.d.ts +1 -0
  18. package/dist/abilities/effects.d.ts +122 -0
  19. package/dist/abilities/land.d.ts +21 -0
  20. package/dist/abilities/scaled.d.ts +21 -0
  21. package/dist/abilities/text.d.ts +113 -0
  22. package/dist/ai/area.d.ts +53 -0
  23. package/dist/ai/brain.d.ts +528 -0
  24. package/dist/ai/budget.d.ts +67 -0
  25. package/dist/ai/checks.d.ts +115 -0
  26. package/dist/ai/computer.d.ts +166 -0
  27. package/dist/ai/defence.d.ts +108 -0
  28. package/dist/ai/define.d.ts +21 -0
  29. package/dist/ai/economy.d.ts +129 -0
  30. package/dist/ai/geometry.d.ts +35 -0
  31. package/dist/ai/goals.d.ts +360 -0
  32. package/dist/ai/index.d.ts +38 -0
  33. package/dist/ai/knowledge.d.ts +418 -0
  34. package/dist/ai/lanes.d.ts +232 -0
  35. package/dist/ai/melee/build.d.ts +61 -0
  36. package/dist/ai/melee/goals.d.ts +299 -0
  37. package/dist/ai/melee/heroes.d.ts +27 -0
  38. package/dist/ai/melee/index.d.ts +14 -0
  39. package/dist/ai/melee/production.d.ts +8 -0
  40. package/dist/ai/melee/surrender.d.ts +24 -0
  41. package/dist/ai/micro.d.ts +278 -0
  42. package/dist/ai/mission.d.ts +195 -0
  43. package/dist/ai/missionRules.d.ts +18 -0
  44. package/dist/ai/module.d.ts +116 -0
  45. package/dist/ai/options.d.ts +61 -0
  46. package/dist/ai/plans/build.d.ts +280 -0
  47. package/dist/ai/plans/placement.d.ts +82 -0
  48. package/dist/ai/plans/plans.d.ts +105 -0
  49. package/dist/ai/plans/production.d.ts +210 -0
  50. package/dist/ai/plans/purse.d.ts +73 -0
  51. package/dist/ai/plans/tech.d.ts +37 -0
  52. package/dist/ai/profiles.d.ts +204 -0
  53. package/dist/ai/reach.d.ts +4 -0
  54. package/dist/ai/report.d.ts +203 -0
  55. package/dist/ai/roles.d.ts +133 -0
  56. package/dist/ai/rules.d.ts +288 -0
  57. package/dist/ai/scouting.d.ts +98 -0
  58. package/dist/ai/settings.d.ts +73 -0
  59. package/dist/ai/squads.d.ts +429 -0
  60. package/dist/ai/strength.d.ts +167 -0
  61. package/dist/ai/task.d.ts +118 -0
  62. package/dist/ai/tasks/attack.d.ts +7 -0
  63. package/dist/ai/tasks/capture.d.ts +21 -0
  64. package/dist/ai/tasks/creep.d.ts +16 -0
  65. package/dist/ai/tasks/defend.d.ts +29 -0
  66. package/dist/ai/tasks/drop.d.ts +34 -0
  67. package/dist/ai/tasks/escort.d.ts +16 -0
  68. package/dist/ai/tasks/gather.d.ts +23 -0
  69. package/dist/ai/tasks/harass.d.ts +7 -0
  70. package/dist/ai/tasks/hold.d.ts +20 -0
  71. package/dist/ai/tasks/index.d.ts +32 -0
  72. package/dist/ai/tasks/move.d.ts +19 -0
  73. package/dist/ai/tasks/patrol.d.ts +8 -0
  74. package/dist/ai/tasks/retreat.d.ts +20 -0
  75. package/dist/ai/tasks/scout.d.ts +29 -0
  76. package/dist/ai/tasks/shared.d.ts +74 -0
  77. package/dist/ai/team.d.ts +155 -0
  78. package/dist/ai/threat.d.ts +91 -0
  79. package/dist/ai/view.d.ts +366 -0
  80. package/dist/ai/waves.d.ts +126 -0
  81. package/dist/ai.js +6239 -0
  82. package/dist/ai.js.map +1 -0
  83. package/dist/aiTesting.d.ts +179 -0
  84. package/dist/areas.d.ts +149 -0
  85. package/dist/attacks.d.ts +66 -0
  86. package/dist/attributes.d.ts +66 -0
  87. package/dist/brain-BvVdUhX8.js +7659 -0
  88. package/dist/brain-BvVdUhX8.js.map +1 -0
  89. package/dist/builds-C6LfgvEU.js +460 -0
  90. package/dist/builds-C6LfgvEU.js.map +1 -0
  91. package/dist/bytes.d.ts +6 -0
  92. package/dist/camps.d.ts +95 -0
  93. package/dist/capture.d.ts +131 -0
  94. package/dist/cellLayers.d.ts +75 -0
  95. package/dist/cinematics.d.ts +194 -0
  96. package/dist/clock.d.ts +32 -0
  97. package/dist/commands.d.ts +235 -0
  98. package/dist/components.d.ts +184 -0
  99. package/dist/computers.d.ts +108 -0
  100. package/dist/concealment.d.ts +61 -0
  101. package/dist/coreComponents-syuh2fPG.js +5149 -0
  102. package/dist/coreComponents-syuh2fPG.js.map +1 -0
  103. package/dist/coreComponents.d.ts +1 -0
  104. package/dist/dashing.d.ts +8 -0
  105. package/dist/debug.d.ts +36 -0
  106. package/dist/debug.js +3 -0
  107. package/dist/debugCommands-CzjrSm66.js +14739 -0
  108. package/dist/debugCommands-CzjrSm66.js.map +1 -0
  109. package/dist/debugCommands.d.ts +213 -0
  110. package/dist/debugging.d.ts +10 -0
  111. package/dist/definitions.d.ts +43 -0
  112. package/dist/defs.d.ts +1162 -0
  113. package/dist/denying.d.ts +81 -0
  114. package/dist/destructibles.d.ts +27 -0
  115. package/dist/determinism-BCymQwiE.js +518 -0
  116. package/dist/determinism-BCymQwiE.js.map +1 -0
  117. package/dist/determinism.d.ts +121 -0
  118. package/dist/dialog.d.ts +94 -0
  119. package/dist/effectRefs.d.ts +16 -0
  120. package/dist/effects.d.ts +80 -0
  121. package/dist/endings.d.ts +22 -0
  122. package/dist/engagement.d.ts +108 -0
  123. package/dist/engineEvents.d.ts +710 -0
  124. package/dist/entity.d.ts +409 -0
  125. package/dist/entityIndex.d.ts +50 -0
  126. package/dist/errors.d.ts +85 -0
  127. package/dist/events.d.ts +97 -0
  128. package/dist/exactMath.d.ts +63 -0
  129. package/dist/features.d.ts +10 -0
  130. package/dist/fields.d.ts +114 -0
  131. package/dist/fixture.d.ts +17 -0
  132. package/dist/fog.d.ts +110 -0
  133. package/dist/formation.d.ts +111 -0
  134. package/dist/friendlyFire.d.ts +26 -0
  135. package/dist/game-DiJEN-Ks.js +5800 -0
  136. package/dist/game-DiJEN-Ks.js.map +1 -0
  137. package/dist/game.d.ts +501 -0
  138. package/dist/gameData.d.ts +325 -0
  139. package/dist/gameFiles.d.ts +26 -0
  140. package/dist/gates.d.ts +28 -0
  141. package/dist/generate.d.ts +403 -0
  142. package/dist/generateWorker.d.ts +39 -0
  143. package/dist/grid.d.ts +53 -0
  144. package/dist/ground.d.ts +127 -0
  145. package/dist/groundSpeed.d.ts +22 -0
  146. package/dist/hero.d.ts +177 -0
  147. package/dist/home.d.ts +14 -0
  148. package/dist/hooks.d.ts +780 -0
  149. package/dist/hotReload.d.ts +76 -0
  150. package/dist/ids.d.ts +26 -0
  151. package/dist/index.d.ts +227 -0
  152. package/dist/index.js +4701 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/inspect-D9dWHmZ0.js +491 -0
  155. package/dist/inspect-D9dWHmZ0.js.map +1 -0
  156. package/dist/inspect.d.ts +176 -0
  157. package/dist/inventory.d.ts +18 -0
  158. package/dist/items.d.ts +91 -0
  159. package/dist/lanes.d.ts +213 -0
  160. package/dist/life.d.ts +53 -0
  161. package/dist/local-Dkovq42k.js +1379 -0
  162. package/dist/local-Dkovq42k.js.map +1 -0
  163. package/dist/log.d.ts +140 -0
  164. package/dist/manaBurn.d.ts +39 -0
  165. package/dist/map/file.d.ts +114 -0
  166. package/dist/map/images.d.ts +18 -0
  167. package/dist/map/look.d.ts +47 -0
  168. package/dist/map/pathProfile.d.ts +13 -0
  169. package/dist/map/resize.d.ts +54 -0
  170. package/dist/map/schema.d.ts +10 -0
  171. package/dist/map/terrain.d.ts +32 -0
  172. package/dist/map/types.d.ts +613 -0
  173. package/dist/map.d.ts +7 -0
  174. package/dist/mapCheck/cells.d.ts +19 -0
  175. package/dist/mapCheck/rule.d.ts +30 -0
  176. package/dist/mapCheck/rules/names.d.ts +3 -0
  177. package/dist/mapCheck/rules/objects.d.ts +3 -0
  178. package/dist/mapCheck/rules/paths.d.ts +3 -0
  179. package/dist/mapCheck/rules/players.d.ts +3 -0
  180. package/dist/mapCheck/rules/races.d.ts +3 -0
  181. package/dist/mapCheck/rules/random.d.ts +3 -0
  182. package/dist/mapCheck/rules/regions.d.ts +3 -0
  183. package/dist/mapCheck/rules/targets.d.ts +3 -0
  184. package/dist/mapCheck/rules/walking.d.ts +3 -0
  185. package/dist/mapCheck.d.ts +23 -0
  186. package/dist/mapFields.d.ts +364 -0
  187. package/dist/mapFile.d.ts +23 -0
  188. package/dist/mapMeasure.d.ts +95 -0
  189. package/dist/mapMerge.d.ts +19 -0
  190. package/dist/mapObjectives.d.ts +82 -0
  191. package/dist/mapObjects.d.ts +1 -0
  192. package/dist/math.d.ts +44 -0
  193. package/dist/messages.d.ts +150 -0
  194. package/dist/missionRules-C-bGxm0Q.js +523 -0
  195. package/dist/missionRules-C-bGxm0Q.js.map +1 -0
  196. package/dist/missionRules.d.ts +179 -0
  197. package/dist/mods.d.ts +146 -0
  198. package/dist/names.d.ts +93 -0
  199. package/dist/navigation/agentParams.d.ts +4 -0
  200. package/dist/navigation/air.d.ts +89 -0
  201. package/dist/navigation/builds.d.ts +140 -0
  202. package/dist/navigation/groundAreas.d.ts +23 -0
  203. package/dist/navigation/navigation.d.ts +127 -0
  204. package/dist/navigation/recast.d.ts +214 -0
  205. package/dist/navigation/sidePaths.d.ts +69 -0
  206. package/dist/navigation/sized.d.ts +1 -0
  207. package/dist/navigation-worker.js +11 -0
  208. package/dist/navigation-worker.js.map +1 -0
  209. package/dist/nearest.d.ts +8 -0
  210. package/dist/noise.d.ts +12 -0
  211. package/dist/objectives.d.ts +93 -0
  212. package/dist/orders/basic.d.ts +96 -0
  213. package/dist/orders/build.d.ts +91 -0
  214. package/dist/orders/cast.d.ts +105 -0
  215. package/dist/orders/facts.d.ts +14 -0
  216. package/dist/orders/harvest.d.ts +94 -0
  217. package/dist/orders/idle.d.ts +7 -0
  218. package/dist/orders/items.d.ts +14 -0
  219. package/dist/orders/queue.d.ts +24 -0
  220. package/dist/pack.schema.json +6621 -0
  221. package/dist/packs/director/index.d.ts +81 -0
  222. package/dist/packs/heroes/campaign.d.ts +137 -0
  223. package/dist/packs/heroes/carry.d.ts +59 -0
  224. package/dist/packs/heroes/commands.d.ts +6 -0
  225. package/dist/packs/heroes/hire.d.ts +9 -0
  226. package/dist/packs/heroes/index.d.ts +12 -0
  227. package/dist/packs/heroes/making.d.ts +16 -0
  228. package/dist/packs/heroes/respawn.d.ts +42 -0
  229. package/dist/packs/moba/index.d.ts +34 -0
  230. package/dist/packs/pack.d.ts +84 -0
  231. package/dist/packs-g5thvmGn.js +3199 -0
  232. package/dist/packs-g5thvmGn.js.map +1 -0
  233. package/dist/packs.d.ts +84 -0
  234. package/dist/paths.d.ts +51 -0
  235. package/dist/plain.d.ts +17 -0
  236. package/dist/player.d.ts +117 -0
  237. package/dist/portals.d.ts +66 -0
  238. package/dist/prefabs.d.ts +139 -0
  239. package/dist/presetBuildings.d.ts +52 -0
  240. package/dist/presetGround.d.ts +22 -0
  241. package/dist/profiles-B3NS9jwk.js +335 -0
  242. package/dist/profiles-B3NS9jwk.js.map +1 -0
  243. package/dist/races.d.ts +136 -0
  244. package/dist/randomGroups.d.ts +2 -0
  245. package/dist/registry.d.ts +464 -0
  246. package/dist/remains.d.ts +119 -0
  247. package/dist/replication.d.ts +103 -0
  248. package/dist/rng.d.ts +17 -0
  249. package/dist/rules.d.ts +395 -0
  250. package/dist/rulesCheck.d.ts +37 -0
  251. package/dist/runes.d.ts +41 -0
  252. package/dist/save.d.ts +277 -0
  253. package/dist/scenario.d.ts +56 -0
  254. package/dist/scheduler.d.ts +67 -0
  255. package/dist/score.d.ts +306 -0
  256. package/dist/sequences.d.ts +132 -0
  257. package/dist/server/doorman.d.ts +21 -0
  258. package/dist/server/gameServer.d.ts +346 -0
  259. package/dist/server/index.d.ts +24 -0
  260. package/dist/server/lobby.d.ts +1 -0
  261. package/dist/server/log.d.ts +13 -0
  262. package/dist/server/match.d.ts +24 -0
  263. package/dist/server/mode.d.ts +168 -0
  264. package/dist/server/navigation-worker.d.ts +1 -0
  265. package/dist/server/navigation.d.ts +11 -0
  266. package/dist/server/ops.d.ts +78 -0
  267. package/dist/server/packs.d.ts +15 -0
  268. package/dist/server/ratings.d.ts +62 -0
  269. package/dist/server/relay.d.ts +34 -0
  270. package/dist/server/rooms.d.ts +162 -0
  271. package/dist/server/seat.d.ts +2 -0
  272. package/dist/server/seatSettings.d.ts +15 -0
  273. package/dist/server/secret.d.ts +5 -0
  274. package/dist/server/start.d.ts +54 -0
  275. package/dist/server/websocket.d.ts +74 -0
  276. package/dist/server.js +2861 -0
  277. package/dist/server.js.map +1 -0
  278. package/dist/session/can.d.ts +20 -0
  279. package/dist/session/commandReplay.d.ts +92 -0
  280. package/dist/session/debug.d.ts +65 -0
  281. package/dist/session/delay.d.ts +15 -0
  282. package/dist/session/delta.d.ts +98 -0
  283. package/dist/session/entityState.d.ts +1 -0
  284. package/dist/session/local.d.ts +214 -0
  285. package/dist/session/memory.d.ts +27 -0
  286. package/dist/session/protocol.d.ts +1155 -0
  287. package/dist/session/remote.d.ts +530 -0
  288. package/dist/session/replay.d.ts +114 -0
  289. package/dist/session/seed.d.ts +7 -0
  290. package/dist/session/share.d.ts +78 -0
  291. package/dist/session/socket.d.ts +8 -0
  292. package/dist/session/wire.d.ts +153 -0
  293. package/dist/session/worker.d.ts +227 -0
  294. package/dist/shared.d.ts +171 -0
  295. package/dist/sides.d.ts +75 -0
  296. package/dist/sight.d.ts +27 -0
  297. package/dist/simulate-oXBiw1Ff.js +167 -0
  298. package/dist/simulate-oXBiw1Ff.js.map +1 -0
  299. package/dist/simulate-worker.d.ts +1 -0
  300. package/dist/simulate-worker.js +28 -0
  301. package/dist/simulate-worker.js.map +1 -0
  302. package/dist/simulate.d.ts +154 -0
  303. package/dist/smart.d.ts +9 -0
  304. package/dist/spatial.d.ts +62 -0
  305. package/dist/spawning.d.ts +33 -0
  306. package/dist/stances.d.ts +76 -0
  307. package/dist/start.d.ts +71 -0
  308. package/dist/stats.d.ts +122 -0
  309. package/dist/summons.d.ts +63 -0
  310. package/dist/systems/abilities.d.ts +3 -0
  311. package/dist/systems/combat.d.ts +71 -0
  312. package/dist/systems/combatTold.d.ts +14 -0
  313. package/dist/systems/construction.d.ts +34 -0
  314. package/dist/systems/economy.d.ts +21 -0
  315. package/dist/systems/fog.d.ts +19 -0
  316. package/dist/systems/life.d.ts +3 -0
  317. package/dist/systems/movement.d.ts +105 -0
  318. package/dist/systems/orders.d.ts +7 -0
  319. package/dist/systems/production.d.ts +49 -0
  320. package/dist/systems/productionQueue.d.ts +40 -0
  321. package/dist/systems/victory.d.ts +14 -0
  322. package/dist/talk.d.ts +65 -0
  323. package/dist/tech.d.ts +62 -0
  324. package/dist/techTree.d.ts +38 -0
  325. package/dist/terrain.d.ts +173 -0
  326. package/dist/terrainSave.d.ts +29 -0
  327. package/dist/testing.d.ts +58 -0
  328. package/dist/testing.js +822 -0
  329. package/dist/testing.js.map +1 -0
  330. package/dist/tiles.d.ts +34 -0
  331. package/dist/timers.d.ts +146 -0
  332. package/dist/tomes.d.ts +48 -0
  333. package/dist/trade.d.ts +28 -0
  334. package/dist/transport.d.ts +76 -0
  335. package/dist/tunables.d.ts +45 -0
  336. package/dist/upkeep.d.ts +16 -0
  337. package/dist/veterancy.d.ts +80 -0
  338. package/dist/walls.d.ts +86 -0
  339. package/dist/world.d.ts +1118 -0
  340. package/package.json +80 -5
  341. package/README.md +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-Dkovq42k.js","names":["checkpointEvent"],"sources":["../src/session/protocol.ts","../src/session/can.ts","../src/session/delta.ts","../src/session/debug.ts","../src/session/entityState.ts","../src/session/local.ts"],"sourcesContent":["import type { SystemTiming } from '#engine/scheduler'\nimport type { DataKind, DataValues } from '#engine/gameData'\nimport type { Logger } from '#engine/log'\nimport type { Command, ModCommand } from '#engine/commands'\nimport type { ChatAudience, PingKind } from '#engine/talk'\nimport type { Cost, DamageType, ResourceKind, Stats } from '#engine/defs'\nimport type { PlayerId } from '#engine/entity'\nimport type { Vec2 } from '#engine/math'\nimport type { SaidLine } from '#engine/dialog'\nimport type { Message } from '#engine/messages'\nimport type { ObjectiveState, ObjectiveStatus } from '#engine/objectives'\nimport type { ShownTimer } from '#engine/timers'\nimport type { WorldSave } from '#engine/save'\nimport type { Registry } from '#engine/registry'\nimport type { Inspection, InspectTarget, LoggedEvent, WorldListing } from '#engine/inspect'\nimport type { Lane } from '#engine/lanes'\nimport type { MapCamera, MapDoodad, MapEnvironment, MapPath, MapRegion } from '#engine/map'\nimport type { Terrain } from '#engine/terrain'\nimport type { TerrainPatch } from '#engine/ground'\nimport type { MessageKind } from '#engine/world'\nimport type { ScoreLineState, ScoreState } from '#engine/score'\n\n/**\n * What travels between the simulation and a player's screen.\n *\n * A client never touches the world. It gets snapshots of what its player is allowed\n * to know and sends commands back. Today both ends live in the same page, later the\n * simulation runs on a server, and nothing on the client has to change for that.\n * Everything in here is plain data for that reason: it has to survive being sent.\n */\n\n/** @beta */\nexport interface QueueItemState {\n\tkind: 'unit' | 'upgrade' | 'revive' | 'morph'\n\tid: string\n\t/** 0..1 */\n\tprogress: number\n}\n\n/** @beta */\nexport interface AbilityInfo {\n\tid: string\n\tlevel: number\n\t/** Seconds until it can be used again */\n\tcooldown: number\n\t/** Uses left, of an ability with charges, while it holds fewer than it can (all of them when left out: `chargesLeft`) */\n\tcharges?: number\n\t/** Seconds until the next use is back, while it holds fewer than it can */\n\trefill?: number\n\tautocast: boolean\n\t/**\n\t * What the game's `canCast` hook decided, where it is not what the declared costs say: a reason it cannot be used\n\t * now, or null for one it can be used for all that (\"free while Clearcasting\"). Left out when there is nothing to add\n\t */\n\tdecided?: Message | null\n}\n\n/**\n * An ability of a unit as everyone who sees it may be told (`GameRules.hud.shareAbilities`): what it is and its\n * level, and how much of its cooldown is left where the rules share that too\n *\n * @beta\n */\nexport interface SharedAbility {\n\t/** The ability's id */\n\tid: string\n\t/** Its level: 1 and up, those not learned are not told */\n\tlevel: number\n\t/**\n\t * Seconds until it can be used again: with `shareAbilities: 'cooldowns'` alone. Whole seconds, rounded up, from a\n\t * host (`quantize`): the plate counts down between\n\t */\n\tcooldown?: number\n}\n\n/**\n * Something a unit carries\n *\n * @beta\n */\nexport interface CarriedItem {\n\t/** Which one of the unit's items, for commands */\n\tid: number\n\titem: string\n\tcharges: number\n\t/** Seconds until it can be used again */\n\tcooldown: number\n\t/**\n\t * Uses left of the ability it casts, where that has charges (`AbilityDef.charges`) and holds fewer than it can: all\n\t * of them when left out. None, and it cannot be used until one comes back\n\t */\n\tuses?: number\n}\n\n/**\n * What everyone who sees a unit is told of its items (`inventorySlots`' snapshot): what it carries; its owner and their\n * allies the slots too, for commands\n *\n * @beta\n */\nexport interface InventoryInfo {\n\t/** The items it carries, by id: anyone who sees the unit sees that */\n\titems: string[]\n\t/** One entry per slot, null for the empty ones: for its owner and their allies */\n\tslots?: (CarriedItem | null)[]\n}\n\n/**\n * What a worker's owner and their allies are told of what it carries (`gathering`'s snapshot)\n *\n * @beta\n */\nexport interface GatheringInfo {\n\t/** How much of it */\n\tcarrying: number\n\t/** What it is that it carries, or last gathered. Null for a worker that has not gathered anything yet */\n\tkind: ResourceKind | null\n}\n\n/**\n * What a building's owner and their allies are told of what it makes (`productionQueue`'s snapshot): its queue and where\n * what comes out goes; and everyone who sees it, how far it is in turning into another type\n *\n * @beta\n */\nexport interface ProductionInfo {\n\t/** What it makes, the first being made: for its owner and their allies */\n\tqueue?: QueueItemState[]\n\t/** Where what it makes goes once out: for its owner and their allies */\n\trally?: Vec2\n\t/** 0..1 while it turns into another type (`upgradeTo`, `UnitTypeDef.upgradesTo`): what every player who sees it sees */\n\tupgrade?: number\n\t/** The type it turns into, while it does */\n\tupgradeTo?: string\n}\n\n/**\n * An item lying on the ground\n *\n * @beta\n */\nexport interface GroundItemState {\n\tid: number\n\titem: string\n\tx: number\n\tz: number\n}\n\n/** @beta */\nexport interface StockInfo {\n\titem: string\n\t/** How many are left. Left out for what a shop never runs out of */\n\tcount?: number\n\t/** 0..1 towards the next one, when the shop is not full */\n\trestock: number\n}\n\n/**\n * An ability a hero can put points into\n *\n * @beta\n */\nexport interface LearnableInfo {\n\tid: string\n\tlevel: number\n\tmaxLevel: number\n\t/** Hero level needed for the next level of the ability */\n\tneeds: number\n\t/** Whether a point can go into it right now */\n\tavailable: boolean\n}\n\n/**\n * A hero's experience: what it has, at what the level it is at started and at what the next one does (`HeroSent.xp`)\n *\n * @beta\n */\nexport interface XpInfo {\n\t/** Experience in total, whole */\n\txp: number\n\t/** What the level it is at took */\n\tlevelXp: number\n\t/** What the next level takes */\n\tnextXp: number\n}\n\n/**\n * A hero of the player, for the row of portraits. Fallen ones are in here too\n *\n * @beta\n */\nexport interface HeroSummary {\n\tid: number\n\ttype: string\n\tlevel: number\n\talive: boolean\n\t/** 0..1 */\n\thp: number\n\tmana: number\n\tpoints: number\n\t/** 0..1 while being brought back: at an altar, or coming back by itself (`withRespawn`) */\n\treviving?: number\n\t/** Seconds until it comes back by itself, while it waits to (`withRespawn`) */\n\trespawnIn?: number\n\t/** What bringing it back would cost */\n\treviveCost?: Cost\n}\n\n/**\n * The part of an entity only its owner and their allies get to know\n *\n * @beta\n */\nexport interface OwnEntityState {\n\t/** Another player's, which this one may command: its owner shares control with them (`world.shareControl`) */\n\tshared?: boolean\n\t/** Inside something, like a worker in a mine */\n\thidden: boolean\n\t/** Type of the order being carried out */\n\torder: string | null\n\t/** What it is about to build, for a build order */\n\tbuild?: string\n\t/** Orders in the queue, the current one included */\n\torders: number\n\tpassive: boolean\n\tfighting: boolean\n\t/** Where it is walking to right now */\n\tgoal?: Vec2\n\t/** Destinations of the orders waiting in the queue: none while nothing waits */\n\twaypoints?: Vec2[]\n\tabilities?: AbilityInfo[]\n}\n\n/** @beta */\nexport interface EntityState {\n\tid: number\n\ttype: string\n\towner: PlayerId\n\tx: number\n\tz: number\n\tfacing: number\n\thp: number\n\t/** The stats that are not what its type starts with. Whoever sees a unit can tell what it is capable of */\n\tstats?: Partial<Stats>\n\t/** What its shields still hold */\n\tshield?: number\n\t/** On its way through the air: from where to where, and how high it rises in between */\n\tleap?: { from: Vec2; to: Vec2; height: number }\n\t/** False for a structure that is out of sight and shown the way it was last seen */\n\tvisible: boolean\n\t/** Left out when it is what the unit type says */\n\tmaxHp?: number\n\tmana?: number\n\tmaxMana?: number\n\t/** Ids of the buffs on it */\n\tbuffs?: string[]\n\t/** How many of each of its buffs that stack it carries, for the ones it carries any of */\n\tstacks?: Record<string, number>\n\t/**\n\t * Seconds left of each of its `buffs`, in their order (whole seconds, rounded up, from a host: the plate counts\n\t * down between); -1 for one kept up by an aura or a passive (`BuffInstance.kept`) or that lasts until it is\n\t * taken off. Where the rules share them (`GameRules.hud.shareBuffTimes`)\n\t *\n\t * @beta\n\t */\n\tbuffTimes?: number[]\n\t/**\n\t * The abilities it has learned, for whoever sees it, its side's or not, where the rules share them\n\t * (`GameRules.hud.shareAbilities`). Its side has them in `own.abilities` all the same\n\t *\n\t * @beta\n\t */\n\tabilities?: SharedAbility[]\n\t/** What is left in a resource */\n\tresource?: number\n\t/** The resource it stands on (`UnitTypeDef.builtOn`, a cursed mine on a gold mine), by id */\n\ton?: number\n\t/** Doing nothing until woken, like a creep sleeping through the night */\n\tasleep?: boolean\n\t/** How big it is drawn, when that is not 1 */\n\tscale?: number\n\t/** Which of the models of its type it is drawn with, when the map says */\n\tlook?: string\n\t/** Seconds left and seconds in all, for what is gone by itself after a while, like a ward */\n\tlifetime?: { left: number; total: number }\n\t/** Invisible to enemies right now. Whoever gets this sees it all the same: it is theirs, or they found it */\n\tunseen?: boolean\n\t/** Components of game modules and mods that are sent to this player (see `Component.replicate`), by id */\n\tcomponents?: Record<string, unknown>\n\t/** The name the map or the rules gave it (`world.named`), for whoever knows of it: \"the gate\", \"the hero\" */\n\tname?: string\n\town?: OwnEntityState\n}\n\n/** @beta */\nexport interface PlayerState {\n\tid: PlayerId\n\tname: string\n\tteam: number\n\tcolor: [number, number, number]\n\tneutral: boolean\n\t/** Whether they are the creeps: hostile to everyone, but no one's rival */\n\tcreeps?: boolean\n\t/** The race they play (`raceOf`): left out in a game without races */\n\trace?: string\n\tdefeated: boolean\n\t/** What they are to the player the snapshot is for: by their teams, or as the rules set it (`setRelation`) */\n\trelation: 'self' | 'ally' | 'enemy' | 'neutral'\n\t/**\n\t * What the player the snapshot is for shares with this ally (`shareWith`): their units' control, and their team's\n\t * sight (always, for an ally of their team). Left out for who is not an ally\n\t */\n\tshared?: { control: boolean; vision: boolean }\n\t/** Only filled in for the player the snapshot is for */\n\town?: {\n\t\t/** What the player has of each resource, by resource id */\n\t\tresources: Record<ResourceKind, number>\n\t\tsupplyUsed: number\n\t\tsupplyCap: number\n\t\t/** The game's other pools of supply, by name (`GameRules.supply.pools`): left out in a game with none */\n\t\tsupplies?: Record<string, { used: number; cap: number }>\n\t\t/** What the size of the army costs in income */\n\t\tupkeep: { tier: number; name: string; income: number }\n\t\tupgrades: Record<string, number>\n\t\tresearching: string[]\n\t\t/** Types of the finished buildings the player has, with what those count as */\n\t\ttech: string[]\n\t\theroes: HeroSummary[]\n\t\t/** What the player is set to do, in a mission. Empty in a game without objectives */\n\t\tobjectives: ObjectiveState[]\n\t\t/** The timers the rules show the player (`world.timers.show`): their words and the tick each goes off at */\n\t\ttimers?: ShownTimer[]\n\t\t/**\n\t\t * What the game's `requirement` hook decided, where it differs from what the requirements say (see\n\t\t * `PlayerFacts.unlocks`): by unit or structure type, and `upgrade:<id>` for the next level. Left out without one\n\t\t */\n\t\tunlocks?: Record<string, Message | null>\n\t\t/**\n\t\t * What the game's `available` hook decided, where it differs from what their race says (see\n\t\t * `PlayerFacts.availability`): by unit or structure type, and `upgrade:<id>`. Left out without one\n\t\t */\n\t\tavailability?: Record<string, boolean>\n\t}\n}\n\n/** @beta */\nexport interface ProjectileState {\n\tid: number\n\tx: number\n\tz: number\n\t/** The type of what shot it, known even when the shooter is out of sight: what it looks like */\n\tkind: string\n\towner: PlayerId\n\tcrit: boolean\n\tdamageType: DamageType\n\t/** A look the rules gave it (see `Projectile.look`) */\n\tlook?: string\n\t/** Entity it was fired by, when that one is known to the player */\n\tsource?: number\n\t/** Entity it is after, when that one is known to the player */\n\ttarget?: number\n\t/** Where it was fired from and where it comes down, for shots that are lobbed at a spot */\n\tfrom?: Vec2\n\tto?: Vec2\n}\n\n/**\n * What an ability sent on its way, like a tornado\n *\n * @beta\n */\nexport interface MissileState {\n\tid: number\n\tability: string\n\tlevel: number\n\t/** Entity that sent it, when that one is known to the player */\n\tsource?: number\n\tx: number\n\tz: number\n\tradius: number\n\t/** The way it is heading, in radians */\n\theading: number\n\t/** How far it is with taking shape, 0..1, while it has not set off yet */\n\tforming?: number\n\t/** How much of its way it has come, 0..1, for the ones that go a known way */\n\tprogress?: number\n\t/** How high above the ground its arc carries it now, for what is thrown in one (`EffectFields.arc`) */\n\tarc?: number\n}\n\n/**\n * What the players are told happened during a tick, which cannot be read from the state afterwards: each kind by its\n * `type` (design review E7). The engine's are told by its replications (`replicateEvent(key, type, tell)`, typed by\n * this entry); a pack's or a game's own added by declaration merging, as `OrderStates` is. A screen's handlers are\n * keyed by the same names (`SessionEventOf`)\n *\n * @beta\n */\nexport interface SessionEvents {\n\t/**\n\t * Something died. What killed it (`killer`, `killerType`, `from`, where it stood) when the player sees it; how:\n\t * an attack of the killer's, the blow's damage type, the ability, how much too much, a critical strike, and what\n\t * the rules made of it (`how`, set in the `death` hook: `'exploded'`). For the screen to show it its way\n\t */\n\tdeath: {\n\t\ttype: 'death'\n\t\tid: number\n\t\tfrom?: Vec2\n\t\tkiller?: number\n\t\tkillerType?: string\n\t\tattack: boolean\n\t\tdamageType?: DamageType\n\t\tability?: string\n\t\toverkill?: number\n\t\tcrit?: boolean\n\t\thow?: string\n\t\t/** Why, when it was not of damage (`DeathReason`): `cancelled`, `expired`, a game's own word */\n\t\treason?: string\n\t\t/** The blow's words of the game's own (`DamageOptions.tags`) */\n\t\ttags?: string[]\n\t}\n\t/**\n\t * Cells of one of the game's layers (`Terrain.cells`) were set to `value` (`world.setCells`): the session's ground has\n\t * it already, for the screen to draw again. Told where the player's team sees the cells, and as they come into its sight\n\t * where it does not (`TeamMemory.cells`): an observer is told of all\n\t */\n\tcells: { type: 'cells'; layer: string; at: number[]; value: number }\n\t/**\n\t * A part of the ground was reshaped (`world.reshapeGround`, the editor's Play here): the session's ground has it\n\t * already, for the screen to draw again. Told to everyone\n\t */\n\tground: { type: 'ground'; patch: TerrainPatch }\n\t/**\n\t * Something the player does not see moved in a layer of cells where the player sees the ground (`ConcealmentOptions.rustle`):\n\t * where, and whether it stepped in. Not who: for the screen to shake the bushes there\n\t *\n\t * @beta\n\t */\n\trustle: { type: 'rustle'; layer: string; x: number; z: number; entered?: boolean }\n\t/** What the map looks like beyond its ground, as it is now (`world.setEnvironment`), and the seconds to ease into it over */\n\tenvironment: { type: 'environment'; environment: MapEnvironment; over?: number }\n\t/**\n\t * A definition changed while the game runs (`world.redefine`), a copy made with `copyOf`: a screen with a registry of\n\t * its own puts it in. Told to everyone\n\t */\n\tredefined: { type: 'redefined'; kind: DataKind; definition: string; values: DataValues }\n\t/** An attack started, at `target` when the player sees it */\n\t/** `weapon`: which of its attacks swings, by place (`UnitTypeDef.attacks`); the first when left out */\n\tattack: { type: 'attack'; id: number; target?: number; weapon?: number }\n\t/** Damage dealt to an entity the player sees: by whom when the player sees that too, with what, how much */\n\tdamage: {\n\t\ttype: 'damage'\n\t\tid: number\n\t\tamount: number\n\t\tdamageType: DamageType\n\t\tsource?: number\n\t\tsourceType?: string\n\t\tattack: boolean\n\t\tcrit: boolean\n\t\t/** The ability that dealt it, where the player sees the source (`source`) */\n\t\tability?: string\n\t\ttags?: string[]\n\t}\n\t/** Health given back to an entity the player sees */\n\theal: { type: 'heal'; id: number; amount: number; source?: number }\n\t/**\n\t * A buff put on an entity the player sees (`on`), put on again at another level (`renewed`), or taken off or run\n\t * out. Once as it begins and once as it ends: a renewal at the same level is not told\n\t */\n\tbuff: { type: 'buff'; id: number; buff: string; on: boolean; level?: number; renewed?: boolean; source?: number }\n\t/** A unit came out of `building`, where the player sees that too */\n\ttrained: { type: 'trained'; id: number; building?: number }\n\t/** A structure was put down to be built, to go up over `buildTime` seconds as builders work (`EntityState.construction`) */\n\tconstructionStarted: { type: 'constructionStarted'; id: number; buildTime: number }\n\t/** A structure was finished (or put down whole, `UnitTypeDef.construction: 'instant'`) */\n\tbuilt: { type: 'built'; id: number }\n\t/** A construction was called off by its owner: it dies next, its death's reason `cancelled` */\n\tconstructionCancelled: { type: 'constructionCancelled'; id: number }\n\t/** A building started to turn into another type (`to`) over `time` seconds (`EntityState.upgrade`) */\n\tupgradeStarted: { type: 'upgradeStarted'; id: number; to: string; time: number }\n\t/** That was called off */\n\tupgradeCancelled: { type: 'upgradeCancelled'; id: number; to: string }\n\t/** An entity became another type (`from`: what it was): an upgrade done, a morph */\n\tmorphed: { type: 'morphed'; id: number; from: string }\n\t/** A hero was brought back */\n\trevived: { type: 'revived'; id: number }\n\t/** An entity picked an item up */\n\tpicked: { type: 'picked'; id: number; item: string }\n\t/** Research of the player or an ally finished */\n\tresearched: { type: 'researched'; upgrade: string; level: number; building: number }\n\t/** A shot arrived: at its target when it had one, missing (`miss`), or struck critically */\n\tshot: { type: 'shot'; id: number; x: number; z: number; target?: number; miss: boolean; crit: boolean }\n\t/** A channelled ability started to be kept up (`on`, for `duration` seconds), or ended: done, or `interrupted` */\n\tchannel: { type: 'channel'; id: number; ability: string; on: boolean; duration?: number; interrupted?: boolean }\n\t/** What an ability sent on its way struck an entity */\n\tmissileHit: { type: 'missileHit'; missile: number; target: number }\n\t/** A critical strike landed on the entity */\n\tcrit: { type: 'crit'; id: number; amount: number }\n\t/** An attack up a cliff went wide, at this spot */\n\tmiss: { type: 'miss'; x: number; z: number }\n\t/** A shot that hits an area came down */\n\timpact: { type: 'impact'; x: number; z: number; radius: number }\n\t/** A worker struck what it is mending */\n\twork: { type: 'work'; id: number }\n\t/** A worker struck what it is gathering from */\n\tchop: { type: 'chop'; id: number; target: number }\n\t/** An ability went off. `radius` is there for the ones that hit an area */\n\tlevelUp: { type: 'levelUp'; id: number; level: number }\n\t/** Experience a hero of the player's or an ally's earned, and the level it is at after it */\n\txp: { type: 'xp'; id: number; amount: number; level: number }\n\t/**\n\t * Mana of a unit of the player's or an ally's spent on a cast (`amount` below 0, `ability` the one cast) or given by\n\t * an effect (above 0). Not regeneration\n\t */\n\tmana: { type: 'mana'; id: number; amount: number; ability?: string }\n\t/** A pool of the game's own on a unit of the player's or an ally's changed (`resourceChanged`) */\n\tresource: { type: 'resource'; id: number; kind: string; amount: number; reason?: string }\n\t/** Gold for a kill */\n\tbounty: { type: 'bounty'; x: number; z: number; amount: number }\n\t/** Someone started to cast. `duration` is how long until it goes off */\n\twindup: { type: 'windup'; id: number; ability: string; level: number; x: number; z: number; duration: number }\n\t/** `id`: the caster, where the player sees it (not where only the spot is seen). `charged`: it went off charged, see `charge` on the ability */\n\tcast: { type: 'cast'; id?: number; ability: string; level: number; x: number; z: number; target?: number; radius?: number; charged?: boolean }\n\t/** What an ability set off arrived somewhere: a missile hit, a rush ended, the time was up. `id`: the caster, where the player sees it */\n\tstrike: { type: 'strike'; id?: number; ability: string; level: number; x: number; z: number; target?: number; radius?: number; impact?: string }\n\t/** Something to tell the player. The client finds the words for it, see `Message` */\n\tmessage: { type: 'message'; message: Message; kind: MessageKind; seconds?: number }\n\t/** A command the player sent (`seq`, what `send` gave) was carried out: refused, with why, or not */\n\tcommand: { type: 'command'; seq: number; refusal?: Message }\n\t/** An objective of the player was given (`was` undefined), got further along, or was done or failed */\n\tobjective: { type: 'objective'; objective: ObjectiveState; was?: ObjectiveStatus }\n\t/** Someone says a line to the player: who, what, and for how long (see `world.dialog`) */\n\tline: { type: 'line'; line: SaidLine }\n\t/** The line was skipped: it ends now */\n\tlineEnded: { type: 'lineEnded'; id: number }\n\t/** One of the view's cinematics plays (see `playCinematic`) */\n\tcinematic: { type: 'cinematic'; cinematic: string; hold: boolean; skippable: boolean; params?: Record<string, unknown> }\n\t/** The rules cue the cinematic playing (see `cueCinematic`) */\n\tcinematicCue: { type: 'cinematicCue'; cue: string; params?: Record<string, unknown> }\n\t/**\n\t * One of the view's effects plays, as the rules said (`world.effect`): `id` is the rules' handle on it, `fx` its name,\n\t * at a place (`x`, `y`, `z`) or on an entity (`on`, at a `point`), its knobs, the seed of its random parts\n\t */\n\tfx: {\n\t\ttype: 'fx'\n\t\tid: number\n\t\tfx: string\n\t\tx?: number\n\t\ty?: number\n\t\tz?: number\n\t\ton?: number\n\t\tpoint?: string\n\t\tparams?: Record<string, unknown>\n\t\tseed: number\n\t\toverFog?: boolean\n\t}\n\t/** An effect the rules played stops (`world.stopEffect`) */\n\tfxStop: { type: 'fxStop'; id: number; fade?: number }\n\t/** A player of the side marked a spot of the map, or any player for everyone (`to`, see `ping`) */\n\t/** `by`: the name of who watches, for one of theirs (`to: 'observers'`) */\n\tping: { type: 'ping'; player: PlayerId; x: number; z: number; kind: PingKind; to: ChatAudience; by?: string }\n\t/** A line of chat for the player: of their side, or to everyone (see `chat`) */\n\t/** `by`: the name of who watches, for a line of theirs (`to: 'observers'`) */\n\tchat: { type: 'chat'; player: PlayerId; text: string; to: ChatAudience; by?: string }\n\t/** An event of the game's own that goes to the screen (see `defineEvent`): its id, and what it says */\n\tgame: { type: 'game'; event: string; payload: unknown }\n}\n\n/**\n * Things that happened during a tick and cannot be read from the state afterwards: one of `SessionEvents`\n *\n * @beta\n */\nexport type SessionEvent = SessionEvents[keyof SessionEvents]\n\n/**\n * How the game stands for the player\n *\n * @beta\n */\nexport type Outcome = 'playing' | 'victory' | 'defeat'\n\n/**\n * Everything one player knows about the game at the end of a tick\n *\n * @beta\n */\nexport interface Snapshot {\n\ttick: number\n\t/**\n\t * The switches of the debug tools as they stand, for a player who may use them (`world.debugPlayers`): `explored`,\n\t * the whole map explored (`debug.explore`)\n\t */\n\tdebug?: { noCooldowns: boolean; noManaCosts: boolean; invulnerable: boolean; speed: number; explored?: boolean }\n\t/** Hour of the day, 0..24, in a game with days and nights */\n\thour?: number\n\toutcome: Outcome\n\tentities: EntityState[]\n\tplayers: PlayerState[]\n\tprojectiles: ProjectileState[]\n\tmissiles: MissileState[]\n\t/** Items on the ground, where the player can see the ground */\n\titems: GroundItemState[]\n\t/** Spots someone sees for a while. Everyone can tell, not only whoever it is */\n\treveals: RevealState[]\n\t/** Corpses where the player can see the ground, by the id of who died there (see `raiseDead`). None when left out */\n\tcorpses?: CorpseState[]\n\tevents: SessionEvent[]\n\t/** What the game tells the player about itself, see `GameModule.report` */\n\treport?: Record<string, unknown>\n\t/**\n\t * The score of the players the player is told of (`GameRules.score`: `live`, then `end`), told again at most once\n\t * in `refresh` seconds. None in a game that counts nothing\n\t *\n\t * @beta\n\t */\n\tscore?: ScoreState\n\t/**\n\t * The score's timeline, of the same players: told again at each point of it (`ScoreRules.every`)\n\t *\n\t * @beta\n\t */\n\tscoreLine?: ScoreLineState\n}\n\n/**\n * A corpse as the player sees it: the id the unit had, of what type, where\n *\n * @beta\n */\nexport interface CorpseState {\n\tid: number\n\ttype: string\n\tx: number\n\tz: number\n}\n\n/** @beta */\nexport interface RevealState {\n\tid: number\n\tx: number\n\tz: number\n\tradius: number\n\t/** Seconds it goes on */\n\tleft: number\n\t/** The player's team is the one that sees it */\n\tours: boolean\n}\n\n/** A creep camp. Where they are is part of the map, which everyone knows */\n/**\n * A deposit of the game's money, as the map shows it (`GameSession.mines`)\n *\n * @beta\n */\nexport interface MineInfo {\n\tid: number\n\tx: number\n\tz: number\n}\n\n/** @beta */\nexport interface CampInfo {\n\tid: number\n\tx: number\n\tz: number\n\t/** Levels of its creeps added up */\n\tlevel: number\n\t/** Whether the player has seen that the camp is empty */\n\tcleared: boolean\n}\n\n/**\n * What the player's team sees of the map. The arrays are per cell, row by row\n *\n * @beta\n */\nexport interface FogState {\n\twidth: number\n\tdepth: number\n\t/** Changes whenever the arrays did */\n\tversion: number\n\t/** The whole map is lit, a debug switch */\n\trevealed: boolean\n\tvisible: Uint8Array\n\texplored: Uint8Array\n}\n\ntype WithoutPlayer<T> = T extends unknown ? Omit<T, 'player'> : never\n\n/**\n * A command as the client writes it. Who it comes from is decided by the session, never by the sender\n *\n * @beta\n */\nexport type PlayerCommand = WithoutPlayer<Command> | ModCommand\n\n/**\n * Whether a command is one of the engine's of a kind, narrowed to its shape (`isCommand(sent, 'order')`: its units and\n * its order): what reads a command it did not write, a game's own (`ModCommand`) passed over\n *\n * @beta\n */\nexport function isCommand<K extends Command['type']>(command: PlayerCommand, type: K): command is Extract<WithoutPlayer<Command>, { type: K }> {\n\treturn command.type === type\n}\n\n/**\n * What the debug tools of a client see of the simulation: an entity as the rules have it, and the events and hooks of\n * the last seconds. Plain data, as the snapshots are, so that it works the same with a simulation somewhere else: the\n * client says what it wants to follow, and reads what came back last\n *\n * @beta\n */\nexport interface SessionDebug {\n\t/** Follows an entity, a player or the world, or nothing. Its inspection comes back from then on */\n\tinspect(target: InspectTarget | null): void\n\t/** What is followed, as it stood when last heard of. Null when nothing is followed, or it is gone */\n\treadonly inspection: Inspection | null\n\t/** Changes a number, or a switch (a boolean), of what is followed, where its inspection shows it (`InspectedSection.path` and the key) */\n\tset(path: (string | number)[], value: number | boolean): void\n\t/** Whether the list of everything in the world comes back. Off until asked for: the world can be big */\n\tlisting: boolean\n\t/** Every player and entity of the world, out of sight, hidden and scenery too, as when last heard of. Null while not listing */\n\treadonly world: WorldListing | null\n\t/** Whether the events and hooks are logged. Off until asked for: logging costs a little */\n\tlogging: boolean\n\t/** The events and hooks of the last seconds, oldest first */\n\tlog(): readonly LoggedEvent[]\n\t/** Forgets what was logged so far */\n\tclearLog(): void\n}\n\n/**\n * What a session can do besides being a seat, each where it can (`GameSession.can`): a game played in this page holds\n * its pace and saves, a game in a worker of it says its timing too, a seat a computer plays from serves its brain. Asked\n * for as `session.can.pace?.advance()`: there or not\n *\n * @beta\n */\nexport interface SessionCan {\n\t/** The pace, where it is this player's to set: a game played in this page, in its thread or in a worker of it */\n\treadonly pace?: SessionPace\n\t/** Saves of the world as it stands, and the last checkpoint: a game played in this page */\n\treadonly saves?: SessionSaves\n\t/** The debug tools' view of the simulation, where the session allows it */\n\treadonly inspect?: SessionDebug\n\t/** Where the time of a simulation run elsewhere in this page went of late: a worker (S54) */\n\treadonly timing?: SessionTiming\n\t/** What a computer player's brain reads besides the snapshot: a seat in the simulation's own thread */\n\treadonly computer?: SessionComputer\n}\n\n/**\n * The pace a session holds the game at (`SessionCan.pace`)\n *\n * @beta\n */\nexport interface SessionPace {\n\t/** 1 as it goes, 0 held (a pause menu, a cinematic that has the game wait) */\n\tspeed: number\n\t/** Moves a held game on by `ticks` (one when left out): a step */\n\tadvance(ticks?: number): void\n}\n\n/**\n * Saves of the world a session plays (`SessionCan.saves`)\n *\n * @beta\n */\nexport interface SessionSaves {\n\t/** A save of the world as it stands: at once in this thread, a message there and back in a worker */\n\tsave(): Promise<WorldSave>\n\t/**\n\t * The last moment the rules marked to start again from (`world.checkpoint`), with what it is called, and a save of\n\t * the world as it stood: a scene can load it for \"Retry from wave 6\"\n\t */\n\treadonly checkpoint?: { label: Message; save: WorldSave }\n}\n\n/**\n * Where the time of a simulation run elsewhere went of late (`SessionCan.timing`)\n *\n * @beta\n */\nexport interface SessionTiming {\n\t/**\n\t * Milliseconds a tick took, evened out, the longest, what sending the page what changed took, what the page took to\n\t * take it in, and each system's share (`world.scheduler.timing()`) while they are measured (`profile`)\n\t */\n\ttiming(): { tick: number; tickMax: number; send: number; receive?: number; systems?: SystemTiming[] } | undefined\n\t/** Measures the simulation's systems, or stops (it costs a little): what the stats window asks while it is open */\n\tprofile?(on: boolean): void\n}\n\n/**\n * What a computer player's seat gives its brain besides the snapshot (`SessionCan.computer`)\n *\n * @beta\n */\nexport interface SessionComputer {\n\t/**\n\t * Where the game's money is mined (a resource of `Registry.currency`: gold mines), as a player knows from the map,\n\t * under the fog too: what a computer player looks to for another hall\n\t */\n\tmines(): readonly MineInfo[]\n\t/** The lanes of the map (`lanesOf`), as everyone knows them from the map: what a computer player of lanes walks with its waves */\n\tlanes(): readonly Lane[]\n\t/**\n\t * What happened since the last snapshot, not yet given in one: a copy. The brain's save keeps what it heard since it\n\t * last thought (`restoreEvents`), so that a game loaded from the save hears it too\n\t */\n\tpendingEvents(): SessionEvent[]\n\t/** Takes back what `pendingEvents` gave, ahead of what has happened since: in a game loaded from a save */\n\trestoreEvents(events: readonly SessionEvent[]): void\n}\n\n/**\n * A seat in a game: the only thing a client needs to play\n *\n * @beta\n */\nexport interface GameSession {\n\treadonly playerId: PlayerId\n\treadonly team: number\n\t/** The map and the game data are the same for everyone and known up front */\n\treadonly terrain: Terrain\n\t/**\n\t * What the map looks like beyond its ground, for the screen: its water, sky, weather. Nothing when it does not say.\n\t * As it was when the session began: what the rules change after comes as `environment` events\n\t */\n\treadonly environment?: MapEnvironment\n\t/** The scenery of the map, for the screen: none when it has none (see `MapDoodad`) */\n\treadonly doodads: readonly MapDoodad[]\n\t/** The regions of the map, for the screen: what mist in places lies over by name (see `MapRegion`, `AreaRef`) */\n\treadonly regions: readonly MapRegion[]\n\t/** The views of the map saved under names, for cinematics and a player's first view (see `MapCamera`) */\n\treadonly cameras: readonly MapCamera[]\n\t/** The paths of the map (a road), for the screen: a cinematic's camera on a rail along one (see `MapPath`) */\n\treadonly paths: readonly MapPath[]\n\treadonly registry: Registry\n\treadonly tickRate: number\n\t/**\n\t * What the game says about what it does (`World.log`), where the session has it: a game played in the page. A\n\t * server's game says it on the server, and a player is not given it\n\t */\n\treadonly log?: Logger\n\t/**\n\t * Why the game ended on an error in its rules, once it has (`World.failure`): what the player is told. A game that\n\t * failed does not go on; a client says so, and offers what there is to offer\n\t */\n\treadonly failure?: { message: string } | null\n\t/** How far the current frame is between the last two snapshots, 0..1 */\n\treadonly alpha: number\n\n\t/** State to start from */\n\tsnapshot(): Snapshot\n\t/** Lets time pass. Returns the snapshots that came in since the last call, oldest first */\n\tupdate(dt: number): Snapshot[]\n\t/** Sends a command, to be carried out at the next tick. What it gives is told back with how it went (a `command` event) */\n\tsend(command: PlayerCommand): number\n\tfog(): FogState\n\tcamps(): readonly CampInfo[]\n\n\t/** Whether the player could build this here, as far as they can tell */\n\tcanPlace(unitType: string, point: Vec2): boolean\n\t/**\n\t * Which cells of the ground a building would cover there are in the way, as far as the player can tell, row by row\n\t * from its corner (`placementCells`): what a preview draws cell by cell. None for one built on a resource, or where\n\t * the session does not say @beta\n\t */\n\tplaceCells?(unitType: string, point: Vec2): readonly boolean[] | undefined\n\t/** Route a unit would take, over the ground the player knows */\n\tfindPath(from: Vec2, to: Vec2, flying?: boolean): Vec2[] | null\n\n\t/**\n\t * What this kind of session can do besides being a seat (`SessionCan`): hold the pace, save, show the debug tools,\n\t * tell its timing, serve a computer player. A seat over a wire can none of it; a game in this page most of it\n\t */\n\treadonly can: SessionCan\n\n\t/** Whether the player only watches, and sees everything (every player's resources among it): see `LocalSession.observer` */\n\treadonly observer?: boolean\n\t/** Milliseconds a message takes to the simulation and back, where it runs elsewhere. Nothing in the page */\n\treadonly ping?: number\n\n\tdispose(): void\n}\n\n/**\n * The version of what goes over the wire between a host and its players: the messages here and in `session/remote.ts`,\n * and how deltas are made (`session/delta.ts`). The host says it in its welcome and a player says it when joining a\n * server; a player of another version is refused with a reason, not left to fail somewhere strange. Raised by one on\n * any change of their shape, which a game's own data (`Registry.dataHash`) does not show\n *\n * @beta\n */\nexport const PROTOCOL_VERSION = 13\n\n/**\n * What a player is told when the host's version of the wire is not its own (`PROTOCOL_VERSION`)\n *\n * @internal\n */\nexport function protocolMismatch(host: unknown, player: number = PROTOCOL_VERSION): string {\n\treturn `The host runs another version of the engine (protocol ${typeof host === 'number' ? host : 'unknown'}, this player's is ${player}): update the game`\n}\n\n/**\n * Reads a message that came over a wire: an object with a `type` that is a string, or nothing. What is not JSON, or is\n * JSON of another shape (`null`, a number, a list), is nothing, so that a peer that sends anything at all makes whoever\n * reads it drop the message, not fall over. The other fields are still the sender's word: check each before it is used\n *\n * @internal\n */\nexport function readMessage(text: string): ({ type: string } & Record<string, unknown>) | undefined {\n\tlet message: unknown\n\ttry {\n\t\tmessage = JSON.parse(text)\n\t} catch {\n\t\treturn undefined\n\t}\n\tif (typeof message !== 'object' || message === null || Array.isArray(message)) return undefined\n\tconst { type } = message as { type?: unknown }\n\treturn typeof type === 'string' ? (message as { type: string } & Record<string, unknown>) : undefined\n}\n\n/**\n * A number that is a number: not `NaN`, not infinite, not a string of digits\n *\n * @internal\n */\nexport const isFiniteNumber = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value)\n\n/**\n * A game of a server, as its list says it (`GET /games`): its room (what to connect to, `ws://host:port/<room>`; none for\n * a server of one game), the game and mode, where it is at, its seats taken and free, who watches, and its settings\n * (the map, among them, where the mode offers one)\n *\n * @beta\n */\nexport interface GameListing {\n\troom: string\n\tgame: string\n\tmode: string\n\tphase: 'lobby' | 'game' | 'ended'\n\t/** Seats players hold, seats nobody holds a player could, seats the computer plays */\n\tplayers: number\n\tfree: number\n\tcomputer: number\n\twatchers: number\n\tsettings: Record<string, string>\n\t/** Whether it takes no new games: stopping */\n\tdraining: boolean\n\t/** How its players are rated, on average, where the server keeps ratings (`Ratings`) */\n\trating?: number\n}\n\n/**\n * A kind of game a server lets players make a room of, as its list says it (`GET /games`'s `kinds`): what to ask\n * `POST /games` for (`{ kind: id, settings }`), what it is called, and the settings it offers (a map, among them)\n *\n * @beta\n */\nexport interface GameKindListing {\n\tid: string\n\tname: string\n\t/** Where to wait to be matched with others for it (`ws://host:port/<queue>`), and how many wait now, of how many it takes. None without matchmaking */\n\tqueue?: string\n\twaiting?: number\n\tneeded?: number\n\tsettings: Record<string, { label: string; options: string[]; default: string }>\n}\n","/**\n * What a session can do besides being a seat (`SessionCan`), made of its own members: what a game played in this page\n * gives, in its thread (`LocalSession`) or in a worker (`WorkerSession`)\n */\nimport type { WorldSave } from '#engine/save'\nimport type { Message } from '#engine/messages'\nimport type { SessionPace, SessionSaves } from './protocol'\n\n/** A session's pace, as `SessionCan.pace`: its own `speed` and `advance` */\nexport function paceOf(session: { speed: number; advance(ticks?: number): void }): SessionPace {\n\treturn {\n\t\tget speed() {\n\t\t\treturn session.speed\n\t\t},\n\t\tset speed(speed: number) {\n\t\t\tsession.speed = speed\n\t\t},\n\t\tadvance: (ticks) => session.advance(ticks)\n\t}\n}\n\n/** A session's saves, as `SessionCan.saves`: its own `save` and `checkpoint` */\nexport function savesOf(session: { save(): Promise<WorldSave>; readonly checkpoint?: { label: Message; save: WorldSave } }): SessionSaves {\n\treturn {\n\t\tsave: () => session.save(),\n\t\tget checkpoint() {\n\t\t\treturn session.checkpoint\n\t\t}\n\t}\n}\n","import type { Registry } from '#engine/registry'\nimport type { CampInfo, EntityState, OwnEntityState, SessionEvent, Snapshot } from './protocol'\n\n/*\n * Snapshots as changes. The host keeps what it sent a player at each tick, and sends the next one as what changed since\n * the last one the player has said it got (`base`): entities that came, the fields of those that changed, entities\n * that went, and the other parts when they differ. The player rebuilds the whole snapshot from the one at `base`,\n * keeping the very objects of what did not change: the screen tells what changed by them, and goes no further for\n * the rest. Numbers are rounded first (`quantize`), so that what moves by nothing worth drawing is not a change\n */\n\n/**\n * The fog of a team, as runs of the same value: 0s first, then 1s, then 0s... Few runs for a map of open fields\n *\n * @beta\n */\nexport interface FogMessage {\n\trevealed: boolean\n\tvisible: number[]\n\texplored: number[]\n}\n\n/**\n * What a player knows at a tick: the snapshot (without its events, which go their own way), the fog, the camps, the team\n *\n * @beta\n */\nexport interface Frame {\n\tsnapshot: Snapshot\n\tfog: FogMessage\n\tcamps: CampInfo[]\n\tteam: number\n}\n\n/** The parts of a frame besides its entities, sent when they differ from the base's */\ntype Rest = Omit<Snapshot, 'tick' | 'entities' | 'events'> & { fog: FogMessage; camps: CampInfo[]; team: number }\n\n/**\n * A list or an object sent as the parts of it that changed (`$patch`): by index for a list as long as the one before,\n * by key for an object, each part whole or a patch of its own, and the keys of an object that are gone (`$unset`).\n * What a cooldown of one ability of four, or the gold of one player, sends in place of all of them\n *\n * @beta\n */\nexport interface WirePatch {\n\t/** The parts that changed, by index or key: each the part whole, or a patch of its own */\n\t$patch: Record<string, unknown>\n\t/** The keys of an object that are gone */\n\t$unset?: string[]\n}\n\n/**\n * An entity that changed, as a list rather than an object (what goes over the wire for each one adds up): its id, the\n * fields that are new, those that are gone, and of what only its owner is told (`own`), the same, and its fields that\n * changed in part, as what changed in them (`WirePatch`: one ability's cooldown). Trailing parts that say nothing are\n * left off, the others `0`\n *\n * @beta\n */\nexport type EntityChange = [\n\tid: number,\n\tset: Partial<EntityState>,\n\tunset?: (keyof EntityState)[] | 0,\n\townSet?: Partial<OwnEntityState> | 0,\n\townUnset?: (keyof OwnEntityState)[] | 0,\n\townPatch?: Partial<Record<keyof OwnEntityState, WirePatch>>\n]\n\n/**\n * A frame as what changed since another (`base`, a tick the player has), or all of it (`base: null`)\n *\n * @beta\n */\nexport interface Delta {\n\ttick: number\n\tbase: number | null\n\tadded: EntityState[]\n\tchanged: EntityChange[]\n\tremoved: number[]\n\trest: Partial<Rest>\n\t/** The other parts that changed in part, as what changed in them (`WirePatch`: the gold of one player of four) */\n\trestPatch?: Partial<Record<keyof Rest, WirePatch>>\n\t/**\n\t * The batches of events the player has not said it got, each by its own number (`n`) and the tick it went out with:\n\t * sent again until it does, applied once. Talk between two ticks is a batch of its own (RV14)\n\t */\n\tevents: { tick: number; n: number; events: SessionEvent[] }[]\n}\n\n/** Rounded to `step` */\nconst round = (value: number, step: number) => Math.round(value / step) * step\n\n/**\n * Seconds rounded up to whole ones, a hair over one (what floating point leaves over) not counted: what a plate\n * sweeps changes once a second on the wire, not every round (the plate counts down between)\n */\nconst secondsUp = (value: number) => Math.ceil(value - 1e-6)\n\n/** Positions on the wire, in 256ths of a unit, and the facing in 256ths of a turn: whole numbers, short to write */\nconst POSITION = 256\nconst TURN = 256 / (Math.PI * 2)\n\n/** An entity's numbers as they go over the wire: whole numbers where they can be. `decode` takes them back */\nfunction encode<T extends Partial<EntityState>>(state: T): T {\n\tconst out = { ...state }\n\tif (out.x !== undefined) out.x = Math.round(out.x * POSITION)\n\tif (out.z !== undefined) out.z = Math.round(out.z * POSITION)\n\tif (out.facing !== undefined) out.facing = ((Math.round(out.facing * TURN) % 256) + 256) % 256\n\treturn out\n}\n\nfunction decode<T extends Partial<EntityState>>(state: T): T {\n\tconst out = { ...state }\n\tif (out.x !== undefined) out.x /= POSITION\n\tif (out.z !== undefined) out.z /= POSITION\n\tif (out.facing !== undefined) out.facing /= TURN\n\treturn out\n}\n\n/**\n * An entity's state with its numbers rounded for the wire: positions to 1/256 of a unit (16 bits over a map of 256),\n * the facing to a 256th of a turn, health and shield up to whole points (what is alive keeps at least one), mana down\n * (an ability is never shown ready that the simulation would refuse), what is under way to hundredths, the seconds\n * left of buffs and of shared cooldowns up to whole seconds\n *\n * @beta\n */\nexport function quantize(state: EntityState): EntityState {\n\t// what the wire's whole numbers come back as (`encode`, then `decode`), in one copy: the host diffs what the player\n\t// will have, for every entity in sight of every seat each round\n\tconst out: EntityState = { ...state }\n\tout.x = Math.round(state.x * POSITION) / POSITION\n\tout.z = Math.round(state.z * POSITION) / POSITION\n\tout.facing = (((Math.round(state.facing * TURN) % 256) + 256) % 256) / TURN\n\tout.hp = Math.ceil(state.hp)\n\tif (state.shield !== undefined) out.shield = Math.ceil(state.shield)\n\tif (state.mana !== undefined) out.mana = Math.floor(state.mana)\n\t// what the rules share for the plates (indicators-plan U3): whole seconds, rounded up (what is about to end is not\n\t// shown ended). To a tenth, a buff on each of 1,000 footmen doubled what each seat is sent (395 KB/s to 846)\n\tif (state.buffTimes) out.buffTimes = state.buffTimes.map((left) => (left < 0 ? left : secondsUp(left)))\n\tif (state.abilities?.some((ability) => ability.cooldown))\n\t\tout.abilities = state.abilities.map((ability) => (ability.cooldown ? { ...ability, cooldown: secondsUp(ability.cooldown) } : ability))\n\tif (state.lifetime) out.lifetime = { left: round(state.lifetime.left, 0.1), total: state.lifetime.total }\n\treturn out\n}\n\n/**\n * Whether two values of a field are the same: the very same, or equal as data. Two flat objects (an entity's `stats`, a\n * `lifetime`, a `leap`'s points) are compared field by field; what nests deeper as text\n */\nfunction same(a: unknown, b: unknown): boolean {\n\tif (a === b) return true\n\tif (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false\n\tif (Array.isArray(a) || Array.isArray(b)) {\n\t\tif (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n\t\tfor (let i = 0; i < a.length; i++) if (!same(a[i], b[i])) return false\n\t\treturn true\n\t}\n\tconst left = a as Record<string, unknown>\n\tconst right = b as Record<string, unknown>\n\tfor (const key in left) {\n\t\tif (!(key in right)) return false\n\t\tconst x = left[key]\n\t\tconst y = right[key]\n\t\tif (x === y) continue\n\t\tif (typeof x !== 'object' || typeof y !== 'object' || x === null || y === null) return false\n\t\tif (!same(x, y)) return false\n\t}\n\tfor (const key in right) if (!(key in left)) return false\n\treturn true\n}\n\n/** How deep a patch goes into lists and objects: past it, what changed is sent whole */\nconst PATCH_DEPTH = 4\n\nconst isObject = (value: unknown): value is object => typeof value === 'object' && value !== null\n\n/**\n * What to send of a value that changed (`same` said so) to whoever has `before`: the parts of a list or an object\n * that changed (`WirePatch`), or `after` whole where every part did, or where it is not the same kind of thing\n */\nfunction patchOf(before: unknown, after: unknown, depth = PATCH_DEPTH): unknown {\n\tif (depth === 0 || !isObject(before) || !isObject(after) || Array.isArray(before) !== Array.isArray(after)) return after\n\tconst parts: Record<string, unknown> = {}\n\tlet changed = 0\n\tif (Array.isArray(before)) {\n\t\tconst list = after as unknown[]\n\t\tif (list.length !== before.length) return after\n\t\tfor (let i = 0; i < list.length; i++) {\n\t\t\tif (same(before[i], list[i])) continue\n\t\t\tparts[i] = patchOf(before[i], list[i], depth - 1)\n\t\t\tchanged++\n\t\t}\n\t\treturn changed === list.length ? after : { $patch: parts }\n\t}\n\tconst left = before as Record<string, unknown>\n\tconst right = after as Record<string, unknown>\n\tlet fields = 0\n\tlet unset: string[] | undefined\n\tfor (const key in right) {\n\t\tif (right[key] === undefined) continue\n\t\tfields++\n\t\tif (same(left[key], right[key])) continue\n\t\tparts[key] = patchOf(left[key], right[key], depth - 1)\n\t\tchanged++\n\t}\n\tfor (const key in left) if (left[key] !== undefined && right[key] === undefined) (unset ??= []).push(key)\n\tif (changed === fields && !unset) return after\n\treturn unset ? { $patch: parts, $unset: unset } : { $patch: parts }\n}\n\nconst isPatch = (value: unknown): value is WirePatch => isObject(value) && !Array.isArray(value) && '$patch' in value\n\n/** A value a patch was made against, with the patch put in: new lists and objects where it says, the very parts it does not */\nfunction patched(base: unknown, patch: WirePatch): unknown {\n\tconst made = (Array.isArray(base) ? [...base] : { ...(base as Record<string, unknown>) }) as Record<string, unknown>\n\tfor (const [key, part] of Object.entries(patch.$patch)) made[key] = isPatch(part) ? patched((base as Record<string, unknown>)[key], part) : part\n\tfor (const key of patch.$unset ?? []) delete made[key]\n\treturn made\n}\n\n/** Whether two entities' components say the same: each as it knows how (`Component.same`), or as text */\nfunction sameComponents(registry: Registry | undefined, a: Record<string, unknown> | undefined, b: Record<string, unknown> | undefined): boolean {\n\tif (a === b) return true\n\tif (!a || !b) return false\n\tfor (const id in a) if (!(id in b)) return false\n\tfor (const id in b) {\n\t\tif (!(id in a)) return false\n\t\tconst compare = registry?.component(id)?.same\n\t\tif (compare ? !compare(a[id], b[id]) : !same(a[id], b[id])) return false\n\t}\n\treturn true\n}\n\n/**\n * The fields of an object that changed, and those that are gone, or nothing when none did. A field named in `skip` is\n * left to the caller (an entity's `own` part goes field by field on its own)\n */\nfunction fieldsOf<T extends object>(\n\tregistry: Registry | undefined,\n\tbefore: T,\n\tafter: T,\n\tskip?: keyof T\n): { set: Partial<T>; unset?: (keyof T)[] } | undefined {\n\tlet set: Partial<T> | undefined\n\tlet unset: (keyof T)[] | undefined\n\tfor (const key in after) {\n\t\tif (key === skip || after[key] === undefined) continue\n\t\tconst changed =\n\t\t\t(key as string) === 'components'\n\t\t\t\t? !sameComponents(registry, before[key] as Record<string, unknown> | undefined, after[key] as Record<string, unknown> | undefined)\n\t\t\t\t: !same(before[key], after[key])\n\t\tif (changed) (set ??= {} as Partial<T>)[key] = after[key]\n\t}\n\tfor (const key in before) if (key !== skip && before[key] !== undefined && after[key] === undefined) (unset ??= []).push(key)\n\treturn set || unset ? { set: set ?? {}, ...(unset ? { unset } : {}) } : undefined\n}\n\n/** What changed of an entity, or nothing when nothing did. What only its owner is told goes field by field too */\nfunction changeOf(registry: Registry | undefined, before: EntityState, after: EntityState): EntityChange | undefined {\n\tconst ownBefore = before.own\n\tconst ownAfter = after.own\n\tconst fields = fieldsOf<EntityState>(registry, before, after, 'own')\n\tlet own: { set: Partial<OwnEntityState>; unset?: (keyof OwnEntityState)[] } | undefined\n\tlet ownPatch: Partial<Record<keyof OwnEntityState, WirePatch>> | undefined\n\tlet unsetOwn = false\n\tif (ownBefore && ownAfter) {\n\t\town = fieldsOf(registry, ownBefore, ownAfter)\n\t\t// a list or an object that changed in part (one ability's cooldown of four) goes as what changed in it\n\t\tif (own)\n\t\t\tfor (const key in own.set) {\n\t\t\t\tconst field = key as keyof OwnEntityState\n\t\t\t\tif (!isObject(ownBefore[field])) continue\n\t\t\t\tconst patch = patchOf(ownBefore[field], own.set[field])\n\t\t\t\tif (!isPatch(patch)) continue\n\t\t\t\t;(ownPatch ??= {})[field] = patch\n\t\t\t\tdelete own.set[field]\n\t\t\t}\n\t} else if (ownAfter) own = { set: ownAfter }\n\telse if (ownBefore) unsetOwn = true\n\tif (!fields && !own && !unsetOwn) return undefined\n\tconst unset = [...((fields?.unset ?? []) as (keyof EntityState)[]), ...(unsetOwn ? (['own'] as const) : [])]\n\t// (the set is this call's own object: its numbers are made the wire's in place)\n\tconst set = fields?.set ?? {}\n\tif (set.x !== undefined) set.x = Math.round(set.x * POSITION)\n\tif (set.z !== undefined) set.z = Math.round(set.z * POSITION)\n\tif (set.facing !== undefined) set.facing = ((Math.round(set.facing * TURN) % 256) + 256) % 256\n\tconst change: EntityChange = [after.id, set]\n\tif (unset.length || own) change.push(unset.length ? unset : 0)\n\tif (own) {\n\t\tchange.push(Object.keys(own.set).length || !ownPatch ? own.set : 0)\n\t\tif (own.unset || ownPatch) change.push(own.unset ?? 0)\n\t\tif (ownPatch) change.push(ownPatch)\n\t}\n\treturn change\n}\n\n/**\n * Every part of a frame besides its tick, its entities and its events: the snapshot's parts, the engine's and a pack's\n * (`SnapshotPart`), and the fog, the camps and the team\n */\nconst restOf = (frame: Frame): Rest => {\n\tconst { snapshot, fog, camps, team } = frame\n\tconst { tick: _tick, entities: _entities, events: _events, ...parts } = snapshot\n\treturn { ...parts, fog, camps, team }\n}\n\n/** A frame's entities by id, worked out once: a base is diffed against round after round while the player's answer is on its way */\nconst BY_ID = new WeakMap<Frame, Map<number, EntityState>>()\nfunction entitiesById(frame: Frame): Map<number, EntityState> {\n\tlet byId = BY_ID.get(frame)\n\tif (!byId) {\n\t\tbyId = new Map()\n\t\tfor (const entity of frame.snapshot.entities) byId.set(entity.id, entity)\n\t\tBY_ID.set(frame, byId)\n\t}\n\treturn byId\n}\n\n/** What changed of the entities between two lists, worked out once for the two (the seats of a side share their lists) */\ntype EntitiesDiff = Pick<Delta, 'added' | 'changed' | 'removed'>\nconst entityDiffs = new WeakMap<EntityState[], WeakMap<EntityState[], EntitiesDiff>>()\nconst wholeDiffs = new WeakMap<EntityState[], EntitiesDiff>()\n\nfunction entitiesDiff(then: EntityState[] | undefined, now: EntityState[], base: Frame | undefined, registry: Registry | undefined): EntitiesDiff {\n\tlet byBase = then && entityDiffs.get(then)\n\tconst known = then ? byBase?.get(now) : wholeDiffs.get(now)\n\tif (known) return known\n\tconst made: EntitiesDiff = { added: [], changed: [], removed: [] }\n\tconst before = base ? entitiesById(base) : undefined\n\tconst seen = before && before.size ? new Set<number>() : undefined\n\tfor (const entity of now) {\n\t\tconst old = before?.get(entity.id)\n\t\tif (old) seen!.add(entity.id)\n\t\t// another type under the same id (a building upgraded) is sent whole\n\t\tif (!old || old.type !== entity.type) {\n\t\t\tif (old) made.removed.push(old.id)\n\t\t\tmade.added.push(encode(entity))\n\t\t\tcontinue\n\t\t}\n\t\tconst change = changeOf(registry, old, entity)\n\t\tif (change) made.changed.push(change)\n\t}\n\tif (before) for (const id of before.keys()) if (!seen!.has(id)) made.removed.push(id)\n\tif (then) {\n\t\tif (!byBase) entityDiffs.set(then, (byBase = new WeakMap()))\n\t\tbyBase.set(now, made)\n\t} else wholeDiffs.set(now, made)\n\treturn made\n}\n\n/**\n * A frame as what changed since `base`, or all of it without one. Events are the caller's to add. `registry`: the game's, whose\n * components say how a change of theirs is found (`Component.same`); without it, as text\n *\n * @internal\n */\nexport function diff(base: Frame | undefined, next: Frame, registry?: Registry): Omit<Delta, 'events'> {\n\tconst delta: Omit<Delta, 'events'> = {\n\t\ttick: next.snapshot.tick,\n\t\tbase: base ? base.snapshot.tick : null,\n\t\tadded: [],\n\t\tchanged: [],\n\t\tremoved: [],\n\t\trest: {}\n\t}\n\tconst { added, changed, removed } = entitiesDiff(base?.snapshot.entities, next.snapshot.entities, base, registry)\n\tdelta.added = added\n\tdelta.changed = changed\n\tdelta.removed = removed\n\tconst now = restOf(next)\n\tconst then = base && restOf(base)\n\tconst keys = then ? new Set([...Object.keys(now), ...Object.keys(then)]) : Object.keys(now)\n\tfor (const key of keys) {\n\t\tconst before = then?.[key as keyof Rest]\n\t\tconst after = now[key as keyof Rest]\n\t\tif (then && same(before, after)) continue\n\t\t// a part that changed in part (the gold of one player) goes as what changed in it; the fog whole, as the player\n\t\t// takes it whole (`RemoteSession`)\n\t\tconst patch = then && key !== 'fog' ? patchOf(before, after) : after\n\t\tif (isPatch(patch)) (delta.restPatch ??= {})[key as keyof Rest] = patch\n\t\telse (delta.rest as Record<string, unknown>)[key] = after\n\t}\n\treturn delta\n}\n\n/**\n * The frame a delta makes of the one at its base (none, for a whole one). Entities that did not change are the very\n * objects they were, so that whoever compares them by identity knows they did not. That is the frame before\n * (`latest`) whose object is the same as what is made, which is not always the base: the base is the last frame the\n * host heard was got, a frame or two behind, and the frames in between have objects of their own\n *\n * @internal\n */\nexport function apply(base: Frame | undefined, delta: Delta, latest?: Frame): Frame {\n\tconst removed = new Set(delta.removed)\n\tconst changed = new Map<number, EntityChange>()\n\tfor (const change of delta.changed) changed.set(change[0], change)\n\tconst before = new Map<number, EntityState>()\n\tif (latest && latest !== base) for (const entity of latest.snapshot.entities) before.set(entity.id, entity)\n\t/** The frame before's object for what is made, where it is the same as it; else what is made */\n\tconst kept = (made: EntityState) => {\n\t\tconst was = before.get(made.id)\n\t\treturn was && (was === made || sameEntity(was, made)) ? was : made\n\t}\n\tconst entities: EntityState[] = []\n\tfor (const entity of base?.snapshot.entities ?? []) {\n\t\tif (removed.has(entity.id)) continue\n\t\tconst change = changed.get(entity.id)\n\t\tif (!change) {\n\t\t\tentities.push(kept(entity))\n\t\t\tcontinue\n\t\t}\n\t\tconst [, set, unset, ownSet, ownUnset, ownPatch] = change\n\t\tconst next = { ...entity, ...decode(set) }\n\t\tfor (const field of unset || []) delete next[field]\n\t\tif (ownSet || ownUnset || ownPatch) {\n\t\t\tconst own = { ...entity.own, ...(ownSet || {}) } as OwnEntityState\n\t\t\tfor (const field of ownUnset || []) delete own[field]\n\t\t\tfor (const [field, patch] of Object.entries(ownPatch ?? {}))\n\t\t\t\t(own as unknown as Record<string, unknown>)[field] = patched(entity.own?.[field as keyof OwnEntityState], patch)\n\t\t\tnext.own = own\n\t\t}\n\t\tentities.push(kept(next))\n\t}\n\tfor (const added of delta.added) entities.push(kept(decode(added)))\n\tconst rest = { ...(base ? restOf(base) : {}), ...delta.rest } as Rest\n\tfor (const [key, patch] of Object.entries(delta.restPatch ?? {}))\n\t\t(rest as unknown as Record<string, unknown>)[key] = patched(base && restOf(base)[key as keyof Rest], patch)\n\tconst { fog, camps, team, ...parts } = rest\n\treturn { snapshot: { tick: delta.tick, ...parts, entities, events: [] }, fog, camps, team }\n}\n\n/**\n * Whether two states of an entity say the same, field by field\n *\n * @internal\n */\nexport function sameEntity(a: EntityState, b: EntityState): boolean {\n\tif (a.type !== b.type) return false\n\treturn fieldsOf(undefined, a, b) === undefined\n}\n\n/**\n * Characters of a delta's text by what they carry, added to `into`: each field of an entity, of those added and those\n * changed together (`entity.hp`; of what only its owner is told, `entity.own.abilities`), the other parts (`rest.fog`),\n * `events`, `removed`, and what is left (ids, brackets, the tick) as `other`, so that they add up to `text`'s length.\n * A field is its key, its value and the comma between, as `JSON.stringify` writes them\n */\nexport function bytesByKey(delta: Delta, text: string, into: Record<string, number>): void {\n\tlet counted = 0\n\tconst add = (key: string, characters: number) => {\n\t\tinto[key] = (into[key] ?? 0) + characters\n\t\tcounted += characters\n\t}\n\tconst fields = (prefix: string, values: object) => {\n\t\tfor (const [key, value] of Object.entries(values)) {\n\t\t\tif (value === undefined) continue\n\t\t\tif (key === 'own' && prefix === 'entity.' && value && typeof value === 'object') {\n\t\t\t\tadd('entity.own', key.length + 5)\n\t\t\t\tfields('entity.own.', value)\n\t\t\t} else add(prefix + key, key.length + 4 + JSON.stringify(value).length)\n\t\t}\n\t}\n\tfor (const entity of delta.added) fields('entity.', entity)\n\tfor (const [, set, unset, ownSet, ownUnset, ownPatch] of delta.changed) {\n\t\tfields('entity.', set)\n\t\tif (unset) add('entity.unset', JSON.stringify(unset).length + 1)\n\t\tif (ownSet) fields('entity.own.', ownSet)\n\t\tif (ownUnset) add('entity.own.unset', JSON.stringify(ownUnset).length + 1)\n\t\t// a field sent as what changed in it counts as the field\n\t\tif (ownPatch) fields('entity.own.', ownPatch)\n\t}\n\tfor (const part of [delta.rest, delta.restPatch ?? {}])\n\t\tfor (const [key, value] of Object.entries(part)) if (value !== undefined) add(`rest.${key}`, key.length + 4 + JSON.stringify(value).length)\n\tif (delta.events.length) add('events', JSON.stringify(delta.events).length)\n\tif (delta.removed.length) add('removed', JSON.stringify(delta.removed).length)\n\tadd('other', text.length - counted)\n}\n","import { EventLog, inspect, type Inspection, type InspectTarget, listWorld, type LoggedEvent, setInspected, type WorldListing } from '#engine/inspect'\nimport type { World } from '#engine/world'\nimport { isFiniteNumber, type SessionDebug } from './protocol'\nimport type { DebugAsk } from './wire'\n\n/** Milliseconds between two words of the debug tools' view of a world elsewhere: a server's, a worker's */\nexport const DEBUG_EVERY = 100\n\n/** Ticks between two lists of everything in the world: thousands of trees need not be listed every tick */\nconst LIST_EVERY = 10\n\n/**\n * The debug tools' view of a world running in the same page. What it hands out is worked out again whenever a\n * snapshot is, and at once when the client asks for something else: a remote one would wait for the answer instead\n */\nexport class LocalDebug implements SessionDebug {\n\tinspection: Inspection | null = null\n\tworld: WorldListing | null = null\n\tprivate target: InspectTarget | null = null\n\tprivate listedAt = -Infinity\n\tprivate readonly events = new EventLog()\n\n\tconstructor(private readonly simulation: World) {}\n\n\tinspect(target: InspectTarget | null): void {\n\t\tthis.target = target\n\t\tthis.refresh()\n\t}\n\n\tset(path: (string | number)[], value: number | boolean): void {\n\t\tif (!this.target) return\n\t\tsetInspected(this.simulation, this.target, path, value)\n\t\tthis.refresh()\n\t}\n\n\tget listing(): boolean {\n\t\treturn this.world !== null\n\t}\n\n\tset listing(on: boolean) {\n\t\tthis.listedAt = -Infinity\n\t\tthis.world = on ? listWorld(this.simulation) : null\n\t}\n\n\tget logging(): boolean {\n\t\treturn this.events.attached\n\t}\n\n\tset logging(on: boolean) {\n\t\tif (on === this.logging) return\n\t\tif (on) this.events.attach(this.simulation)\n\t\telse this.events.detach()\n\t}\n\n\tlog(): readonly LoggedEvent[] {\n\t\treturn this.events.entries\n\t}\n\n\tclearLog(): void {\n\t\tthis.events.clear()\n\t}\n\n\t/** Works what is handed out again. The session does when a tick went by */\n\trefresh(): void {\n\t\tconst world = this.simulation\n\t\tthis.inspection = this.target && inspect(world, this.target)\n\t\tif (this.world && world.tick - this.listedAt >= LIST_EVERY) {\n\t\t\tthis.world = listWorld(world)\n\t\t\tthis.listedAt = world.tick\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tthis.events.detach()\n\t}\n}\n\n/** What is followed, as the wire says it: an entity, a player or the world, or nothing; anything else is not */\nfunction targetOf(value: unknown): InspectTarget | null | undefined {\n\tif (value === null) return null\n\tif (typeof value !== 'object') return undefined\n\tconst target = value as Record<string, unknown>\n\tif (isFiniteNumber(target.entity)) return { entity: target.entity }\n\tif (isFiniteNumber(target.player)) return { player: target.player }\n\tif (target.world === true) return { world: true }\n\treturn undefined\n}\n\n/**\n * Does what the debug tools of a screen asked of a world here (`DebugAsk`), each field checked first: it comes from\n * anyone who can send anything\n */\nexport function askDebug(view: SessionDebug, ask: Record<string, unknown>): void {\n\tconst target = targetOf(ask.inspect)\n\tif (target !== undefined) view.inspect(target)\n\tconst set = ask.set as { path?: unknown; value?: unknown } | undefined\n\tif (\n\t\tset &&\n\t\tArray.isArray(set.path) &&\n\t\tset.path.every((key) => typeof key === 'string' || isFiniteNumber(key)) &&\n\t\t(isFiniteNumber(set.value) || typeof set.value === 'boolean')\n\t)\n\t\tview.set(set.path as (string | number)[], set.value)\n\tif (typeof ask.listing === 'boolean') view.listing = ask.listing\n\tif (typeof ask.logging === 'boolean') view.logging = ask.logging\n\tif (ask.clearLog === true) view.clearLog()\n}\n\n/**\n * The debug tools' view of a world elsewhere, a server's or a worker's: what it asked to follow, said over the wire\n * (`DebugAsk`), and what came back last (`take`)\n */\nexport class RemoteDebug implements SessionDebug {\n\tinspection: Inspection | null = null\n\tworld: WorldListing | null = null\n\tprivate listed = false\n\tprivate logged = false\n\tprivate target: InspectTarget | null = null\n\tprivate events: readonly LoggedEvent[] = []\n\n\tconstructor(private readonly ask: (ask: DebugAsk) => void) {}\n\n\tinspect(target: InspectTarget | null): void {\n\t\tthis.target = target\n\t\tif (!target) this.inspection = null\n\t\tthis.ask({ inspect: target })\n\t}\n\n\t/** Asks again for all it follows: of a world it is served from anew (a session resumed, a replay gone back) */\n\taskAgain(): void {\n\t\tif (this.target || this.listed || this.logged) this.ask({ inspect: this.target, listing: this.listed, logging: this.logged })\n\t}\n\n\tset(path: (string | number)[], value: number | boolean): void {\n\t\tthis.ask({ set: { path, value } })\n\t}\n\n\tget listing(): boolean {\n\t\treturn this.listed\n\t}\n\n\tset listing(on: boolean) {\n\t\tthis.listed = on\n\t\tif (!on) this.world = null\n\t\tthis.ask({ listing: on })\n\t}\n\n\tget logging(): boolean {\n\t\treturn this.logged\n\t}\n\n\tset logging(on: boolean) {\n\t\tthis.logged = on\n\t\tthis.ask({ logging: on })\n\t}\n\n\tlog(): readonly LoggedEvent[] {\n\t\treturn this.events\n\t}\n\n\tclearLog(): void {\n\t\tthis.events = []\n\t\tthis.ask({ clearLog: true })\n\t}\n\n\t/** What the world's side said of what is followed */\n\ttake(said: { inspection: Inspection | null; world: WorldListing | null; log: readonly LoggedEvent[] }): void {\n\t\tthis.inspection = said.inspection\n\t\tthis.world = this.listed ? said.world : null\n\t\tif (this.logged) this.events = said.log\n\t}\n}\n","/**\n * What a player is told of an entity (design review E7): what everyone in sight of it is, worked out once a tick for\n * every seat of a host (`commonEntityState`), and on it what is one player's own (`playerEntityState`). A seat\n * (`LocalSession`) puts them in its snapshots; nothing here keeps anything between ticks\n */\nimport { orderSays } from '#engine/orders/facts'\nimport { dashing } from '#engine/dashing'\nimport { illusion } from '#engine/summons'\nimport type { SnapshotView } from '#engine/components'\nimport type { Entity } from '#engine/entity'\nimport type { Vec2 } from '#engine/math'\nimport { declaredRefusal, notReady } from '#engine/orders/cast'\nimport { shieldOf } from '#engine/abilities/buffs'\nimport { baseStats } from '#engine/defs'\nimport { changedStats } from '#engine/stats'\nimport type { World } from '#engine/world'\nimport type { HudShareRule } from '#engine/rules'\nimport type { SessionView } from '#engine/replication'\nimport { deposit, fighting, moving } from '#engine/entity'\nimport type { AbilityInfo, EntityState, OwnEntityState, SharedAbility } from './protocol'\n\n/** A rule of `GameRules.hud` for one unit: its value, or what its function decides */\nconst ruleOf = <T>(world: World, entity: Entity, rule: HudShareRule<T>): T =>\n\ttypeof rule === 'function' ? (rule as (world: World, entity: Entity) => T)(world, entity) : rule\n\n/** The seconds left of a unit's buffs, in their order: -1 for one with no end, or kept up by an aura or a passive */\nfunction buffTimesOf(entity: Entity): number[] {\n\tconst times = new Array<number>(entity.buffs.length)\n\tfor (let i = 0; i < entity.buffs.length; i++) {\n\t\tconst buff = entity.buffs[i]\n\t\t// an aura's, a passive's: there while its source keeps it up, not for a time\n\t\ttimes[i] = Number.isFinite(buff.remaining) && !buff.kept ? Math.max(buff.remaining, 0) : -1\n\t}\n\treturn times\n}\n\n/**\n * What everyone in sight of an entity is told of it this tick, the same for every seat (`EntityState`): where it is,\n * its health and mana, its stats where they changed, its buffs, what the rules share for the plates over it. `name`\n * is what the map calls it, where it has a name\n *\n * @internal\n */\nexport function commonEntityState(world: World, entity: Entity, name: string | undefined): EntityState {\n\tconst state: EntityState = {\n\t\tid: entity.id,\n\t\ttype: entity.def.id,\n\t\towner: entity.owner,\n\t\tx: entity.pos.x,\n\t\tz: entity.pos.z,\n\t\tfacing: entity.facing,\n\t\thp: entity.hp,\n\t\tstats: changedStats(world, entity),\n\t\tvisible: true\n\t}\n\tconst base = baseStats(entity.def, world.registry)\n\tif (entity.maxHp !== base.health) state.maxHp = entity.maxHp\n\tif (entity.buffs.length) state.shield = shieldOf(entity) || undefined\n\tconst dash = entity.get(dashing)\n\tif (dash?.height) state.leap = { from: dash.from, to: { x: dash.x, z: dash.z }, height: dash.height }\n\tif (entity.maxMana > 0) {\n\t\tstate.mana = entity.mana\n\t\tif (entity.maxMana !== base.mana) state.maxMana = entity.maxMana\n\t}\n\tif (entity.buffs.length) state.buffs = entity.buffs.map((buff) => buff.id)\n\tfor (const buff of entity.buffs) if (buff.stacks) (state.stacks ??= {})[buff.id] = buff.stacks\n\t// what the game's rules share besides, for the plates over it (indicators-plan U3)\n\tconst { hud } = world.rules\n\tif (hud.shareBuffTimes !== undefined && entity.buffs.length && ruleOf(world, entity, hud.shareBuffTimes) === true)\n\t\tstate.buffTimes = buffTimesOf(entity)\n\tif (hud.shareAbilities !== undefined && entity.abilities.length) {\n\t\tconst share = ruleOf(world, entity, hud.shareAbilities)\n\t\tif (share === 'icons' || share === 'cooldowns') {\n\t\t\tconst abilities: SharedAbility[] = []\n\t\t\tfor (const { id, level, cooldown } of entity.abilities) {\n\t\t\t\tif (level >= 1) abilities.push(share === 'cooldowns' ? { id, level, cooldown } : { id, level })\n\t\t\t}\n\t\t\tif (abilities.length) state.abilities = abilities\n\t\t}\n\t}\n\tif (entity.get(deposit)) state.resource = entity.get(deposit)!.amount\n\tif (entity.on !== undefined) state.on = entity.on\n\tif (entity.asleep) state.asleep = true\n\tif (entity.scale !== 1) state.scale = entity.scale\n\tif (entity.look) state.look = entity.look\n\tif (world.sight.isInvisible(entity)) state.unseen = true\n\tif (name !== undefined) state.name = name\n\t// how long an illusion lasts would give it away: its side alone is told (`describe`)\n\tif (entity.expires !== null && !entity.has(illusion)) state.lifetime = { left: entity.expires, total: entity.lifetime }\n\treturn state\n}\n\n/**\n * Whether an entity has a component replicated to its owner, or shaping itself for each player (`Component.snapshot`)\n *\n * @internal\n */\nexport function hasOnePlayersPart(world: World, entity: Entity): boolean {\n\tfor (const held of entity.heldComponents()) {\n\t\tconst component = world.registry.component(held.id)\n\t\tif (component?.replicate === 'owner' || (component?.replicate && component.snapshot)) return true\n\t}\n\treturn false\n}\n\n/**\n * What one player is told of an entity, on what everyone is (`shared`, `commonEntityState`): an illusion's lifetime on\n * its own side, the components replicated to the player and what they make of themselves for them, and its own part\n * (`own`: its orders, where it goes, its abilities) for one of the player's side. `shared` itself where there is\n * nothing more\n *\n * @internal\n */\nexport function playerEntityState(view: SessionView, entity: Entity, shared: EntityState): EntityState {\n\tconst { world, player, observer } = view\n\tlet state = shared\n\t/** This player's copy of the shared state, made once something of this player's is added */\n\tconst mine = () => (state === shared ? (state = { ...shared }) : state)\n\tif (entity.expires !== null && entity.has(illusion) && view.isAlly(entity.owner)) mine().lifetime = { left: entity.expires, total: entity.lifetime }\n\tlet seen: SnapshotView | undefined\n\tfor (const held of entity.heldComponents()) {\n\t\tconst { id } = held\n\t\tconst component = world.registry.component(id)\n\t\tconst audience = component?.replicate\n\t\tif (!audience) continue\n\t\tconst ally = view.isAlly(entity.owner)\n\t\tif (!(audience === 'everyone' || (audience === 'allies' ? ally : entity.owner === player))) continue\n\t\t// what the component makes of it for this player, or a copy: what is sent must not change with the world, nor change it\n\t\tconst value = entity.get(held)\n\t\tconst sent = component!.snapshot\n\t\t\t? component!.snapshot(\n\t\t\t\t\tvalue,\n\t\t\t\t\tentity,\n\t\t\t\t\t(seen ??= {\n\t\t\t\t\t\tworld,\n\t\t\t\t\t\tplayer: observer ? undefined : player,\n\t\t\t\t\t\town: entity.owner === player,\n\t\t\t\t\t\tally,\n\t\t\t\t\t\tobserver: observer,\n\t\t\t\t\t\tknows: view.knows,\n\t\t\t\t\t\tisAlly: view.isAlly,\n\t\t\t\t\t\tsees: view.sees\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t: structuredClone(value)\n\t\tif (sent !== undefined) (mine().components ??= {})[id] = sent\n\t}\n\tif (!view.isAlly(entity.owner)) return state\n\tconst shareBuffTimes = world.rules.hud.shareBuffTimes\n\tif (shareBuffTimes !== undefined && entity.buffs.length && !shared.buffTimes && ruleOf(world, entity, shareBuffTimes) === 'allies')\n\t\tmine().buffTimes = buffTimesOf(entity)\n\n\tconst m = entity.get(moving)\n\t// the places of the orders queued after the first: none made for a unit with nothing queued, most of them (RV87)\n\tlet waypoints: Vec2[] | undefined\n\tfor (let i = 1; i < entity.orders.length; i++) {\n\t\tconst order = entity.orders[i]\n\t\tconst target = world.get(order.init.target)\n\t\tconst point = target && view.knows(target) ? target.pos : order.init.point\n\t\tif (point) (waypoints ??= []).push({ x: point.x, z: point.z })\n\t}\n\tconst own: OwnEntityState = (mine().own = {\n\t\t// another's that this player may command: its owner shares control with them\n\t\t...(entity.owner !== player && !observer && world.mayCommand(player, entity) && { shared: true }),\n\t\thidden: entity.hidden,\n\t\torder: entity.orders[0]?.type ?? null,\n\t\t// on its way to build it: once the site is down, what it builds is there to be counted itself\n\t\tbuild: entity.orders[0]?.type === 'build' && !orderSays(world, entity, 'building') ? entity.orders[0].init.unitType : undefined,\n\t\torders: entity.orders.length,\n\t\tpassive: entity.get(fighting)?.passive ?? false,\n\t\tfighting: !!entity.get(fighting)?.autoTarget,\n\t\tgoal: m?.status === 'moving' ? { x: m.navGoal.x, z: m.navGoal.z } : undefined,\n\t\t...(waypoints && { waypoints })\n\t})\n\tif (entity.abilities.length) {\n\t\tconst hooked = world.hooks.has('canCast')\n\t\town.abilities = entity.abilities.map(({ id, level, cooldown, charges, refill, autocast }) => {\n\t\t\tconst info: AbilityInfo = { id, level, cooldown, autocast }\n\t\t\tif (charges !== undefined) Object.assign(info, { charges, refill })\n\t\t\tif (!hooked || level < 1) return info\n\t\t\t// what the game's hook decides, where the screen could not work it out from what is declared\n\t\t\tconst ability = world.registry.ability(id)\n\t\t\tconst declared = declaredRefusal(world, entity, ability)\n\t\t\tconst decided = notReady(world, entity, ability)\n\t\t\tif (declared?.key !== decided?.key) info.decided = decided ?? null\n\t\t\treturn info\n\t\t})\n\t}\n\treturn state\n}\n","import { checkpoint as checkpointEvent } from '#engine/engineEvents'\nimport { minesFor } from '#engine/systems/economy'\nimport { paceOf, savesOf } from './can'\nimport { sameEntity } from './delta'\nimport type { Logger } from '#engine/log'\nimport type { MapCamera, MapDoodad, MapEnvironment, MapPath, MapRegion } from '#engine/map'\nimport { names } from '#engine/names'\nimport { campsFor } from '#engine/camps'\nimport { type Lane, lanesOf } from '#engine/lanes'\nimport { assertPlainData } from '#engine/debug'\nimport type { Entity, EntityId, PlayerId } from '#engine/entity'\nimport { heroSummaries } from '#engine/hero'\nimport type { Vec2 } from '#engine/math'\nimport { canPlaceStructure, placementCells } from '#engine/orders/build'\nimport type { Registry } from '#engine/registry'\nimport { decidedAvailability, decidedUnlocks, techOf } from '#engine/tech'\nimport type { Terrain } from '#engine/terrain'\nimport type { World } from '#engine/world'\nimport type {\n\tCampInfo,\n\tEntityState,\n\tFogState,\n\tGameSession,\n\tMineInfo,\n\tPlayerCommand,\n\tPlayerState,\n\tSessionEvent,\n\tSnapshot,\n\tSessionCan,\n\tSessionDebug\n} from './protocol'\nimport type { Message } from '#engine/messages'\nimport { saveWorld, type WorldSave } from '#engine/save'\nimport type { TeamMemory } from './memory'\nimport { LocalDebug } from './debug'\nimport { deposit } from '../entity'\nimport { SessionView, type SnapshotPart } from '#engine/replication'\nimport { commonEntityState, hasOnePlayersPart, playerEntityState } from './entityState'\nimport { shownEffects } from '#engine/effects'\n\n/**\n * A seat at a world running in the same page. It does the job a server will do later:\n * run the simulation, and hand the player only what their team is allowed to know.\n */\n/** The effects of the rules a player was shown that are kept, for a stop to be told to them: the latest so many */\nconst MOST_EFFECTS = 1024\n\n/**\n * The events a computer player's seat hears (`forComputer`): the facts a brain reads and a save keeps for it (deaths,\n * damage, healing, pings, chat, the game's own events) and the answers to its commands. The rest is for a screen (an\n * attack's swing, a shot, a buff, a hammer blow, a line said), and a computer's seat is spared hearing it\n *\n * @beta\n */\nexport const COMPUTER_EVENTS: ReadonlySet<SessionEvent['type']> = new Set(['death', 'damage', 'heal', 'ping', 'chat', 'game', 'command'])\n\n/**\n * What is told of each entity this round, for every session of a world, while a host sends to its seats\n * (`shareCaptures`), none otherwise: what everyone is told (`common`, by entity), and what the seats of one side are\n * (`sides`: by the side's key, `LocalSession.sideKey`, then by entity) where nothing of it is one player's\n */\ninterface Round {\n\treadonly common: Map<EntityId, EntityState>\n\treadonly sides: Map<string, Side>\n}\n\n/**\n * What the seats of a side are told this round, by entity: what nothing of is one player's (`all`), and of what is, the\n * first seat's (`alike`), which a seat told the very same takes as it is, so that the side's frames share their objects\n */\ninterface Side {\n\treadonly all: Map<EntityId, EntityState>\n\treadonly alike: Map<EntityId, EntityState>\n\t/** What its first seat saw (`LocalSession.capture`): the others of the side see the same, but what may be theirs alone */\n\tseen?: SideSeen\n}\n\n/**\n * What the first seat of a side saw this round: its entities, those of them in sight, and where in the list are those\n * whose description may be one player's (`LocalSession.isOnePlayers`), to be described again for each seat\n */\ninterface SideSeen {\n\treadonly entities: readonly EntityState[]\n\treadonly inSight: ReadonlySet<EntityId>\n\treadonly mine: readonly number[]\n}\nconst SHARED = new WeakMap<World, Round>()\n\n/**\n * From here until `endSharedCaptures`, the sessions of the world describe each entity once between them (what\n * everyone is told; what is one player's goes on a copy): for a host's round of sending, where every seat is captured\n * from the same world. Not while the world changes: what was described is said again\n *\n * @internal\n */\nexport function shareCaptures(world: World): void {\n\tSHARED.set(world, { common: new Map(), sides: new Map() })\n}\n\n/** @internal */\nexport function endSharedCaptures(world: World): void {\n\tSHARED.delete(world)\n}\n\n/** @beta */\nexport class LocalSession implements GameSession {\n\treadonly terrain: Terrain\n\treadonly environment?: MapEnvironment\n\treadonly doodads: readonly MapDoodad[]\n\treadonly regions: readonly MapRegion[]\n\treadonly cameras: readonly MapCamera[]\n\treadonly paths: readonly MapPath[]\n\treadonly registry: Registry\n\treadonly tickRate: number\n\talpha = 1\n\t/** What the world says (`World.log`): a session in the page has it, and the client shows it with its own */\n\tget log(): Logger {\n\t\treturn this.world.log\n\t}\n\t/** Why the game ended on an error, once it has (`World.failure`) */\n\tget failure(): { message: string } | null {\n\t\treturn this.world.failure\n\t}\n\t/** Simulation speed multiplier, 0 pauses. A debug control, a real server sets the pace itself */\n\tspeed = 1\n\n\tprivate accumulator = 0\n\t/** Whether the team saw the whole map at the last snapshot (the debug switch): what it saw then only is forgotten after */\n\tprivate wasRevealed = false\n\t/** What the player's team remembers, or an observer's own (`SessionView.memory`) */\n\tprivate get memory(): TeamMemory {\n\t\treturn this.view.memory\n\t}\n\t/** Ids of what made it into the snapshot being put together as in sight. Kept to be cleared, not made anew */\n\tprivate readonly inSight = new Set<EntityId>()\n\t/** The names the map or the rules gave entities, by id, as of the snapshot being put together (`world.named`) */\n\tprivate readonly namesNow = new Map<EntityId, string>()\n\tprivate readonly disposers: (() => void)[] = []\n\tprivate pendingCheckpoint?: Message\n\tcheckpoint?: { label: Message; save: WorldSave }\n\treadonly debug: LocalDebug\n\t/** Its pace, saves of its world, the debug tools' view, and what a computer player's brain reads (`SessionCan`) */\n\treadonly can: SessionCan = {\n\t\tpace: paceOf(this),\n\t\tsaves: savesOf(this),\n\t\tinspect: undefined,\n\t\tcomputer: {\n\t\t\tmines: () => this.mines(),\n\t\t\tlanes: () => this.lanes(),\n\t\t\tpendingEvents: () => this.pendingEvents(),\n\t\t\trestoreEvents: (events) => this.restoreEvents(events)\n\t\t}\n\t}\n\t/**\n\t * Who only watches, and sees everything: every entity, the whole map, every player's resources and heroes. From\n\t * `playerId`'s side all the same (who is an ally, an enemy). For a server's watchers, whose commands go nowhere\n\t */\n\treadonly observer: boolean\n\t/**\n\t * Whose seat is a computer player's (`forComputer`): its snapshots leave out projectiles, missiles, corpses, reveals\n\t * and the events a brain never reads, and it listens for none of those, so twelve computers cost the world less\n\t */\n\treadonly forComputer: boolean\n\t/** The seat's side of the world: whose it is, what they may know, what was told to them since the last snapshot */\n\treadonly view: SessionView\n\n\tconstructor(\n\t\t/** For tools and tests. Clients have no business here, they go through the session */\n\t\treadonly world: World,\n\t\treadonly playerId: PlayerId,\n\t\t/**\n\t\t * `debug`: the player may use the debug commands (see `world.debugPlayers`). `ownsWorld`: the world is the\n\t\t * session's, and goes with it (`dispose`): for a game played in the page, where the session is all the screen\n\t\t * holds of it. Not for a world others play too, or one that goes on after this session (a host's seats, the computer's).\n\t\t * `forComputer`: the seat is a computer player's, and its snapshots carry what a brain reads and none of what a\n\t\t * screen needs (`COMPUTER_EVENTS`): cheaper to take, and fewer of the world's events to hear.\n\t\t * `mostEffects` (`@beta`): how many of the effects the rules play are kept for their stop, 1024 when left out\n\t\t */\n\t\toptions: { observer?: boolean; debug?: boolean; ownsWorld?: boolean; forComputer?: boolean; mostEffects?: number } = {}\n\t) {\n\t\tthis.observer = options.observer ?? false\n\t\tthis.ownsWorld = options.ownsWorld ?? false\n\t\tthis.forComputer = options.forComputer ?? false\n\t\tthis.view = new SessionView(world, playerId, {\n\t\t\tobserver: this.observer,\n\t\t\tforComputer: this.forComputer,\n\t\t\tmostEffects: options.mostEffects ?? MOST_EFFECTS\n\t\t})\n\t\tif (options.debug) world.debugPlayers.add(playerId)\n\t\tthis.terrain = world.terrain\n\t\tthis.environment = world.map.environment\n\t\tthis.doodads = world.map.doodads\n\t\tthis.regions = world.map.regions\n\t\tthis.cameras = world.map.cameras\n\t\tthis.paths = world.map.paths\n\t\tthis.registry = world.registry\n\t\tthis.tickRate = world.tickRate\n\t\tthis.debug = new LocalDebug(world)\n\t\t;(this.can as { inspect?: SessionDebug }).inspect = this.debug\n\n\t\tconst { events } = world\n\t\tconst { view } = this\n\t\t// what the seat hears of the world, each told as what emits it says (`replicateEvent`): a computer's seat only what\n\t\t// a brain reads (`COMPUTER_EVENTS`), so that it is told of nothing it throws away, and the world's events have fewer\n\t\t// listeners for each computer seated\n\t\tfor (const replication of world.registry.replications) {\n\t\t\tif (!this.hears(replication.as)) continue\n\t\t\tthis.disposers.push(\n\t\t\t\tevents.on(replication.event as never, (payload: unknown) => {\n\t\t\t\t\tconst said = replication.tell(payload, view)\n\t\t\t\t\tif (said) view.events.push(said)\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t\t// saved once the tick is over, with everything in it settled\n\t\tthis.disposers.push(events.on(checkpointEvent, ({ label }) => (this.pendingCheckpoint = label)))\n\t\t// the game's own, to whom it says: those of this world's game (`GameModule.events`), whichever they turn out to be\n\t\tif (this.hears('game'))\n\t\t\tthis.disposers.push(\n\t\t\t\tevents.watch((type, payload) => {\n\t\t\t\t\tif (typeof type !== 'string') return\n\t\t\t\t\tconst audience = world.registry.event(type)?.replicate\n\t\t\t\t\tif (!audience) return\n\t\t\t\t\tif (audience !== 'everyone' && !audience(payload, view)) return\n\t\t\t\t\tif (this.world.checks.events) assertPlainData(payload, `Event \"${type}\"`)\n\t\t\t\t\tview.events.push({ type: 'game', event: type, payload })\n\t\t\t\t})\n\t\t\t)\n\t}\n\n\t/** Whether the seat is told of events of a kind: a player's seat of all of them, a computer's of what a brain reads */\n\tprivate hears(kind: SessionEvent['type']): boolean {\n\t\treturn !this.forComputer || COMPUTER_EVENTS.has(kind)\n\t}\n\n\t/** The player's team: theirs now, as the rules may move them to another (`setTeam`) */\n\tget team(): number {\n\t\treturn this.view.team\n\t}\n\n\tprivate isAlly(owner: PlayerId): boolean {\n\t\treturn this.view.isAlly(owner)\n\t}\n\n\t/** Whether the player's team sees a spot of the map right now: an observer sees all of it */\n\tprivate sees(x: number, z: number): boolean {\n\t\treturn this.view.sees(x, z)\n\t}\n\n\t/**\n\t * How many effects of the rules are kept for their stop to be told (`mostEffects`), for a test of the bound\n\t *\n\t * @internal\n\t */\n\tget keptEffects(): number {\n\t\treturn shownEffects(this.view).size\n\t}\n\n\t/** Whether the player's team can see the entity right now */\n\tprivate knows(entity: Entity): boolean {\n\t\treturn this.view.knows(entity)\n\t}\n\n\t/**\n\t * What everyone in sight of an entity is told of it this tick, the same for every seat: worked out once for all\n\t * the sessions of a world while a host's round of sending is on (`shareCaptures`), else for this session alone\n\t */\n\tprivate common(entity: Entity): EntityState {\n\t\tconst shared = SHARED.get(this.world)?.common\n\t\tconst known = shared?.get(entity.id)\n\t\tif (known) return known\n\t\tconst state = commonEntityState(this.world, entity, this.namesNow.get(entity.id))\n\t\tshared?.set(entity.id, state)\n\t\treturn state\n\t}\n\n\t/**\n\t * What this player is told of an entity: what everyone is (`common`, shared between the seats of a host), and on a\n\t * copy of it what is this player's to know: an illusion's lifetime on its own side, the components replicated to it\n\t * and what they make of themselves for it, and its own part (`own`) for an ally's\n\t */\n\tprivate describe(entity: Entity): EntityState {\n\t\tconst side = this.sideNow\n\t\tif (!side) return playerEntityState(this.view, entity, this.common(entity))\n\t\tif (this.isOnePlayers(entity)) {\n\t\t\tconst state = playerEntityState(this.view, entity, this.common(entity))\n\t\t\tconst first = side.alike.get(entity.id)\n\t\t\tif (!first) side.alike.set(entity.id, state)\n\t\t\telse if (first !== state && sameEntity(first, state)) return first\n\t\t\treturn state\n\t\t}\n\t\tconst known = side.all.get(entity.id)\n\t\tif (known) return known\n\t\tconst state = playerEntityState(this.view, entity, this.common(entity))\n\t\tside.all.set(entity.id, state)\n\t\treturn state\n\t}\n\n\t/**\n\t * What the seats of this one's side are told alike this round (`Round.sides`), by entity: none outside a host's round.\n\t * Set as the capture starts (`capture`)\n\t */\n\tprivate sideNow: Side | undefined\n\n\t/**\n\t * Which seats are told the same of an entity where nothing of it is one player's: an observer's, or a team's with the\n\t * same allies among the players (relations are a pair of players', not a team's)\n\t */\n\tprivate sideKey(): string {\n\t\tif (this.observer) return 'observer'\n\t\tlet key = `team ${this.team}:`\n\t\tfor (const player of this.world.players.keys()) key += this.isAlly(player) ? '1' : '0'\n\t\treturn key\n\t}\n\n\t/**\n\t * Whether what this player is told of an entity is theirs alone, not their side's: a component replicated to its owner\n\t * or shaping itself for each player (`Component.snapshot`), or control of another's unit shared with this player\n\t */\n\tprivate isOnePlayers(entity: Entity): boolean {\n\t\tif (hasOnePlayersPart(this.world, entity)) return true\n\t\treturn entity.owner !== this.playerId && !this.observer && this.isAlly(entity.owner) && this.world.mayCommand(this.playerId, entity)\n\t}\n\n\t/** Where in the list being captured are those that may be one player's (`SideSeen.mine`): while the first seat of a side captures */\n\tprivate mineNow: number[] | undefined\n\n\t/**\n\t * What the team remembers of a structure is every teammate's to be told, not this seat's: without the parts of the\n\t * description shaped for one player (components replicated to the owner, or made by their `snapshot` for whoever is\n\t * told), which the seat that happened to see it first would otherwise give to the whole team\n\t */\n\tprivate forTeam(entity: Entity, state: EntityState): EntityState {\n\t\tif (!state.components || !hasOnePlayersPart(this.world, entity)) return state\n\t\tconst components: Record<string, unknown> = {}\n\t\tfor (const [id, part] of Object.entries(state.components)) {\n\t\t\tconst component = this.world.registry.component(id)\n\t\t\tif (component?.replicate === 'owner' || (component?.replicate && component.snapshot)) continue\n\t\t\tcomponents[id] = part\n\t\t}\n\t\treturn { ...state, components }\n\t}\n\n\t/** Adds what the player sees of an entity in sight to the snapshot, and remembers structures for when they are out of sight */\n\tprivate see(entity: Entity, out: EntityState[], remembered: Record<EntityId, EntityState>): void {\n\t\tconst before = remembered[entity.id]\n\t\t// trees and mines rarely change: what was said about them last time is said again, as it is\n\t\tconst kept = entity.isResource && before?.visible && before.resource === entity.get(deposit)?.amount\n\t\tconst state = kept ? before : this.describe(entity)\n\t\tif (!kept && this.mineNow && (this.isAlly(entity.owner) || hasOnePlayersPart(this.world, entity))) this.mineNow.push(out.length)\n\t\tout.push(state)\n\t\tthis.inSight.add(entity.id)\n\t\tif (entity.isStructure && !this.isAlly(entity.owner)) {\n\t\t\tif (state !== before) remembered[entity.id] = this.forTeam(entity, state)\n\t\t} else if (before) delete remembered[entity.id]\n\t}\n\n\t/** Throws when what was taken to be in sight is not what testing every entity gives. See `debugChecks` */\n\tprivate checkSight(): void {\n\t\tfor (const entity of this.world.entities.values()) {\n\t\t\tif (!entity.alive || this.knows(entity) === this.inSight.has(entity.id)) continue\n\t\t\tconst said = this.inSight.has(entity.id) ? 'in sight' : 'out of sight'\n\t\t\tthrow new Error(`Snapshot for player ${this.playerId} has ${entity.def.id}#${entity.id} ${said}, it is not`)\n\t\t}\n\t}\n\n\t/** The scenery the player's team sees right now */\n\tprivate *sceneryInSight(): Iterable<Entity> {\n\t\tconst { world } = this\n\t\t// a team that sees the whole map sees all of it. Only for players who are out and a debug switch\n\t\tif (this.observer || world.fog.isRevealed(this.team)) {\n\t\t\tfor (const entity of world.entities.values()) if (entity.scenery) yield entity\n\t\t} else yield* world.sceneryInSight.get(this.team) ?? []\n\t}\n\n\t/**\n\t * On a map explored from the start, what stands on it and belongs to no player (trees, mines, rocks, neutral\n\t * buildings, the creeps' own) known to the team from the first snapshot, as it stands, out of sight: the genre's melee\n\t * maps. Once for a team (`TeamMemory.startKnown`); units, and players' buildings, only once seen\n\t */\n\tprivate knowStart(remembered: Record<EntityId, EntityState>): void {\n\t\tconst { world } = this\n\t\tif (this.observer || !world.fog.exploredFromStart) return\n\t\tconst memory = this.memory\n\t\tif (memory.startKnown) return\n\t\tmemory.startKnown = true\n\t\tfor (const entity of world.entities.values()) {\n\t\t\tif (!entity.alive || !entity.isStructure || this.inSight.has(entity.id) || remembered[entity.id]) continue\n\t\t\tconst owner = world.players.get(entity.owner)\n\t\t\tif (!owner?.neutral && !owner?.creeps) continue\n\t\t\tremembered[entity.id] = { ...this.forTeam(entity, this.describe(entity)), visible: false }\n\t\t}\n\t}\n\n\tprivate capture(): Snapshot {\n\t\tconst { world } = this\n\t\tconst round = SHARED.get(world)\n\t\tif (round) {\n\t\t\tconst key = this.sideKey()\n\t\t\tlet side = round.sides.get(key)\n\t\t\tif (!side) round.sides.set(key, (side = { all: new Map(), alike: new Map() }))\n\t\t\tthis.sideNow = side\n\t\t} else this.sideNow = undefined\n\t\tconst remembered = this.memory.structures\n\t\t// what is named, by id, for `describe`: the names are few, and looked up for every entity in sight\n\t\tthis.namesNow.clear()\n\t\tif (world.states.has(names)) for (const [name, id] of Object.entries(world.state(names))) this.namesNow.set(id, name)\n\t\tconst seen = this.sideNow?.seen\n\t\tconst entities = seen ? this.seeAsSide(seen) : this.seeAll(remembered)\n\t\tif (this.world.checks.sight) this.checkSight()\n\t\tif (seen) return this.finish(entities)\n\t\tthis.knowStart(remembered)\n\t\t// the fog back after it was lifted: what was seen only while it was (ground never explored) is not known after all\n\t\tconst revealed = this.observer || world.fog.isRevealed(this.team)\n\t\tif (this.wasRevealed && !revealed) {\n\t\t\tfor (const [key, state] of Object.entries(remembered)) {\n\t\t\t\tif (!this.inSight.has(Number(key)) && !world.fog.isExplored(this.team, state.x, state.z)) delete remembered[Number(key)]\n\t\t\t}\n\t\t}\n\t\tthis.wasRevealed = revealed\n\t\t// Structures that are not in sight are shown the way they were last seen. That goes for the ones that were\n\t\t// destroyed out of sight too: they stay on the map until someone looks at the spot again. Where the rules keep\n\t\t// nothing of what was seen (`FogRules.explored: 'nothing'`), out of sight is forgotten\n\t\tconst forget = world.rules.fog?.explored === 'nothing' && !revealed\n\t\tfor (const [key, state] of Object.entries(remembered)) {\n\t\t\tconst id = Number(key)\n\t\t\tif (this.inSight.has(id)) continue\n\t\t\tif (forget) {\n\t\t\t\tdelete remembered[id]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!world.get(id) && this.sees(state.x, state.z)) {\n\t\t\t\tdelete remembered[id]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// made once, when it leaves the view\n\t\t\tconst memory = state.visible ? { ...state, visible: false } : state\n\t\t\tif (memory !== state) remembered[id] = memory\n\t\t\tentities.push(memory)\n\t\t}\n\t\tif (this.sideNow) this.sideNow.seen = { entities: [...entities], inSight: new Set(this.inSight), mine: this.mineNow ?? [] }\n\t\tthis.mineNow = undefined\n\t\treturn this.finish(entities)\n\t}\n\n\t/** The entities in sight, and what the side remembers out of it, as the first seat of a side (or a seat on its own) sees them */\n\tprivate seeAll(remembered: Record<EntityId, EntityState>): EntityState[] {\n\t\tconst { world } = this\n\t\tconst entities: EntityState[] = []\n\t\tthis.inSight.clear()\n\t\tthis.mineNow = this.sideNow ? [] : undefined\n\t\t// what acts or changes by itself is looked at one by one\n\t\tfor (const entity of world.actors.values()) {\n\t\t\tif (entity.alive && this.knows(entity)) this.see(entity, entities, remembered)\n\t\t}\n\t\t// Scenery (a map can have thousands of trees) never moves, so it only comes into sight or goes out of it when\n\t\t// the fog is worked out again. The fog system keeps what each team sees of it, instead of every tree being tested here\n\t\tfor (const entity of this.sceneryInSight()) {\n\t\t\tif (entity.alive && entity.scenery) this.see(entity, entities, remembered)\n\t\t}\n\t\treturn entities\n\t}\n\n\t/**\n\t * What another seat of the side saw this round, as this one sees it: the same, but what may be this player's alone\n\t * described again for them. The side's memory is the first seat's to keep\n\t */\n\tprivate seeAsSide(seen: SideSeen): EntityState[] {\n\t\tconst entities = [...seen.entities]\n\t\tthis.inSight.clear()\n\t\tfor (const id of seen.inSight) this.inSight.add(id)\n\t\tfor (const at of seen.mine) entities[at] = this.describe(this.world.get(entities[at].id)!)\n\t\t// as the first seat did, what was seen only while the fog was lifted is no longer known\n\t\tthis.wasRevealed = this.observer || this.world.fog.isRevealed(this.team)\n\t\treturn entities\n\t}\n\n\t/** The rest of a snapshot, round its entities: the players, and every feature's part (`SnapshotPart`) */\n\tprivate finish(entities: EntityState[]): Snapshot {\n\t\tconst { world } = this\n\t\tconst players: PlayerState[] = []\n\t\tfor (const player of world.players.values()) {\n\t\t\tconst state: PlayerState = {\n\t\t\t\tid: player.id,\n\t\t\t\tname: player.name,\n\t\t\t\tteam: player.team,\n\t\t\t\tcolor: player.color,\n\t\t\t\tneutral: player.neutral,\n\t\t\t\tcreeps: player.creeps || undefined,\n\t\t\t\t...(player.race !== undefined && { race: player.race }),\n\t\t\t\tdefeated: player.defeated,\n\t\t\t\trelation:\n\t\t\t\t\tplayer.id === this.playerId\n\t\t\t\t\t\t? 'self'\n\t\t\t\t\t\t: world.areAllies(this.playerId, player.id)\n\t\t\t\t\t\t\t? 'ally'\n\t\t\t\t\t\t\t: world.areEnemies(this.playerId, player.id)\n\t\t\t\t\t\t\t\t? 'enemy'\n\t\t\t\t\t\t\t\t: 'neutral'\n\t\t\t}\n\t\t\tif (state.relation === 'ally' && !player.neutral && !this.observer) {\n\t\t\t\tconst me = world.player(this.playerId)\n\t\t\t\tstate.shared = {\n\t\t\t\t\tcontrol: world.sides.controlOf(this.playerId).includes(player.id),\n\t\t\t\t\tvision: me.team === player.team || world.sides.visionOf(me.team).includes(player.team)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// an observer is told every player's\n\t\t\tif (player.id === this.playerId || (this.observer && !player.neutral)) {\n\t\t\t\tstate.own = {\n\t\t\t\t\tresources: { ...player.resources },\n\t\t\t\t\tsupplyUsed: player.supplyUsed,\n\t\t\t\t\tsupplyCap: player.supplyCap,\n\t\t\t\t\t...(Object.keys(player.supplies).length > 0 && { supplies: structuredClone(player.supplies) }),\n\t\t\t\t\tupkeep: world.rules.economy.upkeep(world, player.id),\n\t\t\t\t\tupgrades: Object.fromEntries(player.upgrades),\n\t\t\t\t\tresearching: [...player.researching],\n\t\t\t\t\ttech: [...techOf(world, player.id)],\n\t\t\t\t\theroes: heroSummaries(world, player.id),\n\t\t\t\t\t// copies: the snapshot is the player's to keep, and the objectives go on changing\n\t\t\t\t\tobjectives: world.objectives.of(player.id).map((objective) => structuredClone(objective)),\n\t\t\t\t\t...(world.timers.shownTo(player.id).length && { timers: world.timers.shownTo(player.id) })\n\t\t\t\t}\n\t\t\t\tif (world.hooks.has('requirement') && player.id === this.playerId) state.own.unlocks = decidedUnlocks(world, player.id)\n\t\t\t\tif (world.hooks.has('available') && player.id === this.playerId) {\n\t\t\t\t\tconst availability = decidedAvailability(world, player.id)\n\t\t\t\t\tif (availability) state.own.availability = availability\n\t\t\t\t}\n\t\t\t}\n\t\t\tplayers.push(state)\n\t\t}\n\n\t\t// the rest is each feature's to say (`SnapshotPart`): before the entities where it says, the rest after the players\n\t\tconst { view } = this\n\t\tconst snapshot = { tick: world.tick } as Snapshot\n\t\tconst parts = world.registry.snapshotParts\n\t\tconst take = (part: SnapshotPart) => {\n\t\t\tconst value = part.capture(view)\n\t\t\tif (value !== undefined) (snapshot as unknown as Record<string, unknown>)[part.key] = value\n\t\t}\n\t\tfor (const part of parts) if (part.head) take(part)\n\t\tsnapshot.entities = entities\n\t\tsnapshot.players = players\n\t\tfor (const part of parts) if (!part.head) take(part)\n\t\treturn snapshot\n\t}\n\n\tsnapshot(): Snapshot {\n\t\treturn this.capture()\n\t}\n\n\t/**\n\t * Moves the game on by `ticks` at the next update, however fast it goes: a step of a paused game (`speed` 0), as\n\t * an editor's Step does. Ticks asked for while it runs are taken on top of its pace\n\t */\n\tadvance(ticks = 1): void {\n\t\tthis.accumulator += this.world.dt * Math.max(0, Math.floor(ticks))\n\t}\n\n\t/** A save of the world as it stands (`saveWorld`): at once, as a promise for what a session elsewhere answers later */\n\tsave(): Promise<WorldSave> {\n\t\ttry {\n\t\t\treturn Promise.resolve(saveWorld(this.world))\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error)\n\t\t}\n\t}\n\n\t/**\n\t * Runs the game on by itself, a tick at a time, as fast as the page can, until `until` holds of the world, `most`\n\t * ticks have run, the game is over, or `deadline` (`performance.now()`'s) is past: what an editor's \"Play to\" does a\n\t * slice a frame, its pace and `advance` aside. The ticks are the same ticks the game runs at its own pace, so the\n\t * same game comes to the same moment. What happened in them is in the next snapshot (`update`), as after a slow frame.\n\t * `until` is asked before the first tick too: what holds already runs none\n\t */\n\trunUntil(until: (world: World) => boolean, options: { most?: number; deadline?: number } = {}): { ticks: number; reached: boolean; over: boolean } {\n\t\tconst { world } = this\n\t\tconst most = options.most ?? Infinity\n\t\tconst deadline = options.deadline ?? Infinity\n\t\tlet ticks = 0\n\t\tconst over = () => world.failure !== null || world.winner !== null\n\t\twhile (!until(world)) {\n\t\t\tif (ticks >= most || over()) return this.ran(ticks, false, over())\n\t\t\t// the clock looked at every few ticks: a tick is a fraction of a millisecond, a look is not free\n\t\t\tif (ticks % 8 === 7 && performance.now() > deadline) return this.ran(ticks, false, false)\n\t\t\tthis.tickOnce()\n\t\t\tticks++\n\t\t}\n\t\treturn this.ran(ticks, true, over())\n\t}\n\n\t/** What `runUntil` gives back, the debug tools' view brought up to date where it ran */\n\tprivate ran(ticks: number, reached: boolean, over: boolean): { ticks: number; reached: boolean; over: boolean } {\n\t\tif (ticks) {\n\t\t\tthis.debug.refresh()\n\t\t\tthis.ranOn = true\n\t\t}\n\t\treturn { ticks, reached, over }\n\t}\n\n\t/** Whether `runUntil` ran ticks since the last update: its next snapshot describes them, paused or not */\n\tprivate ranOn = false\n\n\t/** A tick of the world, and the checkpoint it marked saved as the world stood at its end, not at the end of the frame */\n\tprivate tickOnce(): void {\n\t\tthis.world.step()\n\t\tif (this.pendingCheckpoint) {\n\t\t\tthis.checkpoint = { label: this.pendingCheckpoint, save: saveWorld(this.world) }\n\t\t\tthis.pendingCheckpoint = undefined\n\t\t}\n\t}\n\n\tupdate(dt: number): Snapshot[] {\n\t\tconst { world } = this\n\t\tlet stepped = this.ranOn\n\t\tthis.ranOn = false\n\t\t// slowed down or paused here (tests, tools), and by the game's speed (`debug.speed`)\n\t\tthis.accumulator += dt * this.speed * world.cheats.speed\n\t\twhile (this.accumulator >= world.dt) {\n\t\t\tthis.tickOnce()\n\t\t\tthis.accumulator -= world.dt\n\t\t\tstepped = true\n\t\t}\n\t\tthis.alpha = this.speed * world.cheats.speed > 0 ? this.accumulator / world.dt : 1\n\t\t// When a slow frame had several ticks to catch up on, only how things stand after the last one is described:\n\t\t// the client would throw the ones in between away. What happened in them is in the events, which pile up until then.\n\t\t// With no tick, what was said between ticks (talk, carried out at once: RV14) goes in a snapshot of the same tick\n\t\tif (!stepped) return this.view.events.length ? [this.capture()] : []\n\t\tthis.debug.refresh()\n\t\treturn [this.capture()]\n\t}\n\n\t/** Sends a command. `seq` is the sender's own number for it, for a host passing on what a remote player numbered */\n\tsend(command: PlayerCommand, seq = ++this.lastSeq): number {\n\t\t// the seat decides who is speaking, whatever the message claims\n\t\tthis.world.issue({ ...command, player: this.playerId, seq } as Parameters<World['issue']>[0])\n\t\treturn seq\n\t}\n\n\t/**\n\t * The number of the last command sent: a computer's seat keeps it through a save, so the commands it sends after a\n\t * load are numbered as they would have been\n\t *\n\t * @beta\n\t */\n\tlastSeq = 0\n\n\tfog(): FogState {\n\t\tconst { fog } = this.world\n\t\tconst cells = fog.cells(this.team)\n\t\treturn {\n\t\t\twidth: fog.width,\n\t\t\tdepth: fog.depth,\n\t\t\tversion: fog.version,\n\t\t\trevealed: this.observer || fog.isRevealed(this.team) || !cells,\n\t\t\tvisible: cells?.visible ?? new Uint8Array(0),\n\t\t\texplored: cells?.explored ?? new Uint8Array(0)\n\t\t}\n\t}\n\n\t/** Where the game's money is mined, as the map shows it, seen or not (`GameSession.mines`, `minesFor`) */\n\tmines(): readonly MineInfo[] {\n\t\treturn minesFor(this.view)\n\t}\n\n\t/** The lanes of the map, as the map shows them (`GameSession.lanes`) */\n\tlanes(): readonly Lane[] {\n\t\treturn lanesOf(this.world)\n\t}\n\n\t/** The camps as the player knows them (`GameSession.camps`, `campsFor`): worked out once a tick */\n\tcamps(): readonly CampInfo[] {\n\t\treturn campsFor(this.view)\n\t}\n\n\tcanPlace(unitType: string, point: Vec2): boolean {\n\t\treturn this.registry.units.has(unitType) && canPlaceStructure(this.world, this.registry.unit(unitType), point, this.playerId, true)\n\t}\n\n\t/** Which cells of a building's ground are in the way for the player: taken, or not explored by their team (`placementCells`) */\n\tplaceCells(unitType: string, point: Vec2): readonly boolean[] | undefined {\n\t\tif (!this.registry.units.has(unitType)) return undefined\n\t\tconst { world } = this\n\t\tconst { team } = world.player(this.playerId)\n\t\treturn placementCells(\n\t\t\tthis.registry.unit(unitType),\n\t\t\tpoint,\n\t\t\t(x, z) => world.grid.canPlace(x, z, 1, 1),\n\t\t\t(x, z) => world.fog.isExplored(team, x + 0.5, z + 0.5)\n\t\t)\n\t}\n\n\tfindPath(from: Vec2, to: Vec2, flying = false): Vec2[] | null {\n\t\treturn (flying ? this.world.air : this.world.nav).findPath(from, to)\n\t}\n\n\t/** What happened since the last snapshot, not yet given in one: a copy, for a computer's save */\n\tpendingEvents(): SessionEvent[] {\n\t\treturn structuredClone(this.view.events)\n\t}\n\n\t/** Takes back what `pendingEvents` gave, ahead of what has happened since: in a game loaded from a save */\n\trestoreEvents(events: readonly SessionEvent[]): void {\n\t\tthis.view.events = [...structuredClone(events), ...this.view.events]\n\t}\n\n\t/** Whether the world goes with the session */\n\tprivate readonly ownsWorld: boolean\n\n\tdispose(): void {\n\t\tfor (const dispose of this.disposers.splice(0)) dispose()\n\t\tthis.debug.dispose()\n\t\tif (this.ownsWorld) this.world.dispose()\n\t}\n}\n"],"mappings":"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"}
package/dist/log.d.ts ADDED
@@ -0,0 +1,140 @@
1
+ /**
2
+ * The log: what the engine, a server, the client and a game say about what they do, as entries of plain data that go
3
+ * to whoever asked for them (a sink). A world has its own (`world.log`), whose entries say which game and which tick
4
+ * they are from; every logger passes its entries up to the one it was made under, so that a sink at the top
5
+ * (`rootLogger.to`, or a server's own) sees all of them.
6
+ *
7
+ * The log says, and nothing else: it reads nothing of the simulation's chances, changes nothing in a world, and is
8
+ * not kept in a save. Two runs of a game are the same whether anyone listens or not.
9
+ */
10
+ /**
11
+ * How much an entry matters: `debug` for whoever looks closely, `error` for what went wrong
12
+ *
13
+ * @beta
14
+ */
15
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
16
+ /** @beta */
17
+ export declare const LOG_LEVELS: readonly LogLevel[];
18
+ /**
19
+ * One thing said. Plain data: it crosses a session, a worker and a file as it is
20
+ *
21
+ * @beta
22
+ */
23
+ export interface LogEntry {
24
+ level: LogLevel;
25
+ /** What part said it: `server`, `game`, `assets`, a mod's own */
26
+ category: string;
27
+ message: string;
28
+ /** What it is about, by name: an entity's id, a player, a file, an error (`errorFields`) */
29
+ fields?: Record<string, unknown>;
30
+ /** The game it was said in, and its tick, where it was said in one */
31
+ game?: string;
32
+ tick?: number;
33
+ /** When, in milliseconds of the clock (`Date.now`). Never read by the simulation */
34
+ time: number;
35
+ }
36
+ /**
37
+ * Where entries go: the console, a file, a panel, a service
38
+ *
39
+ * @beta
40
+ */
41
+ export type LogSink = (entry: LogEntry) => void;
42
+ /**
43
+ * What a logger adds to each of its entries: the game and the tick of a world, the fields of a part
44
+ *
45
+ * @beta
46
+ */
47
+ export type LogContext = () => Partial<Pick<LogEntry, 'game' | 'tick'>> & {
48
+ fields?: Record<string, unknown>;
49
+ };
50
+ /** @beta */
51
+ export interface LoggerOptions {
52
+ /** The logger this one passes its entries up to. None for one that stands alone */
53
+ parent?: Logger;
54
+ /** The least an entry must matter to be said here: everything when left out */
55
+ level?: LogLevel;
56
+ context?: LogContext;
57
+ }
58
+ /**
59
+ * An error as plain data, for an entry's fields: what it is called, what it says, and where it was thrown
60
+ *
61
+ * @beta
62
+ */
63
+ export declare function errorFields(error: unknown): {
64
+ name: string;
65
+ message: string;
66
+ stack?: string;
67
+ };
68
+ /**
69
+ * An entry as one line of text: `warn [server] tick 120 of td: a connection took in too slowly {bytes: 12}`
70
+ *
71
+ * @beta
72
+ */
73
+ export declare function logLine(entry: LogEntry): string;
74
+ /**
75
+ * Writes entries to the console, each by its level. An error among the fields is shown as the console shows errors
76
+ *
77
+ * @beta
78
+ */
79
+ export declare const consoleSink: LogSink;
80
+ /** @beta */
81
+ export declare class Logger {
82
+ /** The least an entry must matter to be said: what is under it is dropped here, and goes no further */
83
+ level: LogLevel;
84
+ private readonly parent?;
85
+ private readonly context?;
86
+ private readonly sinks;
87
+ constructor(options?: LoggerOptions);
88
+ /** Sends this logger's entries, and those of every logger under it, to a sink. Returns what stops it */
89
+ to(sink: LogSink): () => void;
90
+ /** A logger under this one: its entries carry what `context` adds, and are passed up here */
91
+ child(options?: Omit<LoggerOptions, 'parent'> | LogContext): Logger;
92
+ /** Whether an entry of this level would be said: for not putting together what nobody will read */
93
+ says(level: LogLevel): boolean;
94
+ log(level: LogLevel, category: string, message: string, fields?: Record<string, unknown>): void;
95
+ debug(category: string, message: string, fields?: Record<string, unknown>): void;
96
+ info(category: string, message: string, fields?: Record<string, unknown>): void;
97
+ warn(category: string, message: string, fields?: Record<string, unknown>): void;
98
+ error(category: string, message: string, fields?: Record<string, unknown>): void;
99
+ /**
100
+ * Takes an entry made elsewhere (a world's, by the client that shows it; a server's, sent to a tool) as if it was
101
+ * said here: to this logger's sinks, and up. What it already says of its game and its tick is kept
102
+ */
103
+ pass(entry: LogEntry): void;
104
+ }
105
+ /**
106
+ * The logger everything is under when nothing else is said: a world's, a server's, the client's. It writes to the
107
+ * console (`rootConsole.stop()` ends that, for a page or a server that keeps its log elsewhere), from `info` up
108
+ *
109
+ * @beta
110
+ */
111
+ export declare const rootLogger: Logger;
112
+ /**
113
+ * The root logger's writing to the console: stopped and started again
114
+ *
115
+ * @beta
116
+ */
117
+ export declare const rootConsole: {
118
+ readonly on: boolean;
119
+ stop(): void;
120
+ start(): void;
121
+ };
122
+ /**
123
+ * The last entries, kept: what a console panel shows, and what goes with a report of a crash
124
+ *
125
+ * @beta
126
+ */
127
+ export interface LogRing {
128
+ sink: LogSink;
129
+ /** The entries kept, the oldest first */
130
+ entries(): readonly LogEntry[];
131
+ clear(): void;
132
+ /** Calls back for each entry as it comes. Returns what stops it */
133
+ onEntry(listener: LogSink): () => void;
134
+ }
135
+ /**
136
+ * Keeps the last `size` entries (500 when left out) of whatever its sink is given
137
+ *
138
+ * @beta
139
+ */
140
+ export declare function createLogRing(size?: number): LogRing;
@@ -0,0 +1,39 @@
1
+ import { type DamageType } from './defs';
2
+ import type { Entity } from './entity';
3
+ import type { GamePack } from './packs/pack';
4
+ import type { World } from './world';
5
+ /**
6
+ * The mana burn pack's id
7
+ *
8
+ * @beta
9
+ */
10
+ export declare const MANA_BURN = "core.manaBurn";
11
+ /**
12
+ * How mana is burnt (`burnMana`)
13
+ *
14
+ * @beta
15
+ */
16
+ export interface BurnOptions {
17
+ /** Damage for each point of mana burnt: 1 when left out */
18
+ ratio?: number;
19
+ /** Magic when left out */
20
+ damageType?: DamageType;
21
+ /** The ability that burnt it, by id: for the damage and the mana told */
22
+ ability?: string;
23
+ }
24
+ /**
25
+ * Takes up to `amount` of a unit's mana and hurts it by as much as it took (times `ratio`), from `source`: what the
26
+ * `manaBurn` effect does, for a game's own rules. Gives back the mana it took: none of a unit that has none, and no
27
+ * damage then
28
+ *
29
+ * @beta
30
+ */
31
+ export declare function burnMana(world: World, target: Entity, amount: number, source?: Entity, options?: BurnOptions): number;
32
+ /**
33
+ * Mana burn, as in classic RTS games: the `manaBurn` effect (`EffectTypes.manaBurn`) takes `amount` of what it reaches of its
34
+ * mana and hurts it by as much (times `ratio`). The demon hunter's spell is an ability with it; Feedback is a passive
35
+ * whose `onHit` has it. `burnMana` does it in code
36
+ *
37
+ * @beta
38
+ */
39
+ export declare function withManaBurn(): GamePack;
@@ -0,0 +1,114 @@
1
+ import type { GameData } from '../gameData';
2
+ import type { GeneratedWith } from '../generate';
3
+ import type { MapEnvironment } from './look';
4
+ import { type CellRect, type GameMap, type MapCamera, type MapCamp, type MapDay, type MapDoodad, type MapForce, type MapItemTable, type MapObject, type MapPath, type MapPlayer, type MapPoint, type MapRandomGroup, type MapRegion } from './types';
5
+ /**
6
+ * A map the way it is written to a file: JSON, with the layers packed
7
+ *
8
+ * @beta
9
+ */
10
+ export interface MapFile {
11
+ format: number;
12
+ name: string;
13
+ description: string;
14
+ game?: string;
15
+ width: number;
16
+ depth: number;
17
+ cliffHeight: number;
18
+ /**
19
+ * The layers of the ground, a line of text for each row (since format 3: before, one line for the whole layer): two
20
+ * people who change different rows change different lines, which git merges. The heights by corner, a row of the
21
+ * corners along x for each z; the rest by cell, a row of cells for each z
22
+ */
23
+ ground: string[];
24
+ levels: string[];
25
+ ramps: string[];
26
+ water: string[];
27
+ tiles: string[];
28
+ /** The game's layers of cells (`GameMap.cells`), by id, a line of text for each row as the layers above. Left out for none */
29
+ cells?: Record<string, string[]>;
30
+ /** What is kept off cells by hand (`GameMap.pathing`), a line of text for each row as the layers above. Left out for none */
31
+ pathing?: string[];
32
+ /** See `GameMap.tileset`. Since format 2 */
33
+ tileset: string[];
34
+ players: MapPlayer[];
35
+ objects: MapObject[];
36
+ camps: MapCamp[];
37
+ /** Left out when there are none, as files made before regions were have none */
38
+ regions?: MapRegion[];
39
+ /** Left out when there are none */
40
+ points?: MapPoint[];
41
+ paths?: MapPath[];
42
+ doodads?: MapDoodad[];
43
+ cameras?: MapCamera[];
44
+ randomGroups?: MapRandomGroup[];
45
+ itemTables?: MapItemTable[];
46
+ /** The map's own definitions (`GameMap.definitions`) */
47
+ definitions?: GameData;
48
+ forces?: MapForce[];
49
+ races?: string[];
50
+ author?: string;
51
+ silence?: string[];
52
+ meantFor?: string;
53
+ explored?: boolean;
54
+ loading?: string;
55
+ preview?: string;
56
+ environment?: MapEnvironment;
57
+ day?: MapDay;
58
+ generated?: GeneratedWith;
59
+ bounds?: CellRect;
60
+ /** Left out when the game keeps nothing with the map */
61
+ data?: Record<string, unknown>;
62
+ /** Left out when the editor keeps nothing with the map */
63
+ editor?: Record<string, unknown>;
64
+ }
65
+ /**
66
+ * Brings a file of one format up to the next
67
+ *
68
+ * @beta
69
+ */
70
+ export type MapMigration = (file: Record<string, unknown>) => Record<string, unknown>;
71
+ /**
72
+ * A map file brought up to the format this reader knows, step by step. Throws for what is not a map file, and for
73
+ * one of a newer format: what changed in it cannot be known here. `to` and `steps` are the reader's own when left out
74
+ *
75
+ * @beta
76
+ */
77
+ export declare function migrateMap(data: unknown, to?: number, steps?: Record<number, MapMigration>): Record<string, unknown>;
78
+ /**
79
+ * A map as its file. Throws when what the game keeps with it (`data`) is not plain data, saying where
80
+ *
81
+ * @beta
82
+ */
83
+ export declare function serializeMap(map: GameMap): MapFile;
84
+ /**
85
+ * The maps of map files, by the name of each file without its folder and `.vgmap.json`: `./maps/field.vgmap.json` is
86
+ * `field`. The files by their paths, read (`parseMap`): imported one by one, or Vite's
87
+ * `import.meta.glob('./maps/*.vgmap.json', { eager: true, import: 'default' })` where only a page reads them
88
+ *
89
+ * export const maps = mapsFrom({ './maps/field.vgmap.json': field, './maps/hills.vgmap.json': hills })
90
+ *
91
+ * Throws for two files of one name, and with the path of a file that cannot be read
92
+ *
93
+ * @beta
94
+ */
95
+ export declare function mapsFrom(files: Readonly<Record<string, unknown>>): Record<string, GameMap>;
96
+ /**
97
+ * Reads a map file, of this format or an older one. Throws with what is wrong with it
98
+ *
99
+ * @beta
100
+ */
101
+ export declare function parseMap(file: unknown): GameMap;
102
+ /**
103
+ * A copy that shares nothing with the original
104
+ *
105
+ * @beta
106
+ */
107
+ export declare function cloneMap(map: GameMap): GameMap;
108
+ /**
109
+ * The map without what its editor keeps of its own (`GameMap.editor`): what a game is given to play. The very map
110
+ * where it has none
111
+ *
112
+ * @beta
113
+ */
114
+ export declare function withoutEditor(map: GameMap): GameMap;