@v12-engine/engine 0.1.0 → 0.4.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 (951) hide show
  1. package/dist/abilities/amounts.d.ts +28 -0
  2. package/dist/abilities/amounts.js +74 -0
  3. package/dist/abilities/amounts.js.map +1 -0
  4. package/dist/abilities/buffs.d.ts +106 -6
  5. package/dist/abilities/buffs.js +443 -0
  6. package/dist/abilities/buffs.js.map +1 -0
  7. package/dist/abilities/castTold.d.ts +2 -0
  8. package/dist/abilities/castTold.js +66 -0
  9. package/dist/abilities/castTold.js.map +1 -0
  10. package/dist/abilities/chance.d.ts +38 -0
  11. package/dist/abilities/chance.js +77 -0
  12. package/dist/abilities/chance.js.map +1 -0
  13. package/dist/abilities/charges.d.ts +18 -0
  14. package/dist/abilities/charges.js +101 -0
  15. package/dist/abilities/charges.js.map +1 -0
  16. package/dist/abilities/control.d.ts +28 -0
  17. package/dist/abilities/control.js +113 -0
  18. package/dist/abilities/control.js.map +1 -0
  19. package/dist/abilities/dispel.js +51 -0
  20. package/dist/abilities/dispel.js.map +1 -0
  21. package/dist/abilities/effectFields.d.ts +1 -1
  22. package/dist/abilities/effectFields.js +676 -0
  23. package/dist/abilities/effectFields.js.map +1 -0
  24. package/dist/abilities/effectIndex.d.ts +27 -0
  25. package/dist/abilities/effectIndex.js +64 -0
  26. package/dist/abilities/effectIndex.js.map +1 -0
  27. package/dist/abilities/effects/buff.d.ts +9 -3
  28. package/dist/abilities/effects/buff.js +84 -0
  29. package/dist/abilities/effects/buff.js.map +1 -0
  30. package/dist/abilities/effects/conditions.d.ts +2 -0
  31. package/dist/abilities/effects/conditions.js +41 -0
  32. package/dist/abilities/effects/conditions.js.map +1 -0
  33. package/dist/abilities/effects/core.js +54 -0
  34. package/dist/abilities/effects/core.js.map +1 -0
  35. package/dist/abilities/effects/damage.d.ts +1 -1
  36. package/dist/abilities/effects/damage.js +43 -0
  37. package/dist/abilities/effects/damage.js.map +1 -0
  38. package/dist/abilities/effects/heal.d.ts +2 -2
  39. package/dist/abilities/effects/heal.js +51 -0
  40. package/dist/abilities/effects/heal.js.map +1 -0
  41. package/dist/abilities/effects/missile.d.ts +13 -1
  42. package/dist/abilities/effects/missile.js +104 -0
  43. package/dist/abilities/effects/missile.js.map +1 -0
  44. package/dist/abilities/effects/morph.d.ts +5 -0
  45. package/dist/abilities/effects/morph.js +43 -0
  46. package/dist/abilities/effects/morph.js.map +1 -0
  47. package/dist/abilities/effects/moves.d.ts +16 -4
  48. package/dist/abilities/effects/moves.js +212 -0
  49. package/dist/abilities/effects/moves.js.map +1 -0
  50. package/dist/abilities/effects/passives.d.ts +19 -9
  51. package/dist/abilities/effects/passives.js +131 -0
  52. package/dist/abilities/effects/passives.js.map +1 -0
  53. package/dist/abilities/effects/proxy.d.ts +5 -0
  54. package/dist/abilities/effects/proxy.js +60 -0
  55. package/dist/abilities/effects/proxy.js.map +1 -0
  56. package/dist/abilities/effects/sight.d.ts +2 -2
  57. package/dist/abilities/effects/sight.js +39 -0
  58. package/dist/abilities/effects/sight.js.map +1 -0
  59. package/dist/abilities/effects/spawn.d.ts +5 -2
  60. package/dist/abilities/effects/spawn.js +40 -0
  61. package/dist/abilities/effects/spawn.js.map +1 -0
  62. package/dist/abilities/effects/timed.d.ts +2 -2
  63. package/dist/abilities/effects/timed.js +96 -0
  64. package/dist/abilities/effects/timed.js.map +1 -0
  65. package/dist/abilities/effects/trade.d.ts +1 -1
  66. package/dist/abilities/effects/trade.js +25 -0
  67. package/dist/abilities/effects/trade.js.map +1 -0
  68. package/dist/abilities/effects.d.ts +97 -23
  69. package/dist/abilities/effects.js +860 -0
  70. package/dist/abilities/effects.js.map +1 -0
  71. package/dist/abilities/land.d.ts +38 -4
  72. package/dist/abilities/land.js +189 -0
  73. package/dist/abilities/land.js.map +1 -0
  74. package/dist/abilities/recast.d.ts +45 -0
  75. package/dist/abilities/recast.js +118 -0
  76. package/dist/abilities/recast.js.map +1 -0
  77. package/dist/abilities/scaled.js +40 -0
  78. package/dist/abilities/scaled.js.map +1 -0
  79. package/dist/abilities/screen.d.ts +6 -0
  80. package/dist/abilities/screen.js +83 -0
  81. package/dist/abilities/screen.js.map +1 -0
  82. package/dist/abilities/shapes.d.ts +66 -0
  83. package/dist/abilities/shapes.js +122 -0
  84. package/dist/abilities/shapes.js.map +1 -0
  85. package/dist/abilities/text.d.ts +14 -2
  86. package/dist/abilities/text.js +204 -0
  87. package/dist/abilities/text.js.map +1 -0
  88. package/dist/abilities/triggers.d.ts +98 -0
  89. package/dist/abilities/triggers.js +351 -0
  90. package/dist/abilities/triggers.js.map +1 -0
  91. package/dist/abilityChanges.d.ts +131 -0
  92. package/dist/abilityChanges.js +345 -0
  93. package/dist/abilityChanges.js.map +1 -0
  94. package/dist/ai/area.d.ts +4 -1
  95. package/dist/ai/brain.d.ts +4 -1
  96. package/dist/ai/brain.js +844 -0
  97. package/dist/ai/brain.js.map +1 -0
  98. package/dist/ai/budget.js +74 -0
  99. package/dist/ai/budget.js.map +1 -0
  100. package/dist/ai/checks.d.ts +9 -1
  101. package/dist/ai/checks.js +242 -0
  102. package/dist/ai/checks.js.map +1 -0
  103. package/dist/ai/computer.d.ts +11 -4
  104. package/dist/ai/computer.js +251 -0
  105. package/dist/ai/computer.js.map +1 -0
  106. package/dist/ai/defence.d.ts +4 -0
  107. package/dist/ai/defence.js +430 -0
  108. package/dist/ai/defence.js.map +1 -0
  109. package/dist/ai/define.d.ts +3 -2
  110. package/dist/ai/define.js +31 -0
  111. package/dist/ai/define.js.map +1 -0
  112. package/dist/ai/economy.d.ts +10 -7
  113. package/dist/ai/economy.js +780 -0
  114. package/dist/ai/economy.js.map +1 -0
  115. package/dist/ai/geometry.js +38 -0
  116. package/dist/ai/geometry.js.map +1 -0
  117. package/dist/ai/goals.d.ts +1 -0
  118. package/dist/ai/goals.js +560 -0
  119. package/dist/ai/goals.js.map +1 -0
  120. package/dist/ai/knowledge.d.ts +72 -7
  121. package/dist/ai/knowledge.js +804 -0
  122. package/dist/ai/knowledge.js.map +1 -0
  123. package/dist/ai/lanes.d.ts +10 -2
  124. package/dist/ai/lanes.js +715 -0
  125. package/dist/ai/lanes.js.map +1 -0
  126. package/dist/ai/melee/build.js +264 -0
  127. package/dist/ai/melee/build.js.map +1 -0
  128. package/dist/ai/melee/goals.d.ts +7 -0
  129. package/dist/ai/melee/goals.js +720 -0
  130. package/dist/ai/melee/goals.js.map +1 -0
  131. package/dist/ai/melee/heroes.js +68 -0
  132. package/dist/ai/melee/heroes.js.map +1 -0
  133. package/dist/ai/melee/index.d.ts +1 -1
  134. package/dist/ai/melee/index.js +51 -0
  135. package/dist/ai/melee/index.js.map +1 -0
  136. package/dist/ai/melee/production.js +29 -0
  137. package/dist/ai/melee/production.js.map +1 -0
  138. package/dist/ai/melee/surrender.js +64 -0
  139. package/dist/ai/melee/surrender.js.map +1 -0
  140. package/dist/ai/micro.d.ts +9 -0
  141. package/dist/ai/micro.js +1316 -0
  142. package/dist/ai/micro.js.map +1 -0
  143. package/dist/ai/mission.d.ts +9 -2
  144. package/dist/ai/mission.js +538 -0
  145. package/dist/ai/mission.js.map +1 -0
  146. package/dist/ai/missionRules.d.ts +1 -1
  147. package/dist/ai/missionRules.js +26 -0
  148. package/dist/ai/missionRules.js.map +1 -0
  149. package/dist/ai/module.d.ts +6 -2
  150. package/dist/ai/module.js +37 -0
  151. package/dist/ai/module.js.map +1 -0
  152. package/dist/ai/options.d.ts +3 -3
  153. package/dist/ai/plans/build.d.ts +20 -1
  154. package/dist/ai/plans/build.js +608 -0
  155. package/dist/ai/plans/build.js.map +1 -0
  156. package/dist/ai/plans/placement.d.ts +4 -1
  157. package/dist/ai/plans/placement.js +295 -0
  158. package/dist/ai/plans/placement.js.map +1 -0
  159. package/dist/ai/plans/plans.d.ts +9 -0
  160. package/dist/ai/plans/plans.js +110 -0
  161. package/dist/ai/plans/plans.js.map +1 -0
  162. package/dist/ai/plans/production.d.ts +14 -2
  163. package/dist/ai/plans/production.js +434 -0
  164. package/dist/ai/plans/production.js.map +1 -0
  165. package/dist/ai/plans/purse.d.ts +6 -3
  166. package/dist/ai/plans/purse.js +139 -0
  167. package/dist/ai/plans/purse.js.map +1 -0
  168. package/dist/ai/plans/tech.d.ts +6 -0
  169. package/dist/ai/plans/tech.js +122 -0
  170. package/dist/ai/plans/tech.js.map +1 -0
  171. package/dist/ai/profiles.d.ts +4 -4
  172. package/dist/{profiles-B3NS9jwk.js → ai/profiles.js} +3 -98
  173. package/dist/ai/profiles.js.map +1 -0
  174. package/dist/ai/reach.js +54 -0
  175. package/dist/ai/reach.js.map +1 -0
  176. package/dist/ai/report.d.ts +8 -0
  177. package/dist/ai/report.js +87 -0
  178. package/dist/ai/report.js.map +1 -0
  179. package/dist/ai/roles.d.ts +4 -0
  180. package/dist/ai/roles.js +207 -0
  181. package/dist/ai/roles.js.map +1 -0
  182. package/dist/ai/rules.d.ts +8 -2
  183. package/dist/ai/rules.js +416 -0
  184. package/dist/ai/rules.js.map +1 -0
  185. package/dist/ai/scouting.d.ts +6 -0
  186. package/dist/ai/scouting.js +324 -0
  187. package/dist/ai/scouting.js.map +1 -0
  188. package/dist/ai/settings.js +99 -0
  189. package/dist/ai/settings.js.map +1 -0
  190. package/dist/ai/squads.d.ts +21 -2
  191. package/dist/ai/squads.js +916 -0
  192. package/dist/ai/squads.js.map +1 -0
  193. package/dist/ai/strength.js +320 -0
  194. package/dist/ai/strength.js.map +1 -0
  195. package/dist/ai/task.d.ts +3 -1
  196. package/dist/ai/task.js +17 -0
  197. package/dist/ai/task.js.map +1 -0
  198. package/dist/ai/tasks/attack.js +24 -0
  199. package/dist/ai/tasks/attack.js.map +1 -0
  200. package/dist/ai/tasks/capture.d.ts +3 -3
  201. package/dist/ai/tasks/capture.js +37 -0
  202. package/dist/ai/tasks/capture.js.map +1 -0
  203. package/dist/ai/tasks/creep.js +29 -0
  204. package/dist/ai/tasks/creep.js.map +1 -0
  205. package/dist/ai/tasks/defend.js +61 -0
  206. package/dist/ai/tasks/defend.js.map +1 -0
  207. package/dist/ai/tasks/drop.js +81 -0
  208. package/dist/ai/tasks/drop.js.map +1 -0
  209. package/dist/ai/tasks/escort.js +59 -0
  210. package/dist/ai/tasks/escort.js.map +1 -0
  211. package/dist/ai/tasks/gather.js +48 -0
  212. package/dist/ai/tasks/gather.js.map +1 -0
  213. package/dist/ai/tasks/harass.js +39 -0
  214. package/dist/ai/tasks/harass.js.map +1 -0
  215. package/dist/ai/tasks/hold.js +32 -0
  216. package/dist/ai/tasks/hold.js.map +1 -0
  217. package/dist/ai/tasks/index.js +34 -0
  218. package/dist/ai/tasks/index.js.map +1 -0
  219. package/dist/ai/tasks/move.js +26 -0
  220. package/dist/ai/tasks/move.js.map +1 -0
  221. package/dist/ai/tasks/patrol.js +59 -0
  222. package/dist/ai/tasks/patrol.js.map +1 -0
  223. package/dist/ai/tasks/retreat.js +28 -0
  224. package/dist/ai/tasks/retreat.js.map +1 -0
  225. package/dist/ai/tasks/scout.js +73 -0
  226. package/dist/ai/tasks/scout.js.map +1 -0
  227. package/dist/ai/tasks/shared.d.ts +1 -1
  228. package/dist/ai/tasks/shared.js +137 -0
  229. package/dist/ai/tasks/shared.js.map +1 -0
  230. package/dist/ai/team.d.ts +18 -1
  231. package/dist/ai/team.js +492 -0
  232. package/dist/ai/team.js.map +1 -0
  233. package/dist/ai/threat.d.ts +6 -0
  234. package/dist/ai/threat.js +206 -0
  235. package/dist/ai/threat.js.map +1 -0
  236. package/dist/ai/view.d.ts +21 -7
  237. package/dist/ai/view.js +677 -0
  238. package/dist/ai/view.js.map +1 -0
  239. package/dist/ai/waves.d.ts +6 -0
  240. package/dist/ai/waves.js +410 -0
  241. package/dist/ai/waves.js.map +1 -0
  242. package/dist/ai.js +54 -6239
  243. package/dist/aiTesting.d.ts +6 -3
  244. package/dist/aiTesting.js +229 -0
  245. package/dist/aiTesting.js.map +1 -0
  246. package/dist/areas.d.ts +4 -1
  247. package/dist/areas.js +295 -0
  248. package/dist/areas.js.map +1 -0
  249. package/dist/attacks.d.ts +3 -3
  250. package/dist/attacks.js +127 -0
  251. package/dist/attacks.js.map +1 -0
  252. package/dist/burning.d.ts +267 -0
  253. package/dist/burning.js +795 -0
  254. package/dist/burning.js.map +1 -0
  255. package/dist/bytes.js +21 -0
  256. package/dist/bytes.js.map +1 -0
  257. package/dist/callings.d.ts +71 -0
  258. package/dist/callings.js +157 -0
  259. package/dist/callings.js.map +1 -0
  260. package/dist/cameraOrders.d.ts +78 -0
  261. package/dist/cameraOrders.js +114 -0
  262. package/dist/cameraOrders.js.map +1 -0
  263. package/dist/camps.d.ts +70 -4
  264. package/dist/camps.js +501 -0
  265. package/dist/camps.js.map +1 -0
  266. package/dist/capture.d.ts +15 -3
  267. package/dist/capture.js +304 -0
  268. package/dist/capture.js.map +1 -0
  269. package/dist/cellLayers.d.ts +78 -13
  270. package/dist/cellLayers.js +275 -0
  271. package/dist/cellLayers.js.map +1 -0
  272. package/dist/cellPatches.d.ts +24 -0
  273. package/dist/cellPatches.js +73 -0
  274. package/dist/cellPatches.js.map +1 -0
  275. package/dist/cinematics.d.ts +10 -5
  276. package/dist/cinematics.js +161 -0
  277. package/dist/cinematics.js.map +1 -0
  278. package/dist/clock.d.ts +2 -2
  279. package/dist/clock.js +78 -0
  280. package/dist/clock.js.map +1 -0
  281. package/dist/commands.d.ts +36 -4
  282. package/dist/commands.js +636 -0
  283. package/dist/commands.js.map +1 -0
  284. package/dist/components.d.ts +31 -10
  285. package/dist/components.js +74 -0
  286. package/dist/components.js.map +1 -0
  287. package/dist/computers.d.ts +4 -4
  288. package/dist/computers.js +194 -0
  289. package/dist/computers.js.map +1 -0
  290. package/dist/concealment.d.ts +25 -2
  291. package/dist/concealment.js +409 -0
  292. package/dist/concealment.js.map +1 -0
  293. package/dist/coreComponents.js +130 -0
  294. package/dist/coreComponents.js.map +1 -0
  295. package/dist/createGame.d.ts +306 -0
  296. package/dist/createGame.js +405 -0
  297. package/dist/createGame.js.map +1 -0
  298. package/dist/dashing.d.ts +18 -2
  299. package/dist/dashing.js +41 -0
  300. package/dist/dashing.js.map +1 -0
  301. package/dist/debug.d.ts +8 -0
  302. package/dist/debug.js +5 -3
  303. package/dist/debug2.js +76 -0
  304. package/dist/debug2.js.map +1 -0
  305. package/dist/debugCommands.d.ts +6 -6
  306. package/dist/debugCommands.js +537 -0
  307. package/dist/debugCommands.js.map +1 -0
  308. package/dist/debugging.d.ts +1 -0
  309. package/dist/defaultSets.d.ts +183 -0
  310. package/dist/defaultSets.js +216 -0
  311. package/dist/defaultSets.js.map +1 -0
  312. package/dist/definitions.d.ts +6 -0
  313. package/dist/definitions.js +78 -0
  314. package/dist/definitions.js.map +1 -0
  315. package/dist/defs.d.ts +1895 -165
  316. package/dist/defs.js +380 -0
  317. package/dist/defs.js.map +1 -0
  318. package/dist/denying.d.ts +4 -4
  319. package/dist/denying.js +106 -0
  320. package/dist/denying.js.map +1 -0
  321. package/dist/destructibles.d.ts +2 -2
  322. package/dist/destructibles.js +36 -0
  323. package/dist/destructibles.js.map +1 -0
  324. package/dist/determinism.d.ts +4 -4
  325. package/dist/determinism.js +247 -0
  326. package/dist/determinism.js.map +1 -0
  327. package/dist/dialog.d.ts +17 -2
  328. package/dist/dialog.js +108 -0
  329. package/dist/dialog.js.map +1 -0
  330. package/dist/effectRefs.js +28 -0
  331. package/dist/effectRefs.js.map +1 -0
  332. package/dist/effects.d.ts +27 -11
  333. package/dist/effects.js +110 -0
  334. package/dist/effects.js.map +1 -0
  335. package/dist/endings.d.ts +1 -1
  336. package/dist/endings.js +78 -0
  337. package/dist/endings.js.map +1 -0
  338. package/dist/engagement.d.ts +40 -6
  339. package/dist/engagement.js +530 -0
  340. package/dist/engagement.js.map +1 -0
  341. package/dist/engineEvents.d.ts +72 -9
  342. package/dist/engineEvents.js +520 -0
  343. package/dist/engineEvents.js.map +1 -0
  344. package/dist/entity.d.ts +275 -26
  345. package/dist/entity.js +441 -0
  346. package/dist/entity.js.map +1 -0
  347. package/dist/entityIndex.d.ts +10 -3
  348. package/dist/entityIndex.js +149 -0
  349. package/dist/entityIndex.js.map +1 -0
  350. package/dist/errors.d.ts +6 -2
  351. package/dist/errors.js +59 -0
  352. package/dist/errors.js.map +1 -0
  353. package/dist/events.d.ts +11 -5
  354. package/dist/events.js +158 -0
  355. package/dist/events.js.map +1 -0
  356. package/dist/exactMath.js +273 -0
  357. package/dist/exactMath.js.map +1 -0
  358. package/dist/features.d.ts +1 -1
  359. package/dist/features.js +127 -0
  360. package/dist/features.js.map +1 -0
  361. package/dist/fields.d.ts +25 -5
  362. package/dist/fields.js +140 -0
  363. package/dist/fields.js.map +1 -0
  364. package/dist/fixture.d.ts +3 -3
  365. package/dist/fixture.js +512 -0
  366. package/dist/fixture.js.map +1 -0
  367. package/dist/fog.d.ts +26 -3
  368. package/dist/fog.js +333 -0
  369. package/dist/fog.js.map +1 -0
  370. package/dist/foliage.d.ts +476 -0
  371. package/dist/foliage.js +1478 -0
  372. package/dist/foliage.js.map +1 -0
  373. package/dist/foliageDebug.d.ts +57 -0
  374. package/dist/foliageDebug.js +172 -0
  375. package/dist/foliageDebug.js.map +1 -0
  376. package/dist/foliageRegrowth.d.ts +20 -0
  377. package/dist/foliageRegrowth.js +332 -0
  378. package/dist/foliageRegrowth.js.map +1 -0
  379. package/dist/formState.d.ts +67 -0
  380. package/dist/formState.js +65 -0
  381. package/dist/formState.js.map +1 -0
  382. package/dist/formation.d.ts +46 -8
  383. package/dist/formation.js +297 -0
  384. package/dist/formation.js.map +1 -0
  385. package/dist/forms.d.ts +58 -0
  386. package/dist/forms.js +146 -0
  387. package/dist/forms.js.map +1 -0
  388. package/dist/friendlyFire.d.ts +2 -2
  389. package/dist/friendlyFire.js +37 -0
  390. package/dist/friendlyFire.js.map +1 -0
  391. package/dist/game.d.ts +141 -48
  392. package/dist/game.js +834 -0
  393. package/dist/game.js.map +1 -0
  394. package/dist/gameData.d.ts +96 -22
  395. package/dist/gameData.js +1690 -0
  396. package/dist/gameData.js.map +1 -0
  397. package/dist/gameFiles.d.ts +3 -3
  398. package/dist/gameFiles.js +14 -0
  399. package/dist/gameFiles.js.map +1 -0
  400. package/dist/gates.js +92 -0
  401. package/dist/gates.js.map +1 -0
  402. package/dist/generate.d.ts +28 -1
  403. package/dist/generate.js +1062 -0
  404. package/dist/generate.js.map +1 -0
  405. package/dist/generateWorker.d.ts +7 -3
  406. package/dist/generateWorker.js +86 -0
  407. package/dist/generateWorker.js.map +1 -0
  408. package/dist/grid.d.ts +9 -0
  409. package/dist/grid.js +102 -0
  410. package/dist/grid.js.map +1 -0
  411. package/dist/ground.d.ts +17 -1
  412. package/dist/ground.js +375 -0
  413. package/dist/ground.js.map +1 -0
  414. package/dist/groundObjects.d.ts +70 -0
  415. package/dist/groundObjects.js +371 -0
  416. package/dist/groundObjects.js.map +1 -0
  417. package/dist/groundSpeed.d.ts +20 -3
  418. package/dist/groundSpeed.js +117 -0
  419. package/dist/groundSpeed.js.map +1 -0
  420. package/dist/hero.d.ts +126 -10
  421. package/dist/hero.js +432 -0
  422. package/dist/hero.js.map +1 -0
  423. package/dist/holds.d.ts +94 -0
  424. package/dist/holds.js +305 -0
  425. package/dist/holds.js.map +1 -0
  426. package/dist/home.d.ts +1 -1
  427. package/dist/home.js +30 -0
  428. package/dist/home.js.map +1 -0
  429. package/dist/hooks.d.ts +339 -57
  430. package/dist/hooks.js +105 -0
  431. package/dist/hooks.js.map +1 -0
  432. package/dist/hotReload.d.ts +6 -5
  433. package/dist/hotReload.js +145 -0
  434. package/dist/hotReload.js.map +1 -0
  435. package/dist/ids.d.ts +3 -3
  436. package/dist/ids.js +30 -0
  437. package/dist/ids.js.map +1 -0
  438. package/dist/idsFile.d.ts +36 -0
  439. package/dist/idsFile.js +134 -0
  440. package/dist/idsFile.js.map +1 -0
  441. package/dist/index.d.ts +105 -68
  442. package/dist/index.js +194 -4701
  443. package/dist/inspect.d.ts +29 -2
  444. package/dist/{inspect-D9dWHmZ0.js → inspect.js} +21 -12
  445. package/dist/inspect.js.map +1 -0
  446. package/dist/inventory.d.ts +14 -1
  447. package/dist/inventory.js +84 -0
  448. package/dist/inventory.js.map +1 -0
  449. package/dist/items.d.ts +136 -8
  450. package/dist/items.js +585 -0
  451. package/dist/items.js.map +1 -0
  452. package/dist/lanes.d.ts +12 -3
  453. package/dist/lanes.js +496 -0
  454. package/dist/lanes.js.map +1 -0
  455. package/dist/life.d.ts +6 -2
  456. package/dist/life.js +287 -0
  457. package/dist/life.js.map +1 -0
  458. package/dist/log.d.ts +26 -3
  459. package/dist/log.js +192 -0
  460. package/dist/log.js.map +1 -0
  461. package/dist/manaBurn.d.ts +2 -2
  462. package/dist/manaBurn.js +75 -0
  463. package/dist/manaBurn.js.map +1 -0
  464. package/dist/map/file.d.ts +56 -3
  465. package/dist/map/file.js +264 -0
  466. package/dist/map/file.js.map +1 -0
  467. package/dist/map/images.js +61 -0
  468. package/dist/map/images.js.map +1 -0
  469. package/dist/map/look.d.ts +1 -1
  470. package/dist/map/look.js +30 -0
  471. package/dist/map/look.js.map +1 -0
  472. package/dist/map/pathProfile.js +183 -0
  473. package/dist/map/pathProfile.js.map +1 -0
  474. package/dist/map/resize.d.ts +4 -0
  475. package/dist/map/resize.js +136 -0
  476. package/dist/map/resize.js.map +1 -0
  477. package/dist/map/schema.js +257 -0
  478. package/dist/map/schema.js.map +1 -0
  479. package/dist/map/terrain.js +214 -0
  480. package/dist/map/terrain.js.map +1 -0
  481. package/dist/map/types.d.ts +92 -13
  482. package/dist/map/types.js +251 -0
  483. package/dist/map/types.js.map +1 -0
  484. package/dist/mapCheck/cells.js +94 -0
  485. package/dist/mapCheck/cells.js.map +1 -0
  486. package/dist/mapCheck/rules/foliage.d.ts +9 -0
  487. package/dist/mapCheck/rules/foliage.js +83 -0
  488. package/dist/mapCheck/rules/foliage.js.map +1 -0
  489. package/dist/mapCheck/rules/names.js +39 -0
  490. package/dist/mapCheck/rules/names.js.map +1 -0
  491. package/dist/mapCheck/rules/objects.d.ts +1 -1
  492. package/dist/mapCheck/rules/objects.js +56 -0
  493. package/dist/mapCheck/rules/objects.js.map +1 -0
  494. package/dist/mapCheck/rules/paths.js +32 -0
  495. package/dist/mapCheck/rules/paths.js.map +1 -0
  496. package/dist/mapCheck/rules/players.js +20 -0
  497. package/dist/mapCheck/rules/players.js.map +1 -0
  498. package/dist/mapCheck/rules/races.js +56 -0
  499. package/dist/mapCheck/rules/races.js.map +1 -0
  500. package/dist/mapCheck/rules/random.js +47 -0
  501. package/dist/mapCheck/rules/random.js.map +1 -0
  502. package/dist/mapCheck/rules/regions.js +30 -0
  503. package/dist/mapCheck/rules/regions.js.map +1 -0
  504. package/dist/mapCheck/rules/targets.js +31 -0
  505. package/dist/mapCheck/rules/targets.js.map +1 -0
  506. package/dist/mapCheck/rules/walking.js +45 -0
  507. package/dist/mapCheck/rules/walking.js.map +1 -0
  508. package/dist/mapCheck.d.ts +2 -2
  509. package/dist/mapCheck.js +63 -0
  510. package/dist/mapCheck.js.map +1 -0
  511. package/dist/mapFields.d.ts +25 -2
  512. package/dist/mapFields.js +134 -0
  513. package/dist/mapFields.js.map +1 -0
  514. package/dist/mapFile.js +176 -0
  515. package/dist/mapFile.js.map +1 -0
  516. package/dist/mapMeasure.d.ts +8 -0
  517. package/dist/mapMeasure.js +283 -0
  518. package/dist/mapMeasure.js.map +1 -0
  519. package/dist/mapMerge.d.ts +1 -0
  520. package/dist/mapMerge.js +172 -0
  521. package/dist/mapMerge.js.map +1 -0
  522. package/dist/mapObjectives.js +138 -0
  523. package/dist/mapObjectives.js.map +1 -0
  524. package/dist/mapObjects.js +80 -0
  525. package/dist/mapObjects.js.map +1 -0
  526. package/dist/math.d.ts +37 -7
  527. package/dist/math.js +155 -0
  528. package/dist/math.js.map +1 -0
  529. package/dist/messages.d.ts +71 -4
  530. package/dist/messages.js +29 -0
  531. package/dist/messages.js.map +1 -0
  532. package/dist/missionRules.d.ts +10 -2
  533. package/dist/{missionRules-C-bGxm0Q.js → missionRules.js} +30 -150
  534. package/dist/missionRules.js.map +1 -0
  535. package/dist/mods.d.ts +39 -20
  536. package/dist/mods.js +271 -0
  537. package/dist/mods.js.map +1 -0
  538. package/dist/moves.d.ts +87 -0
  539. package/dist/moves.js +539 -0
  540. package/dist/moves.js.map +1 -0
  541. package/dist/names.d.ts +7 -0
  542. package/dist/names.js +122 -0
  543. package/dist/names.js.map +1 -0
  544. package/dist/navigation/agentParams.js +14 -0
  545. package/dist/navigation/agentParams.js.map +1 -0
  546. package/dist/navigation/air.d.ts +7 -3
  547. package/dist/navigation/air.js +401 -0
  548. package/dist/navigation/air.js.map +1 -0
  549. package/dist/navigation/builds.d.ts +34 -2
  550. package/dist/navigation/builds.js +287 -0
  551. package/dist/navigation/builds.js.map +1 -0
  552. package/dist/navigation/groundAreas.d.ts +59 -1
  553. package/dist/navigation/groundAreas.js +407 -0
  554. package/dist/navigation/groundAreas.js.map +1 -0
  555. package/dist/navigation/navigation.d.ts +98 -9
  556. package/dist/navigation/recast.d.ts +194 -18
  557. package/dist/navigation/recast.js +1379 -0
  558. package/dist/navigation/recast.js.map +1 -0
  559. package/dist/navigation/sidePaths.d.ts +8 -3
  560. package/dist/navigation/sidePaths.js +241 -0
  561. package/dist/navigation/sidePaths.js.map +1 -0
  562. package/dist/navigation/sized.js +243 -0
  563. package/dist/navigation/sized.js.map +1 -0
  564. package/dist/nearest.js +32 -0
  565. package/dist/nearest.js.map +1 -0
  566. package/dist/noise.js +59 -0
  567. package/dist/noise.js.map +1 -0
  568. package/dist/objectives.d.ts +12 -3
  569. package/dist/objectives.js +144 -0
  570. package/dist/objectives.js.map +1 -0
  571. package/dist/orders/basic.d.ts +5 -5
  572. package/dist/orders/basic.js +417 -0
  573. package/dist/orders/basic.js.map +1 -0
  574. package/dist/orders/build.js +278 -0
  575. package/dist/orders/build.js.map +1 -0
  576. package/dist/orders/cast.d.ts +13 -3
  577. package/dist/orders/cast.js +558 -0
  578. package/dist/orders/cast.js.map +1 -0
  579. package/dist/orders/facts.js +16 -0
  580. package/dist/orders/facts.js.map +1 -0
  581. package/dist/orders/harvest.d.ts +21 -5
  582. package/dist/orders/harvest.js +540 -0
  583. package/dist/orders/harvest.js.map +1 -0
  584. package/dist/orders/idle.d.ts +3 -1
  585. package/dist/orders/idle.js +234 -0
  586. package/dist/orders/idle.js.map +1 -0
  587. package/dist/orders/items.js +92 -0
  588. package/dist/orders/items.js.map +1 -0
  589. package/dist/orders/queue.js +108 -0
  590. package/dist/orders/queue.js.map +1 -0
  591. package/dist/orders/waiting.d.ts +39 -0
  592. package/dist/orders/waiting.js +149 -0
  593. package/dist/orders/waiting.js.map +1 -0
  594. package/dist/pack.schema.js +13 -0
  595. package/dist/pack.schema.js.map +1 -0
  596. package/dist/pack.schema.json +7622 -841
  597. package/dist/packs/director/index.d.ts +13 -5
  598. package/dist/packs/director/index.js +204 -0
  599. package/dist/packs/director/index.js.map +1 -0
  600. package/dist/packs/heroes/campaign.d.ts +3 -2
  601. package/dist/packs/heroes/campaign.js +241 -0
  602. package/dist/packs/heroes/campaign.js.map +1 -0
  603. package/dist/packs/heroes/carry.d.ts +6 -0
  604. package/dist/packs/heroes/carry.js +112 -0
  605. package/dist/packs/heroes/carry.js.map +1 -0
  606. package/dist/packs/heroes/commands.js +115 -0
  607. package/dist/packs/heroes/commands.js.map +1 -0
  608. package/dist/packs/heroes/fallen.d.ts +43 -0
  609. package/dist/packs/heroes/fallen.js +61 -0
  610. package/dist/packs/heroes/fallen.js.map +1 -0
  611. package/dist/packs/heroes/hire.js +60 -0
  612. package/dist/packs/heroes/hire.js.map +1 -0
  613. package/dist/packs/heroes/index.d.ts +7 -6
  614. package/dist/packs/heroes/index.js +130 -0
  615. package/dist/packs/heroes/index.js.map +1 -0
  616. package/dist/packs/heroes/loop.d.ts +95 -0
  617. package/dist/packs/heroes/loop.js +250 -0
  618. package/dist/packs/heroes/loop.js.map +1 -0
  619. package/dist/packs/heroes/making.d.ts +6 -3
  620. package/dist/packs/heroes/making.js +55 -0
  621. package/dist/packs/heroes/making.js.map +1 -0
  622. package/dist/packs/heroes/respawn.d.ts +3 -3
  623. package/dist/packs/heroes/respawn.js +87 -0
  624. package/dist/packs/heroes/respawn.js.map +1 -0
  625. package/dist/packs/heroes/sets.d.ts +32 -0
  626. package/dist/packs/heroes/sets.js +51 -0
  627. package/dist/packs/heroes/sets.js.map +1 -0
  628. package/dist/packs/heroes/spells.d.ts +16 -0
  629. package/dist/packs/heroes/spells.js +269 -0
  630. package/dist/packs/heroes/spells.js.map +1 -0
  631. package/dist/packs/items/defaults.d.ts +43 -0
  632. package/dist/packs/items/defaults.js +1504 -0
  633. package/dist/packs/items/defaults.js.map +1 -0
  634. package/dist/packs/items/index.d.ts +27 -0
  635. package/dist/packs/items/index.js +214 -0
  636. package/dist/packs/items/index.js.map +1 -0
  637. package/dist/packs/moba/index.d.ts +3 -3
  638. package/dist/packs/moba/index.js +174 -0
  639. package/dist/packs/moba/index.js.map +1 -0
  640. package/dist/packs/pack.d.ts +15 -15
  641. package/dist/packs/pack.js +14 -0
  642. package/dist/packs/pack.js.map +1 -0
  643. package/dist/packs.d.ts +15 -7
  644. package/dist/packs.js +222 -0
  645. package/dist/packs.js.map +1 -0
  646. package/dist/paths.d.ts +2 -0
  647. package/dist/paths.js +109 -0
  648. package/dist/paths.js.map +1 -0
  649. package/dist/plain.js +57 -0
  650. package/dist/plain.js.map +1 -0
  651. package/dist/player.d.ts +33 -10
  652. package/dist/player.js +159 -0
  653. package/dist/player.js.map +1 -0
  654. package/dist/portals.d.ts +1 -1
  655. package/dist/portals.js +194 -0
  656. package/dist/portals.js.map +1 -0
  657. package/dist/prefabs.d.ts +25 -2
  658. package/dist/prefabs.js +239 -0
  659. package/dist/prefabs.js.map +1 -0
  660. package/dist/presetBuildings.js +58 -0
  661. package/dist/presetBuildings.js.map +1 -0
  662. package/dist/presetFoliage.d.ts +27 -0
  663. package/dist/presetFoliage.js +98 -0
  664. package/dist/presetFoliage.js.map +1 -0
  665. package/dist/presetGround.js +65 -0
  666. package/dist/presetGround.js.map +1 -0
  667. package/dist/proxies.d.ts +12 -0
  668. package/dist/proxies.js +79 -0
  669. package/dist/proxies.js.map +1 -0
  670. package/dist/query.d.ts +56 -0
  671. package/dist/query.js +88 -0
  672. package/dist/query.js.map +1 -0
  673. package/dist/races.d.ts +15 -14
  674. package/dist/races.js +172 -0
  675. package/dist/races.js.map +1 -0
  676. package/dist/randomGroups.js +91 -0
  677. package/dist/randomGroups.js.map +1 -0
  678. package/dist/registry.d.ts +117 -53
  679. package/dist/registry.js +323 -0
  680. package/dist/registry.js.map +1 -0
  681. package/dist/remains.d.ts +11 -9
  682. package/dist/remains.js +188 -0
  683. package/dist/remains.js.map +1 -0
  684. package/dist/replication.d.ts +12 -7
  685. package/dist/replication.js +100 -0
  686. package/dist/replication.js.map +1 -0
  687. package/dist/rng.d.ts +2 -0
  688. package/dist/rng.js +40 -0
  689. package/dist/rng.js.map +1 -0
  690. package/dist/rules.d.ts +186 -99
  691. package/dist/rules.js +179 -0
  692. package/dist/rules.js.map +1 -0
  693. package/dist/rulesCheck.d.ts +5 -4
  694. package/dist/rulesCheck.js +693 -0
  695. package/dist/rulesCheck.js.map +1 -0
  696. package/dist/runes.d.ts +2 -2
  697. package/dist/runes.js +80 -0
  698. package/dist/runes.js.map +1 -0
  699. package/dist/save.d.ts +37 -12
  700. package/dist/save.js +532 -0
  701. package/dist/save.js.map +1 -0
  702. package/dist/scenario.d.ts +2 -2
  703. package/dist/scenario.js +99 -0
  704. package/dist/scenario.js.map +1 -0
  705. package/dist/scheduler.d.ts +3 -0
  706. package/dist/scheduler.js +156 -0
  707. package/dist/scheduler.js.map +1 -0
  708. package/dist/score.d.ts +19 -19
  709. package/dist/score.js +709 -0
  710. package/dist/score.js.map +1 -0
  711. package/dist/sequences.d.ts +10 -6
  712. package/dist/sequences.js +206 -0
  713. package/dist/sequences.js.map +1 -0
  714. package/dist/server/doorman.js +154 -0
  715. package/dist/server/doorman.js.map +1 -0
  716. package/dist/server/gameServer.d.ts +16 -1
  717. package/dist/server/gameServer.js +643 -0
  718. package/dist/server/gameServer.js.map +1 -0
  719. package/dist/server/index.d.ts +1 -1
  720. package/dist/server/lobby.js +199 -0
  721. package/dist/server/lobby.js.map +1 -0
  722. package/dist/server/log.js +18 -0
  723. package/dist/server/log.js.map +1 -0
  724. package/dist/server/match.js +267 -0
  725. package/dist/server/match.js.map +1 -0
  726. package/dist/server/mode.d.ts +18 -9
  727. package/dist/server/mode.js +220 -0
  728. package/dist/server/mode.js.map +1 -0
  729. package/dist/{navigation-worker.js → server/navigation-worker.js} +1 -1
  730. package/dist/server/navigation-worker.js.map +1 -0
  731. package/dist/server/navigation.js +39 -0
  732. package/dist/server/navigation.js.map +1 -0
  733. package/dist/server/ops.d.ts +4 -0
  734. package/dist/server/ops.js +137 -0
  735. package/dist/server/ops.js.map +1 -0
  736. package/dist/server/packs.d.ts +3 -3
  737. package/dist/server/packs.js +32 -0
  738. package/dist/server/packs.js.map +1 -0
  739. package/dist/server/ratings.d.ts +5 -0
  740. package/dist/server/ratings.js +104 -0
  741. package/dist/server/ratings.js.map +1 -0
  742. package/dist/server/relay.d.ts +12 -2
  743. package/dist/server/relay.js +144 -0
  744. package/dist/server/relay.js.map +1 -0
  745. package/dist/server/rooms.d.ts +9 -2
  746. package/dist/server/rooms.js +442 -0
  747. package/dist/server/rooms.js.map +1 -0
  748. package/dist/server/seat.js +116 -0
  749. package/dist/server/seat.js.map +1 -0
  750. package/dist/server/seatSettings.d.ts +3 -3
  751. package/dist/server/seatSettings.js +63 -0
  752. package/dist/server/seatSettings.js.map +1 -0
  753. package/dist/server/secret.js +13 -0
  754. package/dist/server/secret.js.map +1 -0
  755. package/dist/server/start.d.ts +13 -6
  756. package/dist/server/start.js +76 -0
  757. package/dist/server/start.js.map +1 -0
  758. package/dist/server/websocket.d.ts +9 -1
  759. package/dist/server/websocket.js +306 -0
  760. package/dist/server/websocket.js.map +1 -0
  761. package/dist/server.js +15 -2861
  762. package/dist/session/can.js +26 -0
  763. package/dist/session/can.js.map +1 -0
  764. package/dist/session/commandReplay.d.ts +8 -2
  765. package/dist/session/commandReplay.js +293 -0
  766. package/dist/session/commandReplay.js.map +1 -0
  767. package/dist/session/debug.js +151 -0
  768. package/dist/session/debug.js.map +1 -0
  769. package/dist/session/delay.js +62 -0
  770. package/dist/session/delay.js.map +1 -0
  771. package/dist/session/delta.d.ts +14 -1
  772. package/dist/session/delta.js +407 -0
  773. package/dist/session/delta.js.map +1 -0
  774. package/dist/session/entityState.js +415 -0
  775. package/dist/session/entityState.js.map +1 -0
  776. package/dist/session/local.d.ts +47 -5
  777. package/dist/session/local.js +670 -0
  778. package/dist/session/local.js.map +1 -0
  779. package/dist/session/memory.d.ts +20 -2
  780. package/dist/session/memory.js +131 -0
  781. package/dist/session/memory.js.map +1 -0
  782. package/dist/session/protocol.d.ts +325 -31
  783. package/dist/session/protocol.js +55 -0
  784. package/dist/session/protocol.js.map +1 -0
  785. package/dist/session/remote.d.ts +74 -12
  786. package/dist/session/remote.js +1394 -0
  787. package/dist/session/remote.js.map +1 -0
  788. package/dist/session/replay.d.ts +11 -2
  789. package/dist/session/replay.js +160 -0
  790. package/dist/session/replay.js.map +1 -0
  791. package/dist/session/seed.js +12 -0
  792. package/dist/session/seed.js.map +1 -0
  793. package/dist/session/share.d.ts +5 -1
  794. package/dist/session/share.js +94 -0
  795. package/dist/session/share.js.map +1 -0
  796. package/dist/session/socket.d.ts +1 -1
  797. package/dist/session/socket.js +29 -0
  798. package/dist/session/socket.js.map +1 -0
  799. package/dist/session/wire.d.ts +5 -0
  800. package/dist/session/wire.js +84 -0
  801. package/dist/session/wire.js.map +1 -0
  802. package/dist/session/worker.d.ts +77 -12
  803. package/dist/session/worker.js +499 -0
  804. package/dist/session/worker.js.map +1 -0
  805. package/dist/shared.d.ts +31 -5
  806. package/dist/shared.js +166 -0
  807. package/dist/shared.js.map +1 -0
  808. package/dist/sides.d.ts +9 -3
  809. package/dist/sides.js +149 -0
  810. package/dist/sides.js.map +1 -0
  811. package/dist/sight.js +85 -0
  812. package/dist/sight.js.map +1 -0
  813. package/dist/simulate-worker.js +1 -1
  814. package/dist/simulate.d.ts +12 -8
  815. package/dist/{simulate-oXBiw1Ff.js → simulate.js} +10 -11
  816. package/dist/simulate.js.map +1 -0
  817. package/dist/smart.js +77 -0
  818. package/dist/smart.js.map +1 -0
  819. package/dist/spatial.d.ts +32 -16
  820. package/dist/spatial.js +234 -0
  821. package/dist/spatial.js.map +1 -0
  822. package/dist/spawning.d.ts +1 -0
  823. package/dist/spawning.js +224 -0
  824. package/dist/spawning.js.map +1 -0
  825. package/dist/stances.d.ts +6 -3
  826. package/dist/stances.js +169 -0
  827. package/dist/stances.js.map +1 -0
  828. package/dist/start.d.ts +10 -10
  829. package/dist/start.js +75 -0
  830. package/dist/start.js.map +1 -0
  831. package/dist/stats.d.ts +42 -16
  832. package/dist/stats.js +290 -0
  833. package/dist/stats.js.map +1 -0
  834. package/dist/summoned.d.ts +52 -0
  835. package/dist/summoned.js +38 -0
  836. package/dist/summoned.js.map +1 -0
  837. package/dist/summons.d.ts +10 -13
  838. package/dist/summons.js +271 -0
  839. package/dist/summons.js.map +1 -0
  840. package/dist/systems/abilities.js +224 -0
  841. package/dist/systems/abilities.js.map +1 -0
  842. package/dist/systems/combat.d.ts +35 -1
  843. package/dist/systems/combat.js +677 -0
  844. package/dist/systems/combat.js.map +1 -0
  845. package/dist/systems/combatTold.d.ts +3 -1
  846. package/dist/systems/combatTold.js +85 -0
  847. package/dist/systems/combatTold.js.map +1 -0
  848. package/dist/systems/construction.js +80 -0
  849. package/dist/systems/construction.js.map +1 -0
  850. package/dist/systems/economy.d.ts +0 -6
  851. package/dist/systems/economy.js +128 -0
  852. package/dist/systems/economy.js.map +1 -0
  853. package/dist/systems/fog.d.ts +1 -1
  854. package/dist/systems/fog.js +120 -0
  855. package/dist/systems/fog.js.map +1 -0
  856. package/dist/systems/life.js +32 -0
  857. package/dist/systems/life.js.map +1 -0
  858. package/dist/systems/movement.d.ts +24 -12
  859. package/dist/systems/movement.js +1247 -0
  860. package/dist/systems/movement.js.map +1 -0
  861. package/dist/systems/orders.js +64 -0
  862. package/dist/systems/orders.js.map +1 -0
  863. package/dist/systems/production.js +322 -0
  864. package/dist/systems/production.js.map +1 -0
  865. package/dist/systems/productionQueue.js +120 -0
  866. package/dist/systems/productionQueue.js.map +1 -0
  867. package/dist/systems/victory.d.ts +1 -1
  868. package/dist/systems/victory.js +56 -0
  869. package/dist/systems/victory.js.map +1 -0
  870. package/dist/talk.d.ts +6 -6
  871. package/dist/talk.js +153 -0
  872. package/dist/talk.js.map +1 -0
  873. package/dist/targeting.d.ts +142 -0
  874. package/dist/targeting.js +49 -0
  875. package/dist/targeting.js.map +1 -0
  876. package/dist/tech.d.ts +20 -3
  877. package/dist/tech.js +239 -0
  878. package/dist/tech.js.map +1 -0
  879. package/dist/techTree.d.ts +7 -0
  880. package/dist/techTree.js +90 -0
  881. package/dist/techTree.js.map +1 -0
  882. package/dist/terrain.d.ts +59 -7
  883. package/dist/terrain.js +389 -0
  884. package/dist/terrain.js.map +1 -0
  885. package/dist/terrainSave.d.ts +6 -0
  886. package/dist/terrainSave.js +74 -0
  887. package/dist/terrainSave.js.map +1 -0
  888. package/dist/testing.d.ts +8 -7
  889. package/dist/testing.js +13 -739
  890. package/dist/testing.js.map +1 -1
  891. package/dist/tiles.d.ts +1 -1
  892. package/dist/tiles.js +43 -0
  893. package/dist/tiles.js.map +1 -0
  894. package/dist/timers.d.ts +29 -4
  895. package/dist/timers.js +242 -0
  896. package/dist/timers.js.map +1 -0
  897. package/dist/tomes.d.ts +4 -4
  898. package/dist/tomes.js +94 -0
  899. package/dist/tomes.js.map +1 -0
  900. package/dist/trade.js +103 -0
  901. package/dist/trade.js.map +1 -0
  902. package/dist/transport.d.ts +6 -1
  903. package/dist/transport.js +281 -0
  904. package/dist/transport.js.map +1 -0
  905. package/dist/tunables.d.ts +10 -3
  906. package/dist/tunables.js +56 -0
  907. package/dist/tunables.js.map +1 -0
  908. package/dist/unitResources.d.ts +67 -0
  909. package/dist/unitResources.js +266 -0
  910. package/dist/unitResources.js.map +1 -0
  911. package/dist/upkeep.d.ts +6 -1
  912. package/dist/upkeep.js +26 -0
  913. package/dist/upkeep.js.map +1 -0
  914. package/dist/veterancy.d.ts +8 -3
  915. package/dist/veterancy.js +131 -0
  916. package/dist/veterancy.js.map +1 -0
  917. package/dist/vision.d.ts +36 -0
  918. package/dist/vision.js +133 -0
  919. package/dist/vision.js.map +1 -0
  920. package/dist/walls.d.ts +1 -1
  921. package/dist/walls.js +278 -0
  922. package/dist/walls.js.map +1 -0
  923. package/dist/world.d.ts +606 -88
  924. package/dist/world.js +1263 -0
  925. package/dist/world.js.map +1 -0
  926. package/package.json +2 -2
  927. package/dist/ai.js.map +0 -1
  928. package/dist/attributes.d.ts +0 -66
  929. package/dist/brain-BvVdUhX8.js +0 -7659
  930. package/dist/brain-BvVdUhX8.js.map +0 -1
  931. package/dist/builds-C6LfgvEU.js +0 -460
  932. package/dist/builds-C6LfgvEU.js.map +0 -1
  933. package/dist/coreComponents-syuh2fPG.js +0 -5149
  934. package/dist/coreComponents-syuh2fPG.js.map +0 -1
  935. package/dist/debugCommands-CzjrSm66.js +0 -14739
  936. package/dist/debugCommands-CzjrSm66.js.map +0 -1
  937. package/dist/determinism-BCymQwiE.js +0 -518
  938. package/dist/determinism-BCymQwiE.js.map +0 -1
  939. package/dist/game-DiJEN-Ks.js +0 -5800
  940. package/dist/game-DiJEN-Ks.js.map +0 -1
  941. package/dist/index.js.map +0 -1
  942. package/dist/inspect-D9dWHmZ0.js.map +0 -1
  943. package/dist/local-Dkovq42k.js +0 -1379
  944. package/dist/local-Dkovq42k.js.map +0 -1
  945. package/dist/missionRules-C-bGxm0Q.js.map +0 -1
  946. package/dist/navigation-worker.js.map +0 -1
  947. package/dist/packs-g5thvmGn.js +0 -3199
  948. package/dist/packs-g5thvmGn.js.map +0 -1
  949. package/dist/profiles-B3NS9jwk.js.map +0 -1
  950. package/dist/server.js.map +0 -1
  951. package/dist/simulate-oXBiw1Ff.js.map +0 -1
@@ -0,0 +1,1394 @@
1
+ import { footprintOf } from "../defs.js";
2
+ import { worldFailed } from "../engineEvents.js";
3
+ import { toMessage } from "../messages.js";
4
+ import { hasGroundSpeeds, navigationSpeedOn } from "../groundSpeed.js";
5
+ import { groundKnownTo } from "../cellLayers.js";
6
+ import { formationPreview } from "../formation.js";
7
+ import { BuildGrid } from "../grid.js";
8
+ import { placementCells, siteOf } from "../orders/build.js";
9
+ import { errorFields } from "../log.js";
10
+ import { mergeValues, redefineIn, redefinitions, restoreRedefinitions } from "../gameData.js";
11
+ import { loadTerrain, saveTerrain } from "../terrainSave.js";
12
+ import { MissingGround, applyGroundChanges, applyTerrainPatch, groundOf, isGroundChanges, savedGround, terrainPatchProblem } from "../ground.js";
13
+ import { RecastNavigation } from "../navigation/recast.js";
14
+ import { AirNavigation } from "../navigation/air.js";
15
+ import { createRegistry } from "../game.js";
16
+ import { isServerMessage, readHostMessage } from "./wire.js";
17
+ import { isFiniteNumber, protocolMismatch, readMessage } from "./protocol.js";
18
+ import { apply, bytesByKey, diff, quantize } from "./delta.js";
19
+ import { LocalDebug, RemoteDebug, askDebug } from "./debug.js";
20
+ import { LocalSession, endSharedCaptures, shareCaptures } from "./local.js";
21
+ //#region src/session/remote.ts
22
+ /**
23
+ * Two ends of a connection in the page, `[client, host]`: everything sent is text, delivered after the latency the
24
+ * options give. The whole networked way, in one page and in tests
25
+ *
26
+ * @beta
27
+ */
28
+ function loopback(options = {}) {
29
+ const { latency = 0, jitter = 0, loss = 0, random = Math.random } = options;
30
+ /** One end: what it is handed to deliver, and the transport its side holds */
31
+ class End {
32
+ lossy;
33
+ peer;
34
+ bytesSent = 0;
35
+ messagesSent = 0;
36
+ handler = () => {};
37
+ closed = () => {};
38
+ open = true;
39
+ /** When the last message sent is due: none overtakes the one before */
40
+ last = 0;
41
+ constructor(lossy) {
42
+ this.lossy = lossy;
43
+ }
44
+ send(message) {
45
+ if (!this.open) return;
46
+ this.bytesSent += message.length;
47
+ this.messagesSent++;
48
+ if (this.lossy && loss > 0 && message.startsWith("{\"type\":\"delta\"") && random() < loss) return;
49
+ const due = Math.max(performance.now() + latency + random() * jitter, this.last);
50
+ this.last = due;
51
+ const { peer } = this;
52
+ setTimeout(() => peer.deliver(message), Math.max(due - performance.now(), 0));
53
+ }
54
+ deliver(message) {
55
+ if (this.open) this.handler(message);
56
+ }
57
+ onMessage(handler) {
58
+ this.handler = handler;
59
+ }
60
+ onClose(handler) {
61
+ this.closed = handler;
62
+ }
63
+ close() {
64
+ this.shut();
65
+ const { peer } = this;
66
+ setTimeout(() => peer.shut(), Math.max(this.last - performance.now(), latency, 0));
67
+ }
68
+ shut() {
69
+ if (!this.open) return;
70
+ this.open = false;
71
+ this.closed();
72
+ }
73
+ }
74
+ const client = new End(false);
75
+ const host = new End(true);
76
+ client.peer = host;
77
+ host.peer = client;
78
+ return [client, host];
79
+ }
80
+ /** Whether what a player sent as a command is one to look at: an object with a type. Its fields are its definition's to check */
81
+ var isCommand = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.type === "string";
82
+ /**
83
+ * Runs of equal values: how many 0s, then how many 1s, and so on
84
+ *
85
+ * @internal
86
+ */
87
+ function toRuns(cells) {
88
+ const runs = [];
89
+ let value = 0;
90
+ let count = 0;
91
+ for (let i = 0; i < cells.length; i++) {
92
+ const cell = cells[i] ? 1 : 0;
93
+ if (cell === value) count++;
94
+ else {
95
+ runs.push(count);
96
+ value = cell;
97
+ count = 1;
98
+ }
99
+ }
100
+ runs.push(count);
101
+ return runs;
102
+ }
103
+ /**
104
+ * Cells back from `toRuns`, into `out`
105
+ *
106
+ * @internal
107
+ */
108
+ function fromRuns(runs, out) {
109
+ let at = 0;
110
+ let value = 0;
111
+ for (const run of runs) {
112
+ out.fill(value, at, Math.min(at + run, out.length));
113
+ at += run;
114
+ value ^= 1;
115
+ }
116
+ return out;
117
+ }
118
+ /** The fog for the wire: nothing of its cells when the whole map is lit, which they say nothing about then */
119
+ var fogMessage = (fog) => fog.revealed ? {
120
+ revealed: true,
121
+ visible: [],
122
+ explored: []
123
+ } : {
124
+ revealed: false,
125
+ visible: toRuns(fog.visible),
126
+ explored: toRuns(fog.explored)
127
+ };
128
+ /** The runs of a team's fog, by its cells, as they were at a version of the fog: the seats of a team share them */
129
+ var fogRuns = /* @__PURE__ */ new WeakMap();
130
+ var revealedFog = {
131
+ revealed: true,
132
+ visible: [],
133
+ explored: []
134
+ };
135
+ /** The fog for the wire, its runs made once for every seat of a team while it stays as it is */
136
+ function fogMessageOf(fog) {
137
+ if (fog.revealed) return revealedFog;
138
+ const known = fogRuns.get(fog.visible);
139
+ if (known && known.version === fog.version) return known.message;
140
+ const message = fogMessage(fog);
141
+ fogRuns.set(fog.visible, {
142
+ version: fog.version,
143
+ message
144
+ });
145
+ return message;
146
+ }
147
+ /**
148
+ * What each state told was rounded to (`quantize`), by the very object: a state that did not change is the object it
149
+ * was (`LocalSession` hands back what it told while it still says the truth), so it is rounded once and stays the same
150
+ * object round after round, which the diff then passes over without looking inside (`diff`)
151
+ */
152
+ var quantizedStates = /* @__PURE__ */ new WeakMap();
153
+ function quantizedOf(state) {
154
+ let made = quantizedStates.get(state);
155
+ if (!made) quantizedStates.set(state, made = quantize(state));
156
+ return made;
157
+ }
158
+ /**
159
+ * The entities of a frame as the wire has them (`quantize`), one list between the seats of a round told the very same
160
+ * (the seats of a side, the observers: what they are told of an entity is one object between them, `LocalSession`), so
161
+ * that it is rounded once and a diff of the same two lists is worked out once (`diff`). `made` is this round's so far
162
+ */
163
+ function quantizedList(entities, made) {
164
+ for (const { told, sent } of made) {
165
+ if (told.length !== entities.length) continue;
166
+ let alike = true;
167
+ for (let i = 0; i < told.length; i++) if (told[i] !== entities[i]) {
168
+ alike = false;
169
+ break;
170
+ }
171
+ if (alike) return sent;
172
+ }
173
+ const sent = entities.map(quantizedOf);
174
+ made.push({
175
+ told: entities,
176
+ sent
177
+ });
178
+ return sent;
179
+ }
180
+ /** Milliseconds between two pings, to measure the time to the host and back */
181
+ var PING_EVERY = 2e3;
182
+ /** Seconds of jitter the interpolation buffer makes room for, at most */
183
+ var MAX_JITTER = .2;
184
+ /**
185
+ * Seconds with no snapshot after which the host is taken to have gone quiet, at the least (three of its usual gaps
186
+ * between two where they are longer), as it does while its world stands still (a replay held, a game paused): the
187
+ * screen then comes to the newest snapshot it has, there being nothing to make room for
188
+ */
189
+ var QUIET = .5;
190
+ var emptyTiming = (since, byKey = false) => ({
191
+ since,
192
+ ticks: 0,
193
+ tickTime: 0,
194
+ tickMax: 0,
195
+ sends: 0,
196
+ sendTime: 0,
197
+ sendMax: 0,
198
+ parts: {
199
+ capture: 0,
200
+ quantize: 0,
201
+ fog: 0,
202
+ diff: 0,
203
+ stringify: 0
204
+ },
205
+ bytes: 0,
206
+ ...byKey && { keys: {} }
207
+ });
208
+ /** Frames kept on either side, at most: more than a second and a half of ticks a player has not said it got */
209
+ var KEPT_FRAMES = 64;
210
+ /**
211
+ * Bytes of the frames kept for one player, at most (`SessionHostOptions.keptBytes`): 8 MB, some thirty frames of a
212
+ * thousand units (a frame of them is about 250 KB). A player who has said nothing for longer is sent everything again
213
+ */
214
+ var KEPT_BYTES = 8388608;
215
+ /** What each list of entities a frame keeps takes as the wire writes it: one list between the seats of a side (`quantizedList`) */
216
+ var listBytes = /* @__PURE__ */ new WeakMap();
217
+ /** Entities of a list written out to tell what the list takes: the rest are taken to be as big */
218
+ var SAMPLED = 8;
219
+ /**
220
+ * What a frame kept for a player takes, about: its entities as the wire writes them (some of them written out, the rest
221
+ * taken to be as big: writing out all of a thousand units' at every send costs more than the send itself), its fog,
222
+ * its players
223
+ */
224
+ function frameBytes(frame) {
225
+ const { entities, players } = frame.snapshot;
226
+ let bytes = listBytes.get(entities);
227
+ if (bytes === void 0) {
228
+ const sampled = Math.min(entities.length, SAMPLED);
229
+ let written = 0;
230
+ for (let i = 0; i < sampled; i++) written += JSON.stringify(entities[Math.floor(i * entities.length / sampled)]).length;
231
+ listBytes.set(entities, bytes = sampled ? Math.round(written / sampled * entities.length) : 0);
232
+ }
233
+ let fog = listBytes.get(frame.fog);
234
+ if (fog === void 0) listBytes.set(frame.fog, fog = JSON.stringify(frame.fog).length);
235
+ let told = listBytes.get(players);
236
+ if (told === void 0) listBytes.set(players, told = JSON.stringify(players).length);
237
+ return bytes + fog + told;
238
+ }
239
+ /**
240
+ * Snapshots waiting for the screen, at most (`RemoteSession.update`): three seconds of them at 20 a second. A page
241
+ * whose screen stops asking (a tab in the background) folds the oldest into the next, their events kept, rather than
242
+ * keeping every one for as long as it is away
243
+ */
244
+ var KEPT_SNAPSHOTS = 64;
245
+ /** Events the folded snapshots carry together, at most: the newest kept. What is the screen's only (the state is in the snapshot) */
246
+ var KEPT_SCREEN_EVENTS = 2e3;
247
+ /**
248
+ * Runs a world for players connected to it over transports: the server's job, done anywhere. It steps the world by
249
+ * the clock (`start`) or by hand (`update`), and at most `sendRate` times a second sends every player what changed in
250
+ * what they may know (`Delta`), as their `LocalSession` seat sees it: against the last tick they said they got, with
251
+ * the events they have not. Their commands come in as they arrive, and go in at the next tick
252
+ *
253
+ * @beta
254
+ */
255
+ var SessionHost = class {
256
+ world;
257
+ seats = /* @__PURE__ */ new Set();
258
+ accumulator = 0;
259
+ sinceSent = Infinity;
260
+ timer;
261
+ last = 0;
262
+ sendEvery;
263
+ /** Simulation speed multiplier, 0 pauses */
264
+ speed = 1;
265
+ constructor(world, options = {}) {
266
+ this.world = world;
267
+ this.sendEvery = 1 / (options.sendRate ?? 20);
268
+ this.maxTicks = options.maxTicksPerUpdate ?? 8;
269
+ this.onSlowTick = options.onSlowTick;
270
+ this.ownsWorld = options.ownsWorld ?? false;
271
+ this.dropSilentAfter = options.dropSilentAfter ?? 15;
272
+ this.keptEvents = options.keptEvents ?? 600;
273
+ this.keptFrames = Math.max(2, options.keptFrames ?? KEPT_FRAMES);
274
+ this.keptBytes = Math.max(1, options.keptBytes ?? KEPT_BYTES);
275
+ this.groundPart = Math.max(1, options.groundPart ?? GROUND_PART);
276
+ this.byKey = options.bytesByKey ?? false;
277
+ this.timing = emptyTiming(performance.now(), this.byKey);
278
+ this.onError = options.onError;
279
+ this.stopFailed = world.events.on(worldFailed, (failure) => {
280
+ for (const seat of this.seats) this.post(seat, {
281
+ type: "failed",
282
+ message: failure.message
283
+ });
284
+ });
285
+ }
286
+ onError;
287
+ stopFailed;
288
+ dropSilentAfter;
289
+ keptFrames;
290
+ keptBytes;
291
+ groundPart;
292
+ keptEvents;
293
+ /** Whether the characters sent are counted by what they carry (`bytesByKey`) */
294
+ byKey;
295
+ ownsWorld;
296
+ maxTicks;
297
+ onSlowTick;
298
+ /**
299
+ * Seats a player at the world, on the host's end of a transport. The welcome goes out at once: everything the player
300
+ * may know, also to one who comes back. `readOnly` for who only watches: their commands go nowhere but their lines
301
+ * of chat and their pings, which go to who watches alone (`observers`, said by `name`); and with `observer` they see
302
+ * everything, from `player`'s side. `allow` decides on each command before it goes in: a limit of how many, a game
303
+ * paused. One it lets go is answered, refused (the `command` event of its `seq`): with what it gives for why, or
304
+ * `cannotDoThat` for `false`. `inOrder` for a transport that loses nothing and keeps the order (a worker's messages):
305
+ * each frame is the base of the next once it went, with no answer waited for, so the player always gets what changed
306
+ * since the frame it has, and takes it in without looking over the rest
307
+ */
308
+ connect(player, transport, options = {}) {
309
+ const session = new LocalSession(this.world, player, { observer: options.observer });
310
+ const seat = {
311
+ transport,
312
+ session,
313
+ frames: /* @__PURE__ */ new Map(),
314
+ frameSizes: /* @__PURE__ */ new Map(),
315
+ keptBytes: 0,
316
+ acked: -1,
317
+ heardUpTo: -1,
318
+ events: [],
319
+ eventsMade: 0,
320
+ sentAt: /* @__PURE__ */ new Map(),
321
+ roundTrip: 100,
322
+ heard: this.world.tick,
323
+ answers: [],
324
+ groundSent: /* @__PURE__ */ new Set(),
325
+ inOrder: options.inOrder ?? false
326
+ };
327
+ this.seats.add(seat);
328
+ transport.onMessage((text) => {
329
+ const message = readMessage(text);
330
+ if (!message) return;
331
+ if (message.type === "ack") {
332
+ if (isFiniteNumber(message.tick)) this.acknowledge(seat, message.tick, isFiniteNumber(message.events) ? message.events : void 0);
333
+ } else if (message.type === "ping") {
334
+ if (isFiniteNumber(message.at)) this.post(seat, {
335
+ type: "pong",
336
+ at: message.at
337
+ });
338
+ } else if (message.type === "ground") {
339
+ const parts = this.groundParts();
340
+ const { part } = message;
341
+ if (parts && Number.isInteger(part) && part >= 0 && part < parts.length && !seat.groundSent.has(part)) {
342
+ seat.groundSent.add(part);
343
+ this.post(seat, {
344
+ type: "ground",
345
+ part,
346
+ parts: parts.length,
347
+ text: parts[part]
348
+ });
349
+ }
350
+ } else if (message.type === "debug") {
351
+ if (!this.world.debugPlayers.has(player)) return;
352
+ seat.debug ??= {
353
+ view: new LocalDebug(this.world),
354
+ sentAt: -Infinity
355
+ };
356
+ askDebug(seat.debug.view, message);
357
+ seat.debug.sentAt = -Infinity;
358
+ } else if (message.type === "command" && options.readOnly) {
359
+ const { command } = message;
360
+ if (!isCommand(command) || command.type !== "chat" && command.type !== "ping") return;
361
+ session.send({
362
+ ...command,
363
+ to: "observers",
364
+ by: options.name ?? "A watcher"
365
+ });
366
+ this.heardOutside = true;
367
+ } else if (message.type === "command") {
368
+ const allowed = options.allow?.() ?? true;
369
+ const seq = isFiniteNumber(message.seq) ? message.seq : void 0;
370
+ if (!isCommand(message.command)) return;
371
+ if ((message.command.type === "chat" || message.command.type === "ping") && message.command.to === "observers") return;
372
+ if (allowed === true) {
373
+ session.send(message.command, seq);
374
+ if (this.world.registry.command(message.command.type)?.outsideTick) this.heardOutside = true;
375
+ } else if (seq !== void 0) seat.answers.push({
376
+ type: "command",
377
+ seq,
378
+ refusal: allowed ? toMessage(allowed) : { key: "cannotDoThat" }
379
+ });
380
+ }
381
+ });
382
+ transport.onClose(() => this.leave(seat));
383
+ const { registry } = this.world;
384
+ this.post(seat, {
385
+ type: "welcome",
386
+ protocol: 13,
387
+ player,
388
+ tickRate: this.world.tickRate,
389
+ game: registry.game,
390
+ hash: registry.dataHash,
391
+ terrain: savedGround(groundKnownTo(this.world, options.observer ? void 0 : this.world.player(player).team), this.world.ground, this.world.registry.module?.maps, this.world.registry.module ?? {}),
392
+ ...this.world.map.environment && { environment: this.world.map.environment },
393
+ ...this.world.map.doodads.length > 0 && { doodads: [...this.world.map.doodads] },
394
+ ...this.world.map.regions.length > 0 && { regions: [...this.world.map.regions] },
395
+ ...this.world.map.cameras.length > 0 && { cameras: [...this.world.map.cameras] },
396
+ ...this.world.map.paths.length > 0 && { paths: [...this.world.map.paths] },
397
+ ...this.world.states.has(redefinitions) && { redefinitions: structuredClone(this.world.state(redefinitions)) },
398
+ first: this.deltaFor(seat),
399
+ ...options.observer ? { observer: true } : {},
400
+ ...this.world.debugPlayers.has(player) && { debug: true }
401
+ });
402
+ }
403
+ /** The ground the world started as, whole, in parts small enough to go one at a time: made the first time one is asked for */
404
+ groundParts() {
405
+ const base = this.world.ground;
406
+ if (!base) return void 0;
407
+ if (!this.ground) {
408
+ const text = JSON.stringify(saveTerrain(base.terrain));
409
+ this.ground = [];
410
+ for (let i = 0; i < text.length; i += this.groundPart) this.ground.push(text.slice(i, i + this.groundPart));
411
+ }
412
+ return this.ground;
413
+ }
414
+ ground;
415
+ /** The player has the frame of `tick`: what comes next is made against it, and what it has is not sent again */
416
+ acknowledge(seat, tick, events) {
417
+ if (events !== void 0) seat.events = seat.events.filter((sent) => sent.n > events);
418
+ if (tick <= seat.heardUpTo || tick > this.world.tick) return;
419
+ seat.heardUpTo = tick;
420
+ seat.heard = this.world.tick;
421
+ const sent = seat.sentAt.get(tick) ?? (seat.whole?.tick === tick ? seat.whole.at : void 0);
422
+ if (sent !== void 0) seat.roundTrip += (performance.now() - sent - seat.roundTrip) * .2;
423
+ if (seat.whole && tick >= seat.whole.tick) seat.whole = void 0;
424
+ for (const kept of seat.sentAt.keys()) if (kept <= tick) seat.sentAt.delete(kept);
425
+ seat.events = seat.events.filter((sent) => sent.tick > tick);
426
+ if (!seat.frames.has(tick)) return;
427
+ seat.acked = tick;
428
+ for (const kept of [...seat.frames.keys()]) if (kept < tick) this.forget(seat, kept);
429
+ }
430
+ /**
431
+ * Whether a player is sent nothing this round: it has no frame kept to make a delta against, and the whole one it
432
+ * was sent last is on its way still. Another would be as big, and come no sooner than the answer to the first
433
+ */
434
+ holding(seat, now) {
435
+ return !!seat.whole && !seat.frames.has(seat.acked) && now - seat.whole.at <= seat.roundTrip * 1.5 + this.sendEvery * 1e3;
436
+ }
437
+ leave(seat) {
438
+ if (!this.seats.delete(seat)) return;
439
+ seat.session.dispose();
440
+ seat.debug?.view.dispose();
441
+ if (this.seats.size === 0) this.stop();
442
+ }
443
+ /** How many players are connected */
444
+ get players() {
445
+ return this.seats.size;
446
+ }
447
+ /**
448
+ * How much the host keeps for each connected player, for a test of its limits (`keptFrames`, `keptEvents`): the
449
+ * frames it may make a delta against, when each was sent, and the events not yet said to be had
450
+ *
451
+ * @internal
452
+ */
453
+ kept() {
454
+ return [...this.seats].map((seat) => ({
455
+ frames: seat.frames.size,
456
+ bytes: seat.keptBytes,
457
+ sentAt: seat.sentAt.size,
458
+ events: seat.events.length
459
+ }));
460
+ }
461
+ post(seat, message) {
462
+ seat.transport.send(JSON.stringify(message));
463
+ }
464
+ /** Lets `dt` seconds pass: the ticks that fit into it, then what changed to everyone, when it is time to send */
465
+ update(dt) {
466
+ const { world } = this;
467
+ let stepped = false;
468
+ this.accumulator += dt * this.speed * world.cheats.speed;
469
+ if (world.cheats.speed === 0 && this.speed > 0 && world.debugWaiting) this.accumulator += world.dt;
470
+ this.sinceSent += dt;
471
+ let ticks = 0;
472
+ while (this.accumulator >= world.dt) {
473
+ if (ticks++ >= this.maxTicks) {
474
+ this.accumulator = 0;
475
+ break;
476
+ }
477
+ const began = performance.now();
478
+ world.step();
479
+ const took = performance.now() - began;
480
+ const { timing, totals } = this;
481
+ timing.ticks++;
482
+ timing.tickTime += took;
483
+ timing.tickMax = Math.max(timing.tickMax, took);
484
+ totals.ticks++;
485
+ totals.tickTime += took;
486
+ totals.lastTick = took;
487
+ if (took > world.dt * 1e3) this.onSlowTick?.(took, world.tick);
488
+ this.accumulator -= world.dt;
489
+ stepped = true;
490
+ }
491
+ if (stepped || this.heardOutside) this.sendDue();
492
+ }
493
+ /** What the debug tools of a seat follow, as the world stands: when they follow, list or log anything */
494
+ sendDebug(seat, debug, now) {
495
+ debug.sentAt = now;
496
+ const { view } = debug;
497
+ view.refresh();
498
+ if (!view.inspection && !view.world && !view.logging) return;
499
+ this.post(seat, {
500
+ type: "debug",
501
+ inspection: view.inspection,
502
+ world: view.world,
503
+ log: view.logging ? [...view.log()] : []
504
+ });
505
+ }
506
+ /** Moves the game on by `ticks` at the next update, however fast it goes: a step of a held game (`speed` 0) */
507
+ advance(ticks = 1) {
508
+ this.accumulator += this.world.dt * Math.max(0, Math.floor(ticks));
509
+ }
510
+ /**
511
+ * Sends everyone what changed, when it is time to, for a world something else steps: the page's own game, shared with
512
+ * those who watch it (`shareGame`). `dt` is the seconds since the last call. Nothing goes while the world stands still
513
+ */
514
+ publish(dt) {
515
+ this.sinceSent += dt;
516
+ if (this.world.tick !== this.sentTick || this.heardOutside) this.sendDue();
517
+ }
518
+ /** The tick what changed went out at last */
519
+ sentTick = -1;
520
+ /** Talk was carried out since what changed went out last: it goes out with no tick to wait for (RV14) */
521
+ heardOutside = false;
522
+ /** What changed to everyone, when the rate allows */
523
+ sendDue() {
524
+ if (this.sinceSent < this.sendEvery) return;
525
+ this.sentTick = this.world.tick;
526
+ this.heardOutside = false;
527
+ this.sinceSent = Math.min(this.sinceSent - this.sendEvery, this.sendEvery);
528
+ const began = performance.now();
529
+ const silent = this.dropSilentAfter * this.world.tickRate;
530
+ shareCaptures(this.world);
531
+ this.roundEntities = [];
532
+ try {
533
+ for (const seat of [...this.seats]) {
534
+ if (this.world.tick - seat.heard > silent) {
535
+ seat.transport.close();
536
+ this.leave(seat);
537
+ } else if (this.holding(seat, began)) this.sentTick = -1;
538
+ else {
539
+ const delta = this.deltaFor(seat);
540
+ const made = performance.now();
541
+ const text = JSON.stringify({
542
+ type: "delta",
543
+ ...delta
544
+ });
545
+ this.timing.parts.stringify += performance.now() - made;
546
+ this.timing.bytes += text.length;
547
+ if (this.timing.keys) bytesByKey(delta, text, this.timing.keys);
548
+ seat.transport.send(text);
549
+ }
550
+ if (seat.debug && began - seat.debug.sentAt >= 100) this.sendDebug(seat, seat.debug, began);
551
+ }
552
+ } finally {
553
+ endSharedCaptures(this.world);
554
+ this.roundEntities = [];
555
+ }
556
+ const took = performance.now() - began;
557
+ const { timing, totals } = this;
558
+ timing.sends++;
559
+ timing.sendTime += took;
560
+ timing.sendMax = Math.max(timing.sendMax, took);
561
+ totals.sends++;
562
+ totals.sendTime += took;
563
+ }
564
+ /**
565
+ * Where the host's time went since it was last asked (`takeTiming`): ticks of the simulation, and rounds of sending
566
+ * everyone what changed (the snapshots, the diffs, the JSON), each in milliseconds, added up and at most
567
+ */
568
+ timing;
569
+ /**
570
+ * Where the host's time went since it started, never counted anew: ticks and rounds of sending, with the
571
+ * milliseconds they took, and how long the last tick took. What a server's numbers are made of (`/metrics`)
572
+ */
573
+ totals = {
574
+ ticks: 0,
575
+ tickTime: 0,
576
+ lastTick: 0,
577
+ sends: 0,
578
+ sendTime: 0
579
+ };
580
+ /** Where the time went since the last call, and starts counting anew: for a server to print */
581
+ takeTiming() {
582
+ const now = performance.now();
583
+ const timing = {
584
+ ...this.timing,
585
+ seconds: (now - this.timing.since) / 1e3
586
+ };
587
+ this.timing = emptyTiming(now, this.byKey);
588
+ return timing;
589
+ }
590
+ /** The lists of entities told this round so far, and what each was sent as, for the seats told the same to share one (`quantizedList`) */
591
+ roundEntities = [];
592
+ /** What the player knows now, as what changed since the tick they last said they got */
593
+ deltaFor(seat) {
594
+ const { session } = seat;
595
+ const { parts } = this.timing;
596
+ const began = performance.now();
597
+ const snapshot = session.snapshot();
598
+ const captured = performance.now();
599
+ const told = seat.answers.length ? [...snapshot.events, ...seat.answers.splice(0)] : snapshot.events;
600
+ if (told.length) seat.events.push({
601
+ tick: snapshot.tick,
602
+ n: ++seat.eventsMade,
603
+ events: told
604
+ });
605
+ let over = seat.events.length - this.keptEvents;
606
+ while (over-- > 0 && seat.events[0].sentAt !== void 0) seat.events.shift();
607
+ const entities = quantizedList(snapshot.entities, this.roundEntities);
608
+ const quantized = performance.now();
609
+ const fog = fogMessageOf(session.fog());
610
+ const fogged = performance.now();
611
+ const frame = {
612
+ snapshot: {
613
+ ...snapshot,
614
+ entities,
615
+ events: []
616
+ },
617
+ fog,
618
+ camps: session.camps().map((camp) => ({ ...camp })),
619
+ team: session.team
620
+ };
621
+ const now = performance.now();
622
+ const overdue = seat.roundTrip * 1.5 + this.sendEvery * 1e3;
623
+ const events = seat.events.filter((sent) => sent.sentAt === void 0 || now - sent.sentAt > overdue);
624
+ for (const sent of events) sent.sentAt = now;
625
+ const base = seat.frames.get(seat.acked);
626
+ const delta = {
627
+ ...diff(base, frame, this.world.registry),
628
+ events: events.map(({ tick, n, events }) => ({
629
+ tick,
630
+ n,
631
+ events
632
+ }))
633
+ };
634
+ if (!base) seat.whole = {
635
+ tick: frame.snapshot.tick,
636
+ at: now
637
+ };
638
+ parts.capture += captured - began;
639
+ parts.quantize += quantized - captured;
640
+ parts.fog += fogged - quantized;
641
+ parts.diff += performance.now() - fogged;
642
+ this.keep(seat, frame);
643
+ if (seat.inOrder) {
644
+ seat.acked = frame.snapshot.tick;
645
+ seat.whole = void 0;
646
+ for (const kept of [...seat.frames.keys()]) if (kept < seat.acked) this.forget(seat, kept);
647
+ }
648
+ seat.sentAt.set(frame.snapshot.tick, now);
649
+ if (seat.sentAt.size > this.keptFrames) seat.sentAt.delete(seat.sentAt.keys().next().value);
650
+ return delta;
651
+ }
652
+ /**
653
+ * Keeps the frame a player was sent, to make the next delta against: the oldest let go past `keptFrames` of them or
654
+ * `keptBytes` together, the newest kept whatever it takes. A player who says nothing for long is sent everything
655
+ * again, once its base is no longer kept
656
+ */
657
+ keep(seat, frame) {
658
+ const { tick } = frame.snapshot;
659
+ const bytes = frameBytes(frame);
660
+ seat.frames.set(tick, frame);
661
+ seat.frameSizes.set(tick, bytes);
662
+ seat.keptBytes += bytes;
663
+ while (seat.frames.size > 1 && (seat.frames.size > this.keptFrames || seat.keptBytes > this.keptBytes)) this.forget(seat, seat.frames.keys().next().value);
664
+ }
665
+ /** Lets go of a frame kept for a player */
666
+ forget(seat, tick) {
667
+ if (!seat.frames.delete(tick)) return;
668
+ seat.keptBytes -= seat.frameSizes.get(tick) ?? 0;
669
+ seat.frameSizes.delete(tick);
670
+ }
671
+ /** Runs the world by the clock, `rate` updates a second, until `stop` or `dispose` */
672
+ start(rate = this.world.tickRate) {
673
+ this.stop();
674
+ this.last = performance.now();
675
+ this.timer = setInterval(() => {
676
+ const now = performance.now();
677
+ const dt = Math.min((now - this.last) / 1e3, .25);
678
+ this.last = now;
679
+ try {
680
+ this.update(dt);
681
+ } catch (error) {
682
+ this.stop();
683
+ if (this.onError) this.onError(error);
684
+ else this.world.log.error("server", "stepping the game threw: it is stopped", { error: errorFields(error) });
685
+ }
686
+ }, 1e3 / rate);
687
+ }
688
+ /** Stops stepping the world by the clock; does nothing if it was not started */
689
+ stop() {
690
+ if (this.timer !== void 0) clearInterval(this.timer);
691
+ this.timer = void 0;
692
+ }
693
+ /** Whether it runs by the clock */
694
+ get running() {
695
+ return this.timer !== void 0;
696
+ }
697
+ /** Stops, and closes every connection. The world goes too, when it is the host's (`ownsWorld`) */
698
+ /**
699
+ * Stops, and lets every player go: their connections closed, unless `closeTransports` is false (a server that keeps
700
+ * them for its lobby, after the game)
701
+ */
702
+ dispose(options = {}) {
703
+ this.stop();
704
+ this.stopFailed();
705
+ for (const seat of [...this.seats]) {
706
+ if (options.closeTransports !== false) seat.transport.close();
707
+ this.leave(seat);
708
+ }
709
+ if (this.ownsWorld) this.world.dispose();
710
+ }
711
+ };
712
+ /**
713
+ * What the player's side keeps of the map, to answer the screen without asking the host: a placement grid and the
714
+ * ways to walk of the map as it was made, with the structures the player has seen on them. What they have not seen
715
+ * is not there: a path preview never goes around a building in the dark, and gives it away
716
+ */
717
+ var ClientWorld = class {
718
+ terrain;
719
+ registry;
720
+ nav;
721
+ air;
722
+ grid;
723
+ known = /* @__PURE__ */ new Map();
724
+ seen = /* @__PURE__ */ new Set();
725
+ constructor(terrain, registry, nav, air) {
726
+ this.terrain = terrain;
727
+ this.registry = registry;
728
+ this.nav = nav;
729
+ this.air = air;
730
+ this.grid = new BuildGrid(terrain);
731
+ }
732
+ /** Whether a resource of a kind that it knows of covers just this ground, with nothing it knows of standing on it */
733
+ resourceAt(kind, cellX, cellZ, w, d) {
734
+ let found = false;
735
+ for (const structure of this.known.values()) {
736
+ if (structure.cellX !== cellX || structure.cellZ !== cellZ || structure.w !== w || structure.d !== d) continue;
737
+ if (structure.resource !== kind) return false;
738
+ found = true;
739
+ }
740
+ return found;
741
+ }
742
+ /** Brings the structures up to date with a snapshot: those in it stand, those no longer in it are gone */
743
+ sync(snapshot) {
744
+ const { seen, known } = this;
745
+ seen.clear();
746
+ let changed = false;
747
+ for (const entity of snapshot.entities) {
748
+ if (!this.registry.units.has(entity.type)) continue;
749
+ if (!this.registry.unit(entity.type).footprint) continue;
750
+ seen.add(entity.id);
751
+ if (this.stand(entity)) changed = true;
752
+ }
753
+ const gone = [];
754
+ for (const id of known.keys()) if (!seen.has(id)) gone.push(id);
755
+ this.settle(gone, changed);
756
+ }
757
+ /**
758
+ * Brings the structures up to date with a snapshot made on the one before it, from what came and went alone: the
759
+ * last `added` of its entities (`apply` puts those that came after the rest), and the ids of those `removed`. What
760
+ * `sync` does, without looking over every entity of the map
761
+ */
762
+ change(snapshot, added, removed) {
763
+ const { entities } = snapshot;
764
+ let changed = false;
765
+ const gone = removed.filter((id) => this.known.has(id));
766
+ for (const id of gone) this.release(id);
767
+ for (let i = entities.length - added; i < entities.length; i++) {
768
+ const entity = entities[i];
769
+ if (!this.registry.units.has(entity.type) || !this.registry.unit(entity.type).footprint) continue;
770
+ if (this.stand(entity)) changed = true;
771
+ }
772
+ this.settle([], changed || gone.length > 0, gone.length > 0);
773
+ }
774
+ /** Puts a structure on the map, where it is not on it yet: whether it was put */
775
+ stand(entity) {
776
+ const { known, grid, nav } = this;
777
+ if (known.has(entity.id)) return false;
778
+ const def = this.registry.unit(entity.type);
779
+ const site = siteOf(def, entity);
780
+ const { w, d } = footprintOf(def);
781
+ known.set(entity.id, {
782
+ cellX: site.cellX,
783
+ cellZ: site.cellZ,
784
+ w,
785
+ d,
786
+ ...def.resource && { resource: def.resource.id }
787
+ });
788
+ grid.occupy(site.cellX, site.cellZ, w, d, entity.id);
789
+ nav.addObstacle(entity.id, site);
790
+ return true;
791
+ }
792
+ /** Takes a structure off the map */
793
+ release(id) {
794
+ const structure = this.known.get(id);
795
+ this.known.delete(id);
796
+ this.grid.release(structure.cellX, structure.cellZ, structure.w, structure.d, id);
797
+ this.nav.removeObstacle(id);
798
+ }
799
+ /** Takes off those gone, gives the ground back to what stood on them, and has the navmesh take in what changed */
800
+ settle(gone, changed, released = false) {
801
+ for (const id of gone) this.release(id);
802
+ released ||= gone.length > 0;
803
+ if (released) for (const [id, structure] of this.known) this.grid.occupy(structure.cellX, structure.cellZ, structure.w, structure.d, id);
804
+ if (changed || released) this.nav.update(0);
805
+ }
806
+ };
807
+ /**
808
+ * The host said no, with why: to come back to a game that is over, or a player let go. Trying again does not help
809
+ *
810
+ * @beta
811
+ */
812
+ var SessionRefused = class extends Error {
813
+ reason;
814
+ constructor(reason) {
815
+ super(reason);
816
+ this.reason = reason;
817
+ this.name = "SessionRefused";
818
+ }
819
+ };
820
+ /**
821
+ * A player's seat at a world that runs elsewhere, over a transport (see `connect`). It rebuilds what the host sends
822
+ * as changes (`Delta`) into whole snapshots, keeping the objects of what did not change, says which ticks it got, and
823
+ * answers the screen's questions from those and its own copy of the map (`ClientWorld`). No debug access, and no
824
+ * checkpoints: those belong to a simulation in the page
825
+ *
826
+ * @beta
827
+ */
828
+ var RemoteSession = class {
829
+ transport;
830
+ map;
831
+ limits;
832
+ /**
833
+ * A seat over a wire can none of what a game in this page can (`SessionCan`), but the debug tools' view of the world
834
+ * for a player the host lets use them (`inspect`, said over the wire)
835
+ */
836
+ can;
837
+ /** The debug tools' view of the world, for a player the host lets use them (the welcome's `debug`) */
838
+ get debugView() {
839
+ return this.remoteDebug;
840
+ }
841
+ remoteDebug;
842
+ /** The player this seat plays, as the host welcomed it */
843
+ playerId;
844
+ /** The team of that player; updated when a snapshot says it changed */
845
+ team;
846
+ /** The ground, built from the welcome and the parts the host sent */
847
+ terrain;
848
+ /** The map's look (sky, mist, light) from the welcome, when it has one */
849
+ environment;
850
+ /** The map's scenery objects from the welcome */
851
+ doodads;
852
+ /** The map's named regions from the welcome */
853
+ regions;
854
+ /** The map's named camera positions from the welcome */
855
+ cameras;
856
+ /** The map's named paths from the welcome */
857
+ paths;
858
+ /** The definitions of the game, from the rules the player connected with */
859
+ registry;
860
+ /** Simulation ticks per second the host runs at, from the welcome */
861
+ tickRate;
862
+ /** How far, 0..1, the shown tick is between the last two snapshots, for blending the drawing */
863
+ alpha = 1;
864
+ /** What the player knows by tick, for the deltas to come: from the base of the last one on */
865
+ frames = /* @__PURE__ */ new Map();
866
+ latest;
867
+ incoming = [];
868
+ /** What the host's definitions were changed to while it ran (`world.redefine`), as this screen heard it */
869
+ redefined = {};
870
+ /** The number of the last batch of events that went to the screen (`Delta.events`): those sent again are not applied twice */
871
+ eventsUpTo = -1;
872
+ fogState;
873
+ closed = false;
874
+ /** The tick the screen shows, between the last two snapshots given out */
875
+ renderTick;
876
+ /** The tick of the snapshot given out last, and of the one before it */
877
+ shownTick;
878
+ shownBefore;
879
+ /** Ticks between two snapshots, evened out */
880
+ interval = 1;
881
+ /** How far off the time snapshots arrive at is from the ticks between them, in seconds, evened out */
882
+ jitter = 0;
883
+ /** Seconds between two snapshots' arrivals, evened out: a seek's come as often as any, their ticks far apart */
884
+ gap = 0;
885
+ /** When the last snapshot arrived, and its tick */
886
+ arrival;
887
+ constructor(transport, welcome, registry, map, limits = {}) {
888
+ this.transport = transport;
889
+ this.map = map;
890
+ this.limits = limits;
891
+ this.playerId = welcome.player;
892
+ this.tickRate = welcome.tickRate;
893
+ this.observer = welcome.observer ?? false;
894
+ this.remoteDebug = welcome.debug ? new RemoteDebug((ask) => this.tell({
895
+ type: "debug",
896
+ ...ask
897
+ })) : void 0;
898
+ this.can = this.remoteDebug ? { inspect: this.remoteDebug } : {};
899
+ this.registry = registry;
900
+ this.terrain = map.terrain;
901
+ this.environment = welcome.environment;
902
+ this.doodads = welcome.doodads ?? [];
903
+ this.regions = welcome.regions ?? [];
904
+ this.cameras = welcome.cameras ?? [];
905
+ this.paths = welcome.paths ?? [];
906
+ restoreRedefinitions(registry, welcome.redefinitions);
907
+ this.heardRedefined(welcome.redefinitions);
908
+ const cells = this.terrain.width * this.terrain.depth;
909
+ this.fogState = {
910
+ width: this.terrain.width,
911
+ depth: this.terrain.depth,
912
+ version: 0,
913
+ revealed: false,
914
+ visible: new Uint8Array(cells),
915
+ explored: new Uint8Array(cells)
916
+ };
917
+ const first = this.take(welcome.first);
918
+ this.latest = first;
919
+ this.team = first.team;
920
+ this.incoming.length = 0;
921
+ this.shownTick = this.shownBefore = first.snapshot.tick;
922
+ this.attach(transport);
923
+ }
924
+ /** Talks through a transport from now on: what comes in is taken, and its closing is a drop */
925
+ attach(transport) {
926
+ this.transport = transport;
927
+ this.closed = false;
928
+ this.leaving = false;
929
+ transport.onMessage((text) => {
930
+ const message = readHostMessage(text);
931
+ if (message) this.receive(message);
932
+ });
933
+ transport.onClose(() => {
934
+ if (this.transport !== transport) return;
935
+ this.closed = true;
936
+ clearInterval(this.pinger);
937
+ if (!this.leaving) this.onDisconnect?.();
938
+ });
939
+ this.sendPing();
940
+ clearInterval(this.pinger);
941
+ this.pinger = setInterval(() => this.sendPing(), this.limits.pingEvery ?? PING_EVERY);
942
+ }
943
+ /** Whether the host has gone */
944
+ get disconnected() {
945
+ return this.closed;
946
+ }
947
+ /**
948
+ * Told when the connection drops, not by this side's leaving (`dispose`): to try again (`resume`), or to say the
949
+ * game is lost
950
+ */
951
+ onDisconnect;
952
+ /** This side closed it: not a drop */
953
+ leaving = false;
954
+ /**
955
+ * Goes on with the same game over a new connection, once the host has welcomed it there again (a server does, to who
956
+ * comes back with their seat's token): everything known sent again, and the screen catches up. What the host says
957
+ * besides the game before the welcome goes to `onServer`; a `refused` fails it with the reason, as does a connection
958
+ * that closes first, or a host that runs another game
959
+ */
960
+ async resume(transport) {
961
+ const welcome = await new Promise((resolve, reject) => {
962
+ transport.onClose(() => reject(/* @__PURE__ */ new Error("The host closed the connection before it took the player back")));
963
+ transport.onMessage((text) => {
964
+ const message = readHostMessage(text);
965
+ if (!message) return;
966
+ if (message.type === "welcome") resolve(message);
967
+ else if (message.type === "refused") reject(new SessionRefused(String(message.reason ?? "refused")));
968
+ else if (isServerMessage(message)) this.onServer?.(message);
969
+ });
970
+ });
971
+ const problem = welcomeProblem(welcome);
972
+ if (problem) {
973
+ transport.close();
974
+ throw new Error(problem);
975
+ }
976
+ if (welcome.game !== this.registry.game || welcome.hash !== this.registry.dataHash || welcome.player !== this.playerId) {
977
+ transport.close();
978
+ throw new Error("The host took the player back to another game");
979
+ }
980
+ restoreRedefinitions(this.registry, welcome.redefinitions);
981
+ this.heardRedefined(welcome.redefinitions);
982
+ this.eventsUpTo = -1;
983
+ this.attach(transport);
984
+ this.frames.clear();
985
+ this.incoming.length = 0;
986
+ this.arrival = void 0;
987
+ this.interval = 1;
988
+ this.jitter = 0;
989
+ this.gap = 0;
990
+ if (welcome.first.tick < this.shownTick) {
991
+ this.shownTick = this.shownBefore = welcome.first.tick;
992
+ this.renderTick = void 0;
993
+ this.eventsUpTo = welcome.first.tick - 1;
994
+ }
995
+ this.take(welcome.first);
996
+ this.remoteDebug?.askAgain();
997
+ }
998
+ /** Keeps what the host's definitions were changed to, over what was kept before */
999
+ heardRedefined(data) {
1000
+ for (const [kind, byId] of Object.entries(data ?? {})) for (const [id, values] of Object.entries(byId)) {
1001
+ const kept = this.redefined[kind] ??= {};
1002
+ kept[id] = mergeValues(kept[id] ?? {}, values);
1003
+ }
1004
+ }
1005
+ /**
1006
+ * Takes a new version of the game into this screen's registry (hot reload, a game in a worker): its definitions as
1007
+ * the new version has them, what the host changed of them while it ran over them again
1008
+ */
1009
+ takeGame(game) {
1010
+ this.registry.takeFrom(createRegistry(game));
1011
+ restoreRedefinitions(this.registry, this.redefined);
1012
+ }
1013
+ /** Takes in a message of the host's: what the transport hands it, and what came in while the session was made */
1014
+ receive(message) {
1015
+ if (message.type === "delta") this.take(message);
1016
+ else if (message.type === "debug") this.remoteDebug?.take(message);
1017
+ else if (message.type === "pong") {
1018
+ const took = performance.now() - message.at;
1019
+ this.ping = this.ping === void 0 ? took : this.ping + (took - this.ping) * .3;
1020
+ } else if (message.type === "failed") {
1021
+ if (typeof message.message === "string") this.failure = { message: message.message };
1022
+ } else if (isServerMessage(message)) {
1023
+ if (message.type === "paused") {
1024
+ this.pause = message.paused === true ? {
1025
+ ...typeof message.player === "number" && { player: message.player },
1026
+ ...typeof message.seconds === "number" && { until: Date.now() + message.seconds * 1e3 }
1027
+ } : null;
1028
+ this.onPause?.(this.pause);
1029
+ }
1030
+ this.onServer?.(message);
1031
+ }
1032
+ }
1033
+ /**
1034
+ * The game paused by the server, for everyone: by a player (`player`, until a time at most, in `Date.now()`'s
1035
+ * milliseconds) or an admin (neither). Null while it goes on
1036
+ */
1037
+ pause = null;
1038
+ /** Told each time the server pauses the game or lets it go on */
1039
+ onPause;
1040
+ /** Says something to the server beside the game: a lobby's message (`{ type: 'resume' }`) */
1041
+ tell(message) {
1042
+ if (!this.closed) this.transport.send(JSON.stringify(message));
1043
+ }
1044
+ /** Why the game ended on an error in its rules, once the host said so */
1045
+ failure = null;
1046
+ /** Milliseconds a message takes to the host and back, evened out: measured every couple of seconds */
1047
+ ping;
1048
+ /** Whether the player only watches, and sees everything */
1049
+ observer;
1050
+ pinger;
1051
+ /** Asks the host to answer at once, to measure the time there and back */
1052
+ sendPing() {
1053
+ if (!this.closed) this.transport.send(JSON.stringify({
1054
+ type: "ping",
1055
+ at: performance.now()
1056
+ }));
1057
+ }
1058
+ /** Told of what the host says besides the game: a server's messages (see `ConnectOptions.onServer`) */
1059
+ onServer;
1060
+ /** Rebuilds the frame a delta makes, says it got it, and has its snapshot wait for the screen */
1061
+ take(delta) {
1062
+ const base = delta.base === null ? void 0 : this.frames.get(delta.base);
1063
+ if (delta.base !== null && !base) return void 0;
1064
+ const frame = apply(base, delta, this.latest);
1065
+ const { snapshot } = frame;
1066
+ this.frames.set(snapshot.tick, frame);
1067
+ for (const tick of this.frames.keys()) if (delta.base !== null && tick < delta.base) this.frames.delete(tick);
1068
+ if (delta.rest.fog) this.takeFog(delta.rest.fog);
1069
+ if (delta.rest.team !== void 0) this.team = delta.rest.team;
1070
+ const events = [];
1071
+ for (const sent of delta.events) {
1072
+ if (sent.n <= this.eventsUpTo) continue;
1073
+ events.push(...sent.events);
1074
+ this.eventsUpTo = sent.n;
1075
+ for (const event of sent.events) {
1076
+ if (event.type === "redefined") {
1077
+ redefineIn(this.registry, event.kind, event.definition, event.values);
1078
+ this.heardRedefined({ [event.kind]: { [event.definition]: event.values } });
1079
+ }
1080
+ if (event.type === "ground" && !terrainPatchProblem(this.terrain, event.patch)) applyTerrainPatch(this.terrain, event.patch);
1081
+ if (event.type !== "cells") continue;
1082
+ const layer = this.terrain.cellLayer(event.layer);
1083
+ for (const c of event.at) if (c >= 0 && c < layer.length) layer[c] = event.value;
1084
+ }
1085
+ }
1086
+ this.incoming.push({
1087
+ ...snapshot,
1088
+ events
1089
+ });
1090
+ if (this.incoming.length > (this.limits.keptSnapshots ?? KEPT_SNAPSHOTS)) this.fold();
1091
+ this.arrived(snapshot.tick);
1092
+ if (base && base === this.latest) this.map.change(snapshot, delta.added.length, delta.removed);
1093
+ else this.map.sync(snapshot);
1094
+ this.latest = frame;
1095
+ if (!this.closed) this.transport.send(JSON.stringify({
1096
+ type: "ack",
1097
+ tick: snapshot.tick,
1098
+ events: this.eventsUpTo
1099
+ }));
1100
+ return frame;
1101
+ }
1102
+ /**
1103
+ * The oldest snapshot waiting let go, its events put before the next one's: the screen, when it asks again, jumps
1104
+ * to the newest anyway. The state is in every snapshot; the events (deaths, sounds, lines said) are what would be lost
1105
+ */
1106
+ fold() {
1107
+ const oldest = this.incoming.shift();
1108
+ if (!oldest.events.length) return;
1109
+ const next = this.incoming[0];
1110
+ const events = oldest.events.concat(next.events);
1111
+ const mostEvents = this.limits.keptScreenEvents ?? KEPT_SCREEN_EVENTS;
1112
+ this.incoming[0] = {
1113
+ ...next,
1114
+ events: events.length > mostEvents ? events.slice(-mostEvents) : events
1115
+ };
1116
+ }
1117
+ /**
1118
+ * Snapshots come in and not yet given to the screen (`update`): a few normally, never more than a few seconds of
1119
+ * them, however long the screen does not ask
1120
+ *
1121
+ * @beta
1122
+ */
1123
+ get waiting() {
1124
+ return this.incoming.length;
1125
+ }
1126
+ takeFog(message) {
1127
+ const fog = this.fogState;
1128
+ fog.revealed = message.revealed;
1129
+ fromRuns(message.visible, fog.visible);
1130
+ fromRuns(message.explored, fog.explored);
1131
+ fog.version++;
1132
+ }
1133
+ /** The newest snapshot the host sent */
1134
+ snapshot() {
1135
+ return this.latest.snapshot;
1136
+ }
1137
+ /** The tick the screen is shown at, between two snapshots: behind the newest by `delay` */
1138
+ get shownAt() {
1139
+ return this.renderTick ?? this.shownTick;
1140
+ }
1141
+ /**
1142
+ * The ticks between two snapshots, and the jitter the interpolation makes room for, as it has them evened out. A
1143
+ * test may set the jitter, as a late line would have
1144
+ *
1145
+ * @internal
1146
+ */
1147
+ get pacing() {
1148
+ return {
1149
+ interval: this.interval,
1150
+ jitter: this.jitter
1151
+ };
1152
+ }
1153
+ /** @internal */
1154
+ set pacing(pacing) {
1155
+ this.jitter = pacing.jitter;
1156
+ }
1157
+ /** How far behind the newest snapshot the screen is shown, in ticks: about two snapshots, and room for the jitter */
1158
+ get delay() {
1159
+ return this.interval * 2 + Math.min(this.jitter, this.limits.maxJitter ?? .2) * this.tickRate * 2;
1160
+ }
1161
+ /** Takes note of when a snapshot arrived, for how far apart they come and how unevenly */
1162
+ arrived(tick) {
1163
+ const now = performance.now();
1164
+ const last = this.arrival;
1165
+ this.arrival = {
1166
+ at: now,
1167
+ tick
1168
+ };
1169
+ if (!last || tick <= last.tick) return;
1170
+ const ticks = tick - last.tick;
1171
+ this.interval += (ticks - this.interval) * .1;
1172
+ this.gap += ((now - last.at) / 1e3 - this.gap) * .1;
1173
+ const off = Math.abs((now - last.at) / 1e3 - ticks / this.tickRate);
1174
+ this.jitter += (off - this.jitter) * .1;
1175
+ }
1176
+ /**
1177
+ * Lets the screen's clock go on by `dt`, and gives out the snapshots it has come to, oldest first: the screen draws
1178
+ * between the last two (`alpha`). The time is the host's: the clock follows the snapshots, not the other way around
1179
+ */
1180
+ update(dt) {
1181
+ const newest = this.incoming.length ? this.incoming[this.incoming.length - 1].tick : this.shownTick;
1182
+ const target = !!this.arrival && performance.now() - this.arrival.at > Math.max(QUIET, this.gap * 3) * 1e3 ? newest : newest - this.delay;
1183
+ if (this.renderTick === void 0 || target - this.renderTick > this.tickRate) this.renderTick = target;
1184
+ else {
1185
+ const rate = 1 + Math.max(-.1, Math.min((target - this.renderTick) * .05, .1));
1186
+ this.renderTick += dt * this.tickRate * rate;
1187
+ }
1188
+ this.renderTick = Math.min(this.renderTick, newest);
1189
+ const out = [];
1190
+ while (this.incoming.length && this.renderTick >= this.shownTick) {
1191
+ const next = this.incoming.shift();
1192
+ this.shownBefore = this.shownTick;
1193
+ this.shownTick = next.tick;
1194
+ out.push(next);
1195
+ }
1196
+ const span = this.shownTick - this.shownBefore;
1197
+ this.alpha = span > 0 ? Math.max(0, Math.min((this.renderTick - this.shownBefore) / span, 1)) : 1;
1198
+ return out;
1199
+ }
1200
+ /** Sends a command to the host and returns the number it was given, which the host's answer names; does nothing once closed */
1201
+ send(command) {
1202
+ const seq = ++this.lastSeq;
1203
+ if (!this.closed) this.transport.send(JSON.stringify({
1204
+ type: "command",
1205
+ seq,
1206
+ command
1207
+ }));
1208
+ return seq;
1209
+ }
1210
+ /** The number of the last command sent */
1211
+ lastSeq = 0;
1212
+ /** The team's fog as built from what the host sent */
1213
+ fog() {
1214
+ return this.fogState;
1215
+ }
1216
+ /** The creep camps as the newest frame has them */
1217
+ camps() {
1218
+ return this.latest.camps;
1219
+ }
1220
+ /**
1221
+ * Whether the player could build this here, as far as they can tell: on their copy of the map, with the structures
1222
+ * they know, on ground they have explored. The game's own say (the `canPlace` hook) is the host's: it may still refuse
1223
+ */
1224
+ canPlace(unitType, point) {
1225
+ if (!this.registry.units.has(unitType)) return false;
1226
+ const def = this.registry.unit(unitType);
1227
+ const site = siteOf(def, point);
1228
+ const { w, d } = footprintOf(def);
1229
+ if (def.builtOn !== void 0 ? !this.map.resourceAt(def.builtOn, site.cellX, site.cellZ, w, d) : !this.map.grid.canPlace(site.cellX, site.cellZ, w, d)) return false;
1230
+ const fog = this.fogState;
1231
+ if (fog.revealed) return true;
1232
+ const explored = (x, z) => fog.explored[Math.floor(z) * fog.width + Math.floor(x)] === 1;
1233
+ return explored(site.x - site.hw + .5, site.z - site.hd + .5) && explored(site.x + site.hw - .5, site.z - site.hd + .5) && explored(site.x - site.hw + .5, site.z + site.hd - .5) && explored(site.x + site.hw - .5, site.z + site.hd - .5);
1234
+ }
1235
+ /** Which cells of a building's ground are in the way, as `canPlace` sees them: on the player's copy of the map, explored */
1236
+ placeCells(unitType, point) {
1237
+ if (!this.registry.units.has(unitType)) return void 0;
1238
+ const fog = this.fogState;
1239
+ return placementCells(this.registry.unit(unitType), point, (x, z) => this.map.grid.canPlace(x, z, 1, 1), fog.revealed ? void 0 : (x, z) => fog.explored[z * fog.width + x] === 1);
1240
+ }
1241
+ /** The way a unit would walk, on the player's copy of the map: around the structures they know, and no others */
1242
+ /** Where a group would stand sent to a point in a formation, `rows` when none is named: the rules are the host's (`GameSession.formationPlaces`) */
1243
+ formationPlaces(units, point, facing, formation = "rows") {
1244
+ return formationPreview(this.registry, units, point, this.map, formation, facing);
1245
+ }
1246
+ /** A path over the ground the player has, on the air layer when `flying`; null when there is none */
1247
+ findPath(from, to, flying = false) {
1248
+ return (flying ? this.map.air : this.map.nav).findPath(from, to);
1249
+ }
1250
+ /** Stops pinging, closes the connection and frees the navigation made from the ground */
1251
+ dispose() {
1252
+ clearInterval(this.pinger);
1253
+ this.leaving = true;
1254
+ if (!this.closed) this.transport.close();
1255
+ this.closed = true;
1256
+ this.map.nav.dispose();
1257
+ this.map.air.dispose();
1258
+ }
1259
+ };
1260
+ /** How much of the ground goes in one message, for a player who does not have its map: well under what a connection holds */
1261
+ var GROUND_PART = 262144;
1262
+ /**
1263
+ * The ground of a welcome: all of it, or the map it started as among the player's (S36), the changes put on it. A
1264
+ * player without that map asks the host for it, a part at a time, and puts the changes on what it is sent
1265
+ */
1266
+ async function groundOfWelcome(transport, ground, maps, game, early, dropped) {
1267
+ try {
1268
+ return groundOf(ground, maps, game).terrain;
1269
+ } catch (error) {
1270
+ if (!(error instanceof MissingGround) || !isGroundChanges(ground)) throw error;
1271
+ }
1272
+ const whole = await new Promise((resolve, reject) => {
1273
+ const parts = [];
1274
+ transport.onClose(() => {
1275
+ dropped();
1276
+ reject(/* @__PURE__ */ new Error("The host closed the connection while the ground was sent"));
1277
+ });
1278
+ transport.onMessage((text) => {
1279
+ const message = readHostMessage(text);
1280
+ if (message?.type !== "ground") {
1281
+ early.push(text);
1282
+ return;
1283
+ }
1284
+ parts[message.part] = message.text;
1285
+ if (message.part + 1 < message.parts) transport.send(JSON.stringify({
1286
+ type: "ground",
1287
+ part: message.part + 1
1288
+ }));
1289
+ else {
1290
+ transport.onMessage((later) => early.push(later));
1291
+ resolve(JSON.parse(parts.join("")));
1292
+ }
1293
+ });
1294
+ transport.send(JSON.stringify({
1295
+ type: "ground",
1296
+ part: 0
1297
+ }));
1298
+ });
1299
+ return applyGroundChanges(loadTerrain(whole), ground);
1300
+ }
1301
+ /**
1302
+ * What is wrong with a welcome, before anything of it is used: another version of the wire (`PROTOCOL_VERSION`), or a
1303
+ * shape that is not one. What comes after it is the host's word, trusted as the welcome said it would be
1304
+ */
1305
+ function welcomeProblem(welcome) {
1306
+ if (welcome.protocol !== 13) return protocolMismatch(welcome.protocol);
1307
+ return Number.isInteger(welcome.player) && isFiniteNumber(welcome.tickRate) && welcome.tickRate > 0 && typeof welcome.game === "string" && typeof welcome.hash === "string" && typeof welcome.terrain === "object" && welcome.terrain !== null && typeof welcome.first === "object" && welcome.first !== null ? void 0 : "The host sent a welcome this player cannot read";
1308
+ }
1309
+ /**
1310
+ * Connects to a host over a transport (the player's end of it), and waits for the welcome: what the session is
1311
+ * made of. Fails when the host runs another version of the game, or of the engine's wire (`PROTOCOL_VERSION`), and
1312
+ * when the connection closes before the session is made: while the map is made from the welcome too
1313
+ *
1314
+ * @public
1315
+ */
1316
+ function connect(transport, options) {
1317
+ return connectAs(transport, options, (...made) => new RemoteSession(...made));
1318
+ }
1319
+ /** `connect`, for a session of a kind of its own: `make` is given what a `RemoteSession` is made of */
1320
+ async function connectAs(transport, options, make) {
1321
+ let dropped = false;
1322
+ const drop = () => {
1323
+ dropped = true;
1324
+ };
1325
+ const welcome = await new Promise((resolve, reject) => {
1326
+ transport.onClose(() => {
1327
+ drop();
1328
+ reject(/* @__PURE__ */ new Error("The host closed the connection before the game started"));
1329
+ });
1330
+ transport.onMessage((text) => {
1331
+ const message = readHostMessage(text);
1332
+ if (!message) return;
1333
+ if (message.type === "welcome") resolve(message);
1334
+ else if (isServerMessage(message)) options.onServer?.(message);
1335
+ });
1336
+ });
1337
+ const problem = welcomeProblem(welcome);
1338
+ if (problem) {
1339
+ transport.close();
1340
+ throw new Error(problem);
1341
+ }
1342
+ const game = "id" in options.rules && typeof options.rules.id === "string" ? options.rules : options.rules[welcome.game];
1343
+ const own = "id" in options.rules && typeof options.rules.id === "string" ? options.rules.id : void 0;
1344
+ const others = otherPacks(welcome.game, game?.id ?? own);
1345
+ if (!game) {
1346
+ transport.close();
1347
+ throw new Error(others ?? `The host runs ${welcome.game}, which this player does not have`);
1348
+ }
1349
+ const registry = createRegistry(game);
1350
+ if (welcome.game !== registry.game || welcome.hash !== registry.dataHash) {
1351
+ transport.close();
1352
+ throw new Error(others ?? `The host runs ${welcome.game} (${welcome.hash}), this is ${registry.game} (${registry.dataHash}): not the same game`);
1353
+ }
1354
+ const early = [];
1355
+ transport.onMessage((text) => early.push(text));
1356
+ transport.onClose(drop);
1357
+ const lost = "The host closed the connection while the map was made";
1358
+ if (dropped) throw new Error(lost);
1359
+ const terrain = await groundOfWelcome(transport, welcome.terrain, options.maps ?? game.maps, game, early, drop);
1360
+ transport.onClose(drop);
1361
+ const speedAt = hasGroundSpeeds(registry) ? (x, z) => navigationSpeedOn(registry, terrain, x, z) : void 0;
1362
+ const nav = await RecastNavigation.create(terrain, {
1363
+ agentRadius: .5,
1364
+ ...speedAt && { speedAt },
1365
+ ...options.navigation
1366
+ });
1367
+ if (dropped) {
1368
+ nav.dispose();
1369
+ throw new Error(lost);
1370
+ }
1371
+ const session = make(transport, welcome, registry, new ClientWorld(terrain, registry, nav, new AirNavigation(terrain.width, terrain.depth)), options.limits);
1372
+ session.onServer = options.onServer;
1373
+ for (const text of early) {
1374
+ const message = readHostMessage(text);
1375
+ if (message) session.receive(message);
1376
+ }
1377
+ return session;
1378
+ }
1379
+ /**
1380
+ * What a player is told who joins a game of the same base as theirs with other packs of content or mods
1381
+ * (`melee+gnomes` against `melee`): the host's and theirs. Nothing for games of other bases, or the same
1382
+ */
1383
+ function otherPacks(host, own) {
1384
+ if (own === void 0 || own === host) return void 0;
1385
+ const [hostBase, ...hostPacks] = host.split("+");
1386
+ const [ownBase, ...ownPacks] = own.split("+");
1387
+ if (hostBase !== ownBase) return void 0;
1388
+ const list = (packs) => packs.length ? packs.join(", ") : "none";
1389
+ return `The host plays ${hostBase} with the packs ${list(hostPacks)}, this player with ${list(ownPacks)}: the host's are the game's`;
1390
+ }
1391
+ //#endregion
1392
+ export { ClientWorld, MAX_JITTER, RemoteSession, SessionHost, SessionRefused, connect, connectAs, fromRuns, loopback, toRuns };
1393
+
1394
+ //# sourceMappingURL=remote.js.map