hoi4-agent-tools 0.0.0-bootstrap.1 → 0.1.3

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 (416) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/LICENSE +201 -0
  3. package/README.md +140 -2
  4. package/SECURITY.md +17 -0
  5. package/dist/bin/http.d.ts +3 -0
  6. package/dist/bin/http.d.ts.map +1 -0
  7. package/dist/bin/http.js +27 -0
  8. package/dist/bin/http.js.map +1 -0
  9. package/dist/bin/setup.d.ts +3 -0
  10. package/dist/bin/setup.d.ts.map +1 -0
  11. package/dist/bin/setup.js +188 -0
  12. package/dist/bin/setup.js.map +1 -0
  13. package/dist/bin/stdio.d.ts +3 -0
  14. package/dist/bin/stdio.d.ts.map +1 -0
  15. package/dist/bin/stdio.js +36 -0
  16. package/dist/bin/stdio.js.map +1 -0
  17. package/dist/hoi4_agent_tools/core/artifacts.d.ts +117 -0
  18. package/dist/hoi4_agent_tools/core/artifacts.d.ts.map +1 -0
  19. package/dist/hoi4_agent_tools/core/artifacts.js +1047 -0
  20. package/dist/hoi4_agent_tools/core/artifacts.js.map +1 -0
  21. package/dist/hoi4_agent_tools/core/canonical.d.ts +13 -0
  22. package/dist/hoi4_agent_tools/core/canonical.d.ts.map +1 -0
  23. package/dist/hoi4_agent_tools/core/canonical.js +41 -0
  24. package/dist/hoi4_agent_tools/core/canonical.js.map +1 -0
  25. package/dist/hoi4_agent_tools/core/configuration.d.ts +137 -0
  26. package/dist/hoi4_agent_tools/core/configuration.d.ts.map +1 -0
  27. package/dist/hoi4_agent_tools/core/configuration.js +383 -0
  28. package/dist/hoi4_agent_tools/core/configuration.js.map +1 -0
  29. package/dist/hoi4_agent_tools/core/diagnostic-collector.d.ts +18 -0
  30. package/dist/hoi4_agent_tools/core/diagnostic-collector.d.ts.map +1 -0
  31. package/dist/hoi4_agent_tools/core/diagnostic-collector.js +45 -0
  32. package/dist/hoi4_agent_tools/core/diagnostic-collector.js.map +1 -0
  33. package/dist/hoi4_agent_tools/core/diagnostics.d.ts +26 -0
  34. package/dist/hoi4_agent_tools/core/diagnostics.d.ts.map +1 -0
  35. package/dist/hoi4_agent_tools/core/diagnostics.js +25 -0
  36. package/dist/hoi4_agent_tools/core/diagnostics.js.map +1 -0
  37. package/dist/hoi4_agent_tools/core/diff.d.ts +22 -0
  38. package/dist/hoi4_agent_tools/core/diff.d.ts.map +1 -0
  39. package/dist/hoi4_agent_tools/core/diff.js +93 -0
  40. package/dist/hoi4_agent_tools/core/diff.js.map +1 -0
  41. package/dist/hoi4_agent_tools/core/engine.d.ts +56 -0
  42. package/dist/hoi4_agent_tools/core/engine.d.ts.map +1 -0
  43. package/dist/hoi4_agent_tools/core/engine.js +319 -0
  44. package/dist/hoi4_agent_tools/core/engine.js.map +1 -0
  45. package/dist/hoi4_agent_tools/core/image-diff.d.ts +14 -0
  46. package/dist/hoi4_agent_tools/core/image-diff.d.ts.map +1 -0
  47. package/dist/hoi4_agent_tools/core/image-diff.js +121 -0
  48. package/dist/hoi4_agent_tools/core/image-diff.js.map +1 -0
  49. package/dist/hoi4_agent_tools/core/index.d.ts +64 -0
  50. package/dist/hoi4_agent_tools/core/index.d.ts.map +1 -0
  51. package/dist/hoi4_agent_tools/core/index.js +963 -0
  52. package/dist/hoi4_agent_tools/core/index.js.map +1 -0
  53. package/dist/hoi4_agent_tools/core/index.public.d.ts +16 -0
  54. package/dist/hoi4_agent_tools/core/index.public.d.ts.map +1 -0
  55. package/dist/hoi4_agent_tools/core/index.public.js +16 -0
  56. package/dist/hoi4_agent_tools/core/index.public.js.map +1 -0
  57. package/dist/hoi4_agent_tools/core/render-budget.d.ts +51 -0
  58. package/dist/hoi4_agent_tools/core/render-budget.d.ts.map +1 -0
  59. package/dist/hoi4_agent_tools/core/render-budget.js +109 -0
  60. package/dist/hoi4_agent_tools/core/render-budget.js.map +1 -0
  61. package/dist/hoi4_agent_tools/core/result.d.ts +45 -0
  62. package/dist/hoi4_agent_tools/core/result.d.ts.map +1 -0
  63. package/dist/hoi4_agent_tools/core/result.js +26 -0
  64. package/dist/hoi4_agent_tools/core/result.js.map +1 -0
  65. package/dist/hoi4_agent_tools/core/scanner.d.ts +28 -0
  66. package/dist/hoi4_agent_tools/core/scanner.d.ts.map +1 -0
  67. package/dist/hoi4_agent_tools/core/scanner.js +136 -0
  68. package/dist/hoi4_agent_tools/core/scanner.js.map +1 -0
  69. package/dist/hoi4_agent_tools/core/server-state.d.ts +31 -0
  70. package/dist/hoi4_agent_tools/core/server-state.d.ts.map +1 -0
  71. package/dist/hoi4_agent_tools/core/server-state.js +413 -0
  72. package/dist/hoi4_agent_tools/core/server-state.js.map +1 -0
  73. package/dist/hoi4_agent_tools/core/source/encoding.d.ts +10 -0
  74. package/dist/hoi4_agent_tools/core/source/encoding.d.ts.map +1 -0
  75. package/dist/hoi4_agent_tools/core/source/encoding.js +54 -0
  76. package/dist/hoi4_agent_tools/core/source/encoding.js.map +1 -0
  77. package/dist/hoi4_agent_tools/core/source/index.d.ts +7 -0
  78. package/dist/hoi4_agent_tools/core/source/index.d.ts.map +1 -0
  79. package/dist/hoi4_agent_tools/core/source/index.js +7 -0
  80. package/dist/hoi4_agent_tools/core/source/index.js.map +1 -0
  81. package/dist/hoi4_agent_tools/core/source/lexer.d.ts +30 -0
  82. package/dist/hoi4_agent_tools/core/source/lexer.d.ts.map +1 -0
  83. package/dist/hoi4_agent_tools/core/source/lexer.js +266 -0
  84. package/dist/hoi4_agent_tools/core/source/lexer.js.map +1 -0
  85. package/dist/hoi4_agent_tools/core/source/limits.d.ts +21 -0
  86. package/dist/hoi4_agent_tools/core/source/limits.d.ts.map +1 -0
  87. package/dist/hoi4_agent_tools/core/source/limits.js +49 -0
  88. package/dist/hoi4_agent_tools/core/source/limits.js.map +1 -0
  89. package/dist/hoi4_agent_tools/core/source/localisation.d.ts +20 -0
  90. package/dist/hoi4_agent_tools/core/source/localisation.d.ts.map +1 -0
  91. package/dist/hoi4_agent_tools/core/source/localisation.js +163 -0
  92. package/dist/hoi4_agent_tools/core/source/localisation.js.map +1 -0
  93. package/dist/hoi4_agent_tools/core/source/parser.d.ts +44 -0
  94. package/dist/hoi4_agent_tools/core/source/parser.d.ts.map +1 -0
  95. package/dist/hoi4_agent_tools/core/source/parser.js +334 -0
  96. package/dist/hoi4_agent_tools/core/source/parser.js.map +1 -0
  97. package/dist/hoi4_agent_tools/core/source/rewrite.d.ts +10 -0
  98. package/dist/hoi4_agent_tools/core/source/rewrite.d.ts.map +1 -0
  99. package/dist/hoi4_agent_tools/core/source/rewrite.js +28 -0
  100. package/dist/hoi4_agent_tools/core/source/rewrite.js.map +1 -0
  101. package/dist/hoi4_agent_tools/core/svg-text.d.ts +34 -0
  102. package/dist/hoi4_agent_tools/core/svg-text.d.ts.map +1 -0
  103. package/dist/hoi4_agent_tools/core/svg-text.js +127 -0
  104. package/dist/hoi4_agent_tools/core/svg-text.js.map +1 -0
  105. package/dist/hoi4_agent_tools/core/transaction-limits.d.ts +9 -0
  106. package/dist/hoi4_agent_tools/core/transaction-limits.d.ts.map +1 -0
  107. package/dist/hoi4_agent_tools/core/transaction-limits.js +9 -0
  108. package/dist/hoi4_agent_tools/core/transaction-limits.js.map +1 -0
  109. package/dist/hoi4_agent_tools/core/transactions.d.ts +162 -0
  110. package/dist/hoi4_agent_tools/core/transactions.d.ts.map +1 -0
  111. package/dist/hoi4_agent_tools/core/transactions.js +1181 -0
  112. package/dist/hoi4_agent_tools/core/transactions.js.map +1 -0
  113. package/dist/hoi4_agent_tools/core/workspace.d.ts +68 -0
  114. package/dist/hoi4_agent_tools/core/workspace.d.ts.map +1 -0
  115. package/dist/hoi4_agent_tools/core/workspace.js +794 -0
  116. package/dist/hoi4_agent_tools/core/workspace.js.map +1 -0
  117. package/dist/hoi4_agent_tools/focus/compiler.d.ts +9 -0
  118. package/dist/hoi4_agent_tools/focus/compiler.d.ts.map +1 -0
  119. package/dist/hoi4_agent_tools/focus/compiler.js +273 -0
  120. package/dist/hoi4_agent_tools/focus/compiler.js.map +1 -0
  121. package/dist/hoi4_agent_tools/focus/continuous-render.d.ts +32 -0
  122. package/dist/hoi4_agent_tools/focus/continuous-render.d.ts.map +1 -0
  123. package/dist/hoi4_agent_tools/focus/continuous-render.js +179 -0
  124. package/dist/hoi4_agent_tools/focus/continuous-render.js.map +1 -0
  125. package/dist/hoi4_agent_tools/focus/drift.d.ts +22 -0
  126. package/dist/hoi4_agent_tools/focus/drift.d.ts.map +1 -0
  127. package/dist/hoi4_agent_tools/focus/drift.js +124 -0
  128. package/dist/hoi4_agent_tools/focus/drift.js.map +1 -0
  129. package/dist/hoi4_agent_tools/focus/geometry.d.ts +17 -0
  130. package/dist/hoi4_agent_tools/focus/geometry.d.ts.map +1 -0
  131. package/dist/hoi4_agent_tools/focus/geometry.js +35 -0
  132. package/dist/hoi4_agent_tools/focus/geometry.js.map +1 -0
  133. package/dist/hoi4_agent_tools/focus/importer.d.ts +9 -0
  134. package/dist/hoi4_agent_tools/focus/importer.d.ts.map +1 -0
  135. package/dist/hoi4_agent_tools/focus/importer.js +732 -0
  136. package/dist/hoi4_agent_tools/focus/importer.js.map +1 -0
  137. package/dist/hoi4_agent_tools/focus/index.d.ts +14 -0
  138. package/dist/hoi4_agent_tools/focus/index.d.ts.map +1 -0
  139. package/dist/hoi4_agent_tools/focus/index.js +14 -0
  140. package/dist/hoi4_agent_tools/focus/index.js.map +1 -0
  141. package/dist/hoi4_agent_tools/focus/layout.d.ts +5 -0
  142. package/dist/hoi4_agent_tools/focus/layout.d.ts.map +1 -0
  143. package/dist/hoi4_agent_tools/focus/layout.js +653 -0
  144. package/dist/hoi4_agent_tools/focus/layout.js.map +1 -0
  145. package/dist/hoi4_agent_tools/focus/limits.d.ts +9 -0
  146. package/dist/hoi4_agent_tools/focus/limits.d.ts.map +1 -0
  147. package/dist/hoi4_agent_tools/focus/limits.js +9 -0
  148. package/dist/hoi4_agent_tools/focus/limits.js.map +1 -0
  149. package/dist/hoi4_agent_tools/focus/lint.d.ts +14 -0
  150. package/dist/hoi4_agent_tools/focus/lint.d.ts.map +1 -0
  151. package/dist/hoi4_agent_tools/focus/lint.js +839 -0
  152. package/dist/hoi4_agent_tools/focus/lint.js.map +1 -0
  153. package/dist/hoi4_agent_tools/focus/model.d.ts +303 -0
  154. package/dist/hoi4_agent_tools/focus/model.d.ts.map +1 -0
  155. package/dist/hoi4_agent_tools/focus/model.js +20 -0
  156. package/dist/hoi4_agent_tools/focus/model.js.map +1 -0
  157. package/dist/hoi4_agent_tools/focus/native-effects.d.ts +9 -0
  158. package/dist/hoi4_agent_tools/focus/native-effects.d.ts.map +1 -0
  159. package/dist/hoi4_agent_tools/focus/native-effects.js +563 -0
  160. package/dist/hoi4_agent_tools/focus/native-effects.js.map +1 -0
  161. package/dist/hoi4_agent_tools/focus/planning.d.ts +15 -0
  162. package/dist/hoi4_agent_tools/focus/planning.d.ts.map +1 -0
  163. package/dist/hoi4_agent_tools/focus/planning.js +241 -0
  164. package/dist/hoi4_agent_tools/focus/planning.js.map +1 -0
  165. package/dist/hoi4_agent_tools/focus/presentation.d.ts +24 -0
  166. package/dist/hoi4_agent_tools/focus/presentation.d.ts.map +1 -0
  167. package/dist/hoi4_agent_tools/focus/presentation.js +204 -0
  168. package/dist/hoi4_agent_tools/focus/presentation.js.map +1 -0
  169. package/dist/hoi4_agent_tools/focus/render.d.ts +35 -0
  170. package/dist/hoi4_agent_tools/focus/render.d.ts.map +1 -0
  171. package/dist/hoi4_agent_tools/focus/render.js +491 -0
  172. package/dist/hoi4_agent_tools/focus/render.js.map +1 -0
  173. package/dist/hoi4_agent_tools/focus/service.d.ts +82 -0
  174. package/dist/hoi4_agent_tools/focus/service.d.ts.map +1 -0
  175. package/dist/hoi4_agent_tools/focus/service.js +492 -0
  176. package/dist/hoi4_agent_tools/focus/service.js.map +1 -0
  177. package/dist/hoi4_agent_tools/focus/source-update.d.ts +6 -0
  178. package/dist/hoi4_agent_tools/focus/source-update.d.ts.map +1 -0
  179. package/dist/hoi4_agent_tools/focus/source-update.js +328 -0
  180. package/dist/hoi4_agent_tools/focus/source-update.js.map +1 -0
  181. package/dist/hoi4_agent_tools/gui/animation-manifest.d.ts +37 -0
  182. package/dist/hoi4_agent_tools/gui/animation-manifest.d.ts.map +1 -0
  183. package/dist/hoi4_agent_tools/gui/animation-manifest.js +66 -0
  184. package/dist/hoi4_agent_tools/gui/animation-manifest.js.map +1 -0
  185. package/dist/hoi4_agent_tools/gui/assets.d.ts +71 -0
  186. package/dist/hoi4_agent_tools/gui/assets.d.ts.map +1 -0
  187. package/dist/hoi4_agent_tools/gui/assets.js +629 -0
  188. package/dist/hoi4_agent_tools/gui/assets.js.map +1 -0
  189. package/dist/hoi4_agent_tools/gui/dds.d.ts +17 -0
  190. package/dist/hoi4_agent_tools/gui/dds.d.ts.map +1 -0
  191. package/dist/hoi4_agent_tools/gui/dds.js +245 -0
  192. package/dist/hoi4_agent_tools/gui/dds.js.map +1 -0
  193. package/dist/hoi4_agent_tools/gui/helpers.d.ts +101 -0
  194. package/dist/hoi4_agent_tools/gui/helpers.d.ts.map +1 -0
  195. package/dist/hoi4_agent_tools/gui/helpers.js +1072 -0
  196. package/dist/hoi4_agent_tools/gui/helpers.js.map +1 -0
  197. package/dist/hoi4_agent_tools/gui/index.d.ts +15 -0
  198. package/dist/hoi4_agent_tools/gui/index.d.ts.map +1 -0
  199. package/dist/hoi4_agent_tools/gui/index.js +15 -0
  200. package/dist/hoi4_agent_tools/gui/index.js.map +1 -0
  201. package/dist/hoi4_agent_tools/gui/layout.d.ts +6 -0
  202. package/dist/hoi4_agent_tools/gui/layout.d.ts.map +1 -0
  203. package/dist/hoi4_agent_tools/gui/layout.js +753 -0
  204. package/dist/hoi4_agent_tools/gui/layout.js.map +1 -0
  205. package/dist/hoi4_agent_tools/gui/limits.d.ts +25 -0
  206. package/dist/hoi4_agent_tools/gui/limits.d.ts.map +1 -0
  207. package/dist/hoi4_agent_tools/gui/limits.js +27 -0
  208. package/dist/hoi4_agent_tools/gui/limits.js.map +1 -0
  209. package/dist/hoi4_agent_tools/gui/renderer.d.ts +18 -0
  210. package/dist/hoi4_agent_tools/gui/renderer.d.ts.map +1 -0
  211. package/dist/hoi4_agent_tools/gui/renderer.js +388 -0
  212. package/dist/hoi4_agent_tools/gui/renderer.js.map +1 -0
  213. package/dist/hoi4_agent_tools/gui/scenario.d.ts +66 -0
  214. package/dist/hoi4_agent_tools/gui/scenario.d.ts.map +1 -0
  215. package/dist/hoi4_agent_tools/gui/scenario.js +191 -0
  216. package/dist/hoi4_agent_tools/gui/scenario.js.map +1 -0
  217. package/dist/hoi4_agent_tools/gui/source-graph.d.ts +7 -0
  218. package/dist/hoi4_agent_tools/gui/source-graph.d.ts.map +1 -0
  219. package/dist/hoi4_agent_tools/gui/source-graph.js +1074 -0
  220. package/dist/hoi4_agent_tools/gui/source-graph.js.map +1 -0
  221. package/dist/hoi4_agent_tools/gui/source-patch.d.ts +13 -0
  222. package/dist/hoi4_agent_tools/gui/source-patch.d.ts.map +1 -0
  223. package/dist/hoi4_agent_tools/gui/source-patch.js +90 -0
  224. package/dist/hoi4_agent_tools/gui/source-patch.js.map +1 -0
  225. package/dist/hoi4_agent_tools/gui/studio.d.ts +86 -0
  226. package/dist/hoi4_agent_tools/gui/studio.d.ts.map +1 -0
  227. package/dist/hoi4_agent_tools/gui/studio.js +830 -0
  228. package/dist/hoi4_agent_tools/gui/studio.js.map +1 -0
  229. package/dist/hoi4_agent_tools/gui/tga.d.ts +16 -0
  230. package/dist/hoi4_agent_tools/gui/tga.d.ts.map +1 -0
  231. package/dist/hoi4_agent_tools/gui/tga.js +157 -0
  232. package/dist/hoi4_agent_tools/gui/tga.js.map +1 -0
  233. package/dist/hoi4_agent_tools/gui/types.d.ts +322 -0
  234. package/dist/hoi4_agent_tools/gui/types.d.ts.map +1 -0
  235. package/dist/hoi4_agent_tools/gui/types.js +19 -0
  236. package/dist/hoi4_agent_tools/gui/types.js.map +1 -0
  237. package/dist/hoi4_agent_tools/gui/validators.d.ts +8 -0
  238. package/dist/hoi4_agent_tools/gui/validators.d.ts.map +1 -0
  239. package/dist/hoi4_agent_tools/gui/validators.js +951 -0
  240. package/dist/hoi4_agent_tools/gui/validators.js.map +1 -0
  241. package/dist/hoi4_agent_tools/map/bmp.d.ts +62 -0
  242. package/dist/hoi4_agent_tools/map/bmp.d.ts.map +1 -0
  243. package/dist/hoi4_agent_tools/map/bmp.js +363 -0
  244. package/dist/hoi4_agent_tools/map/bmp.js.map +1 -0
  245. package/dist/hoi4_agent_tools/map/diagnostic-limit.d.ts +5 -0
  246. package/dist/hoi4_agent_tools/map/diagnostic-limit.d.ts.map +1 -0
  247. package/dist/hoi4_agent_tools/map/diagnostic-limit.js +21 -0
  248. package/dist/hoi4_agent_tools/map/diagnostic-limit.js.map +1 -0
  249. package/dist/hoi4_agent_tools/map/index.d.ts +8 -0
  250. package/dist/hoi4_agent_tools/map/index.d.ts.map +1 -0
  251. package/dist/hoi4_agent_tools/map/index.js +8 -0
  252. package/dist/hoi4_agent_tools/map/index.js.map +1 -0
  253. package/dist/hoi4_agent_tools/map/limits.d.ts +13 -0
  254. package/dist/hoi4_agent_tools/map/limits.d.ts.map +1 -0
  255. package/dist/hoi4_agent_tools/map/limits.js +13 -0
  256. package/dist/hoi4_agent_tools/map/limits.js.map +1 -0
  257. package/dist/hoi4_agent_tools/map/model.d.ts +269 -0
  258. package/dist/hoi4_agent_tools/map/model.d.ts.map +1 -0
  259. package/dist/hoi4_agent_tools/map/model.js +1114 -0
  260. package/dist/hoi4_agent_tools/map/model.js.map +1 -0
  261. package/dist/hoi4_agent_tools/map/operations.d.ts +401 -0
  262. package/dist/hoi4_agent_tools/map/operations.d.ts.map +1 -0
  263. package/dist/hoi4_agent_tools/map/operations.js +2717 -0
  264. package/dist/hoi4_agent_tools/map/operations.js.map +1 -0
  265. package/dist/hoi4_agent_tools/map/render.d.ts +90 -0
  266. package/dist/hoi4_agent_tools/map/render.d.ts.map +1 -0
  267. package/dist/hoi4_agent_tools/map/render.js +759 -0
  268. package/dist/hoi4_agent_tools/map/render.js.map +1 -0
  269. package/dist/hoi4_agent_tools/map/service.d.ts +81 -0
  270. package/dist/hoi4_agent_tools/map/service.d.ts.map +1 -0
  271. package/dist/hoi4_agent_tools/map/service.js +695 -0
  272. package/dist/hoi4_agent_tools/map/service.js.map +1 -0
  273. package/dist/hoi4_agent_tools/map/validation.d.ts +23 -0
  274. package/dist/hoi4_agent_tools/map/validation.d.ts.map +1 -0
  275. package/dist/hoi4_agent_tools/map/validation.js +1177 -0
  276. package/dist/hoi4_agent_tools/map/validation.js.map +1 -0
  277. package/dist/hoi4_agent_tools/mcp/prompts/register.d.ts +3 -0
  278. package/dist/hoi4_agent_tools/mcp/prompts/register.d.ts.map +1 -0
  279. package/dist/hoi4_agent_tools/mcp/prompts/register.js +50 -0
  280. package/dist/hoi4_agent_tools/mcp/prompts/register.js.map +1 -0
  281. package/dist/hoi4_agent_tools/mcp/registry/metadata.d.ts +9 -0
  282. package/dist/hoi4_agent_tools/mcp/registry/metadata.d.ts.map +1 -0
  283. package/dist/hoi4_agent_tools/mcp/registry/metadata.js +10 -0
  284. package/dist/hoi4_agent_tools/mcp/registry/metadata.js.map +1 -0
  285. package/dist/hoi4_agent_tools/mcp/resources/register.d.ts +5 -0
  286. package/dist/hoi4_agent_tools/mcp/resources/register.d.ts.map +1 -0
  287. package/dist/hoi4_agent_tools/mcp/resources/register.js +278 -0
  288. package/dist/hoi4_agent_tools/mcp/resources/register.js.map +1 -0
  289. package/dist/hoi4_agent_tools/mcp/security/auth.d.ts +24 -0
  290. package/dist/hoi4_agent_tools/mcp/security/auth.d.ts.map +1 -0
  291. package/dist/hoi4_agent_tools/mcp/security/auth.js +234 -0
  292. package/dist/hoi4_agent_tools/mcp/security/auth.js.map +1 -0
  293. package/dist/hoi4_agent_tools/mcp/server/base-tools.d.ts +35 -0
  294. package/dist/hoi4_agent_tools/mcp/server/base-tools.d.ts.map +1 -0
  295. package/dist/hoi4_agent_tools/mcp/server/base-tools.js +835 -0
  296. package/dist/hoi4_agent_tools/mcp/server/base-tools.js.map +1 -0
  297. package/dist/hoi4_agent_tools/mcp/server/create.d.ts +5 -0
  298. package/dist/hoi4_agent_tools/mcp/server/create.d.ts.map +1 -0
  299. package/dist/hoi4_agent_tools/mcp/server/create.js +26 -0
  300. package/dist/hoi4_agent_tools/mcp/server/create.js.map +1 -0
  301. package/dist/hoi4_agent_tools/mcp/server/output-schemas.d.ts +133 -0
  302. package/dist/hoi4_agent_tools/mcp/server/output-schemas.d.ts.map +1 -0
  303. package/dist/hoi4_agent_tools/mcp/server/output-schemas.js +127 -0
  304. package/dist/hoi4_agent_tools/mcp/server/output-schemas.js.map +1 -0
  305. package/dist/hoi4_agent_tools/mcp/server/progress.d.ts +8 -0
  306. package/dist/hoi4_agent_tools/mcp/server/progress.d.ts.map +1 -0
  307. package/dist/hoi4_agent_tools/mcp/server/progress.js +21 -0
  308. package/dist/hoi4_agent_tools/mcp/server/progress.js.map +1 -0
  309. package/dist/hoi4_agent_tools/mcp/server/result.d.ts +232 -0
  310. package/dist/hoi4_agent_tools/mcp/server/result.d.ts.map +1 -0
  311. package/dist/hoi4_agent_tools/mcp/server/result.js +353 -0
  312. package/dist/hoi4_agent_tools/mcp/server/result.js.map +1 -0
  313. package/dist/hoi4_agent_tools/mcp/tools/focus.d.ts +5 -0
  314. package/dist/hoi4_agent_tools/mcp/tools/focus.d.ts.map +1 -0
  315. package/dist/hoi4_agent_tools/mcp/tools/focus.js +1059 -0
  316. package/dist/hoi4_agent_tools/mcp/tools/focus.js.map +1 -0
  317. package/dist/hoi4_agent_tools/mcp/tools/gui.d.ts +111 -0
  318. package/dist/hoi4_agent_tools/mcp/tools/gui.d.ts.map +1 -0
  319. package/dist/hoi4_agent_tools/mcp/tools/gui.js +598 -0
  320. package/dist/hoi4_agent_tools/mcp/tools/gui.js.map +1 -0
  321. package/dist/hoi4_agent_tools/mcp/tools/map.d.ts +5 -0
  322. package/dist/hoi4_agent_tools/mcp/tools/map.d.ts.map +1 -0
  323. package/dist/hoi4_agent_tools/mcp/tools/map.js +685 -0
  324. package/dist/hoi4_agent_tools/mcp/tools/map.js.map +1 -0
  325. package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.d.ts +58 -0
  326. package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.d.ts.map +1 -0
  327. package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.js +181 -0
  328. package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.js.map +1 -0
  329. package/dist/hoi4_agent_tools/mcp/transports/event-store.d.ts +26 -0
  330. package/dist/hoi4_agent_tools/mcp/transports/event-store.d.ts.map +1 -0
  331. package/dist/hoi4_agent_tools/mcp/transports/event-store.js +86 -0
  332. package/dist/hoi4_agent_tools/mcp/transports/event-store.js.map +1 -0
  333. package/dist/hoi4_agent_tools/mcp/transports/http.d.ts +28 -0
  334. package/dist/hoi4_agent_tools/mcp/transports/http.d.ts.map +1 -0
  335. package/dist/hoi4_agent_tools/mcp/transports/http.js +744 -0
  336. package/dist/hoi4_agent_tools/mcp/transports/http.js.map +1 -0
  337. package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.d.ts +15 -0
  338. package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.d.ts.map +1 -0
  339. package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.js +51 -0
  340. package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.js.map +1 -0
  341. package/dist/hoi4_agent_tools/runtime.d.ts +4 -0
  342. package/dist/hoi4_agent_tools/runtime.d.ts.map +1 -0
  343. package/dist/hoi4_agent_tools/runtime.js +27 -0
  344. package/dist/hoi4_agent_tools/runtime.js.map +1 -0
  345. package/dist/hoi4_agent_tools/schemas/common.d.ts +74 -0
  346. package/dist/hoi4_agent_tools/schemas/common.d.ts.map +1 -0
  347. package/dist/hoi4_agent_tools/schemas/common.js +51 -0
  348. package/dist/hoi4_agent_tools/schemas/common.js.map +1 -0
  349. package/dist/hoi4_agent_tools/schemas/focus.d.ts +784 -0
  350. package/dist/hoi4_agent_tools/schemas/focus.d.ts.map +1 -0
  351. package/dist/hoi4_agent_tools/schemas/focus.js +330 -0
  352. package/dist/hoi4_agent_tools/schemas/focus.js.map +1 -0
  353. package/dist/hoi4_agent_tools/schemas/index.d.ts +5 -0
  354. package/dist/hoi4_agent_tools/schemas/index.d.ts.map +1 -0
  355. package/dist/hoi4_agent_tools/schemas/index.js +5 -0
  356. package/dist/hoi4_agent_tools/schemas/index.js.map +1 -0
  357. package/dist/hoi4_agent_tools/schemas/map.d.ts +654 -0
  358. package/dist/hoi4_agent_tools/schemas/map.d.ts.map +1 -0
  359. package/dist/hoi4_agent_tools/schemas/map.js +570 -0
  360. package/dist/hoi4_agent_tools/schemas/map.js.map +1 -0
  361. package/dist/hoi4_agent_tools/schemas/transaction.d.ts +259 -0
  362. package/dist/hoi4_agent_tools/schemas/transaction.d.ts.map +1 -0
  363. package/dist/hoi4_agent_tools/schemas/transaction.js +104 -0
  364. package/dist/hoi4_agent_tools/schemas/transaction.js.map +1 -0
  365. package/dist/hoi4_agent_tools/version.d.ts +6 -0
  366. package/dist/hoi4_agent_tools/version.d.ts.map +1 -0
  367. package/dist/hoi4_agent_tools/version.js +7 -0
  368. package/dist/hoi4_agent_tools/version.js.map +1 -0
  369. package/dist/index.d.ts +3 -0
  370. package/dist/index.d.ts.map +1 -0
  371. package/dist/index.js +3 -0
  372. package/dist/index.js.map +1 -0
  373. package/docs/README.md +22 -0
  374. package/docs/adr/0001-runtime-and-language.md +16 -0
  375. package/docs/adr/0002-lossless-source-model.md +18 -0
  376. package/docs/adr/0003-image-and-font-codecs.md +18 -0
  377. package/docs/adr/0004-focus-layout.md +16 -0
  378. package/docs/adr/0005-offline-rendering.md +18 -0
  379. package/docs/adr/0006-mcp-sdk-and-protocol.md +16 -0
  380. package/docs/adr/0007-storage-and-transactions.md +24 -0
  381. package/docs/adr/0008-test-strategy.md +18 -0
  382. package/docs/adr/0009-packaging-and-registry.md +16 -0
  383. package/docs/adr/0010-unsupported-and-refusal-policy.md +18 -0
  384. package/docs/adr/0011-http-security.md +16 -0
  385. package/docs/adr/README.md +13 -0
  386. package/docs/architecture.md +60 -0
  387. package/docs/artifacts.md +133 -0
  388. package/docs/compatibility.md +33 -0
  389. package/docs/completion-report.md +69 -0
  390. package/docs/configuration.md +285 -0
  391. package/docs/focus-workflow.md +68 -0
  392. package/docs/gui-workflow.md +121 -0
  393. package/docs/limitations.md +30 -0
  394. package/docs/map-workflow.md +89 -0
  395. package/docs/performance.md +117 -0
  396. package/docs/release.md +200 -0
  397. package/docs/research/mcp-2026-07-10.md +46 -0
  398. package/docs/research/source-ledger.md +68 -0
  399. package/docs/security.md +139 -0
  400. package/docs/self-hosting.md +168 -0
  401. package/docs/testing.md +43 -0
  402. package/docs/third-party-notices.md +11 -0
  403. package/docs/transactions.md +162 -0
  404. package/docs/troubleshooting.md +46 -0
  405. package/package.json +98 -5
  406. package/schemas/configuration.schema.json +794 -0
  407. package/schemas/continuous-focus-palette.schema.json +325 -0
  408. package/schemas/focus-plan.schema.json +902 -0
  409. package/schemas/focus-planning-sidecar.schema.json +364 -0
  410. package/schemas/gui-animation-source.schema.json +176 -0
  411. package/schemas/gui-helper.schema.json +301 -0
  412. package/schemas/gui-scenario.schema.json +298 -0
  413. package/schemas/map-operation.schema.json +2284 -0
  414. package/schemas/operation-result.schema.json +344 -0
  415. package/schemas/transaction-manifest.schema.json +685 -0
  416. package/server.json +32 -0
@@ -0,0 +1,1114 @@
1
+ import { compareCodeUnits } from '../core/canonical.js';
2
+ import path from 'node:path';
3
+ import { SymbolIndex } from '../core/index.js';
4
+ import { assertRenderDimensions } from '../core/render-budget.js';
5
+ import { addMapDiagnostic, addMapDiagnostics } from './diagnostic-limit.js';
6
+ import { ServiceError } from '../core/result.js';
7
+ import { assignments, childBlocks, decodeSource, encodeSource, firstScalar, nodeLocation, parseClausewitz, parseLocalisation, } from '../core/source/index.js';
8
+ import { BmpImage, rgbKey } from './bmp.js';
9
+ const defaultMapIndexSourceRoots = {
10
+ map: ['map'],
11
+ states: ['history/states'],
12
+ localisation: ['localisation', 'localisation_synced'],
13
+ };
14
+ export function derivedStateCapital(victoryPoints) {
15
+ return victoryPoints
16
+ .slice()
17
+ .sort((left, right) => right.value - left.value || left.provinceId - right.provinceId)[0]
18
+ ?.provinceId;
19
+ }
20
+ export const MAP_PROVINCE_ENGINE_MAX_PIXELS = 13_238_272;
21
+ export const MAP_TEXT_MAX_BYTES = 16_777_216;
22
+ export const MAP_TEXT_MAX_RECORDS = 500_000;
23
+ const MAP_TEXT_FIELD_LIMIT = 10_000;
24
+ const MAP_MODEL_MAX_SCRIPT_FILES = 5_000;
25
+ const MAP_MODEL_MAX_SOURCE_TOKENS = 1_000_000;
26
+ const MAP_MODEL_MAX_RECORDS = 500_000;
27
+ const MAP_MODEL_MAX_MEMBERSHIP_EDGES = 1_000_000;
28
+ class MapModelBudget {
29
+ #documents = new Set();
30
+ #tokens = 0;
31
+ #records = 0;
32
+ #membershipEdges = 0;
33
+ assertScriptFiles(count) {
34
+ if (count > MAP_MODEL_MAX_SCRIPT_FILES) {
35
+ this.block('script files', count, MAP_MODEL_MAX_SCRIPT_FILES);
36
+ }
37
+ }
38
+ addDocument(document) {
39
+ if (this.#documents.has(document.path))
40
+ return;
41
+ this.#documents.add(document.path);
42
+ this.#tokens += document.tokens.length;
43
+ if (this.#tokens > MAP_MODEL_MAX_SOURCE_TOKENS) {
44
+ this.block('retained source tokens', this.#tokens, MAP_MODEL_MAX_SOURCE_TOKENS);
45
+ }
46
+ }
47
+ addRecords(count) {
48
+ this.#records += count;
49
+ if (!Number.isSafeInteger(this.#records) || this.#records > MAP_MODEL_MAX_RECORDS) {
50
+ this.block('domain records', this.#records, MAP_MODEL_MAX_RECORDS);
51
+ }
52
+ }
53
+ addMembershipEdges(count) {
54
+ this.#membershipEdges += count;
55
+ if (!Number.isSafeInteger(this.#membershipEdges) ||
56
+ this.#membershipEdges > MAP_MODEL_MAX_MEMBERSHIP_EDGES) {
57
+ this.block('membership edges', this.#membershipEdges, MAP_MODEL_MAX_MEMBERSHIP_EDGES);
58
+ }
59
+ }
60
+ block(kind, observed, limit) {
61
+ throw new ServiceError('MAP_MODEL_BUDGET_BLOCKED', `Map workspace model exceeds the fixed ${kind} ceiling`, { kind, observed, limit });
62
+ }
63
+ }
64
+ function normalizedPath(value) {
65
+ return value.replaceAll('\\', '/').replace(/^\.\//u, '').toLowerCase();
66
+ }
67
+ /** Selects the one loaded file for each relative filename, while retaining separate database files. */
68
+ export function selectActiveFiles(files) {
69
+ const byRelativePath = new Map();
70
+ for (const file of [...files].sort((left, right) => {
71
+ const load = left.loadOrder - right.loadOrder;
72
+ return load !== 0 ? load : compareCodeUnits(left.displayPath, right.displayPath);
73
+ })) {
74
+ byRelativePath.set(normalizedPath(file.relativePath), file);
75
+ }
76
+ const all = [...byRelativePath.values()].sort((left, right) => left.loadOrder - right.loadOrder || compareCodeUnits(left.relativePath, right.relativePath));
77
+ return { all, byRelativePath };
78
+ }
79
+ export function parseTextDocument(file) {
80
+ if (file.bytes.length > MAP_TEXT_MAX_BYTES) {
81
+ throw new ServiceError('MAP_TEXT_FILE_LIMIT', 'Map text table exceeds the supported 16 MiB parsing limit', { bytes: file.bytes.length, maximumBytes: MAP_TEXT_MAX_BYTES });
82
+ }
83
+ const decoded = decodeSource(file.bytes);
84
+ const lines = [];
85
+ const matcher = /.*(?:\r\n|\n|\r|$)/gu;
86
+ let match;
87
+ let index = 0;
88
+ while ((match = matcher.exec(decoded.text)) !== null) {
89
+ if (match[0] === '' && matcher.lastIndex === decoded.text.length)
90
+ break;
91
+ const full = match[0];
92
+ const text = full.replace(/(?:\r\n|\n|\r)$/u, '');
93
+ const start = match.index;
94
+ if (index >= MAP_TEXT_MAX_RECORDS) {
95
+ throw new ServiceError('MAP_TEXT_RECORD_LIMIT', 'Map text table exceeds the supported record limit', { records: index + 1, maximumRecords: MAP_TEXT_MAX_RECORDS });
96
+ }
97
+ lines.push({ index, start, end: start + text.length, fullEnd: start + full.length, text });
98
+ index += 1;
99
+ if (full.length === 0)
100
+ break;
101
+ }
102
+ return { ...decoded, file, lines };
103
+ }
104
+ export function encodeTextDocument(document, text) {
105
+ return encodeSource(text, document.encoding);
106
+ }
107
+ function lineLocation(document, line) {
108
+ return {
109
+ path: document.file.displayPath,
110
+ start: { line: line.index + 1, column: 1, offset: line.start },
111
+ end: { line: line.index + 1, column: line.text.length + 1, offset: line.end },
112
+ };
113
+ }
114
+ function splitDelimitedRow(value, maximumParts) {
115
+ const parts = [];
116
+ let start = 0;
117
+ while (parts.length + 1 < maximumParts) {
118
+ const next = value.indexOf(';', start);
119
+ if (next < 0)
120
+ break;
121
+ parts.push(value.slice(start, next).trim());
122
+ start = next + 1;
123
+ }
124
+ parts.push(value.slice(start).trim());
125
+ return parts;
126
+ }
127
+ function whitespaceRow(document, line, diagnostics) {
128
+ const comment = line.text.indexOf('#');
129
+ const value = (comment < 0 ? line.text : line.text.slice(0, comment)).trim();
130
+ if (value === '')
131
+ return [];
132
+ const fields = [];
133
+ const matcher = /\S+/gu;
134
+ let match;
135
+ while ((match = matcher.exec(value)) !== null) {
136
+ if (fields.length >= MAP_TEXT_FIELD_LIMIT) {
137
+ addMapDiagnostic(diagnostics, {
138
+ code: 'MAP_TEXT_FIELD_LIMIT',
139
+ severity: 'blocker',
140
+ category: 'map',
141
+ message: 'Map text-table row exceeds the fixed field limit',
142
+ location: lineLocation(document, line),
143
+ details: { limit: MAP_TEXT_FIELD_LIMIT },
144
+ });
145
+ return undefined;
146
+ }
147
+ fields.push(match[0]);
148
+ }
149
+ return fields;
150
+ }
151
+ function parseInteger(value) {
152
+ if (value === undefined || !/^-?\d+$/u.test(value.trim()))
153
+ return undefined;
154
+ const parsed = Number(value);
155
+ return Number.isSafeInteger(parsed) ? parsed : undefined;
156
+ }
157
+ function parseNumber(value) {
158
+ if (value === undefined || !/^-?(?:\d+(?:\.\d*)?|\.\d+)$/u.test(value.trim()))
159
+ return undefined;
160
+ const parsed = Number(value);
161
+ return Number.isFinite(parsed) ? parsed : undefined;
162
+ }
163
+ function requiredNumber(values, index, label) {
164
+ const value = values[index];
165
+ if (value === undefined) {
166
+ throw new ServiceError('MAP_PARSED_NUMBER_MISSING', `${label} is missing after row validation`);
167
+ }
168
+ return value;
169
+ }
170
+ function scalarList(block) {
171
+ if (block === undefined)
172
+ return [];
173
+ return block.entries.filter((entry) => entry.type === 'scalar').map((entry) => entry.value);
174
+ }
175
+ function numericMap(block) {
176
+ const result = new Map();
177
+ if (block === undefined)
178
+ return result;
179
+ for (const assignment of assignments(block)) {
180
+ if (assignment.value.type !== 'scalar')
181
+ continue;
182
+ const value = parseNumber(assignment.value.value);
183
+ if (value !== undefined)
184
+ result.set(assignment.key.value, value);
185
+ }
186
+ return result;
187
+ }
188
+ function directBlock(block, key) {
189
+ return childBlocks(block, key)[0];
190
+ }
191
+ function firstTopLevelAssignment(document, key) {
192
+ return assignments(document.root, key)[0];
193
+ }
194
+ export function parseDefinitions(file, diagnostics) {
195
+ const document = parseTextDocument(file);
196
+ const definitions = [];
197
+ for (const line of document.lines) {
198
+ const trimmed = line.text.trim();
199
+ if (trimmed === '' || trimmed.startsWith('#'))
200
+ continue;
201
+ const parts = splitDelimitedRow(line.text, 9);
202
+ if (parts.length < 8) {
203
+ addMapDiagnostic(diagnostics, {
204
+ code: 'MAP_DEFINITION_ROW_MALFORMED',
205
+ severity: 'error',
206
+ category: 'map',
207
+ message: 'Province definition row must contain eight semicolon-separated fields',
208
+ location: lineLocation(document, line),
209
+ });
210
+ continue;
211
+ }
212
+ const id = parseInteger(parts[0]);
213
+ const red = parseInteger(parts[1]);
214
+ const green = parseInteger(parts[2]);
215
+ const blue = parseInteger(parts[3]);
216
+ const continent = parseInteger(parts[7]);
217
+ if (id === undefined ||
218
+ red === undefined ||
219
+ green === undefined ||
220
+ blue === undefined ||
221
+ continent === undefined ||
222
+ id < 0 ||
223
+ id > 2_147_483_647 ||
224
+ continent < 0 ||
225
+ continent > 2_147_483_647 ||
226
+ red < 0 ||
227
+ red > 255 ||
228
+ green < 0 ||
229
+ green > 255 ||
230
+ blue < 0 ||
231
+ blue > 255) {
232
+ addMapDiagnostic(diagnostics, {
233
+ code: 'MAP_DEFINITION_VALUE_INVALID',
234
+ severity: 'error',
235
+ category: 'map',
236
+ message: 'Province definition contains an invalid ID, color, or continent',
237
+ location: lineLocation(document, line),
238
+ });
239
+ continue;
240
+ }
241
+ definitions.push({
242
+ id,
243
+ color: { r: red, g: green, b: blue },
244
+ type: parts[4] ?? '',
245
+ coastal: parts[5]?.toLowerCase() === 'true',
246
+ terrain: parts[6] ?? '',
247
+ continent,
248
+ line: line.index + 1,
249
+ document,
250
+ });
251
+ }
252
+ return definitions;
253
+ }
254
+ export function parseState(file, diagnostics) {
255
+ const document = parseClausewitz(file.bytes, file.displayPath);
256
+ addMapDiagnostics(diagnostics, document.diagnostics);
257
+ const assignment = firstTopLevelAssignment(document, 'state');
258
+ if (assignment?.value.type !== 'block')
259
+ return undefined;
260
+ const block = assignment.value;
261
+ const idScalar = firstScalar(block, 'id');
262
+ const id = parseInteger(idScalar?.value);
263
+ if (id === undefined || id <= 0 || id > 2_147_483_647) {
264
+ addMapDiagnostic(diagnostics, {
265
+ code: idScalar === undefined ? 'MAP_STATE_ID_MISSING' : 'MAP_STATE_ID_INVALID',
266
+ severity: 'error',
267
+ category: 'map',
268
+ message: idScalar === undefined
269
+ ? 'State file has no integer ID'
270
+ : 'State ID must be a positive signed 32-bit integer',
271
+ location: nodeLocation(document, assignment),
272
+ });
273
+ return undefined;
274
+ }
275
+ const provincesBlock = directBlock(block, 'provinces');
276
+ const provinces = scalarList(provincesBlock).flatMap((value) => {
277
+ const parsed = parseInteger(value);
278
+ return parsed === undefined ? [] : [parsed];
279
+ });
280
+ const historyBlock = directBlock(block, 'history');
281
+ const resourcesBlock = directBlock(block, 'resources');
282
+ const buildingsBlock = historyBlock === undefined ? undefined : directBlock(historyBlock, 'buildings');
283
+ const provinceBuildings = new Map();
284
+ const stateBuildings = new Map();
285
+ if (buildingsBlock !== undefined) {
286
+ for (const entry of assignments(buildingsBlock)) {
287
+ if (entry.value.type === 'block') {
288
+ const province = parseInteger(entry.key.value);
289
+ if (province !== undefined)
290
+ provinceBuildings.set(province, numericMap(entry.value));
291
+ }
292
+ else {
293
+ const level = parseNumber(entry.value.value);
294
+ if (level !== undefined)
295
+ stateBuildings.set(entry.key.value, level);
296
+ }
297
+ }
298
+ }
299
+ const victoryPoints = [];
300
+ if (historyBlock !== undefined) {
301
+ for (const entry of assignments(historyBlock, 'victory_points')) {
302
+ if (entry.value.type !== 'block')
303
+ continue;
304
+ const values = scalarList(entry.value);
305
+ const provinceId = parseInteger(values[0]);
306
+ const value = parseNumber(values[1]);
307
+ if (provinceId !== undefined && value !== undefined) {
308
+ victoryPoints.push({ provinceId, value, assignment: entry });
309
+ }
310
+ }
311
+ }
312
+ const owner = firstScalar(historyBlock ?? block, 'owner')?.value;
313
+ const controller = firstScalar(historyBlock ?? block, 'controller')?.value;
314
+ const capital = derivedStateCapital(victoryPoints);
315
+ return {
316
+ id,
317
+ name: firstScalar(block, 'name')?.value ?? `STATE_${id}`,
318
+ ...(capital === undefined ? {} : { capital }),
319
+ manpower: parseNumber(firstScalar(block, 'manpower')?.value) ?? 0,
320
+ category: firstScalar(block, 'state_category')?.value ?? '',
321
+ provinces,
322
+ resources: numericMap(resourcesBlock),
323
+ ...(owner === undefined ? {} : { owner }),
324
+ ...(controller === undefined ? {} : { controller }),
325
+ cores: historyBlock === undefined
326
+ ? []
327
+ : assignments(historyBlock, 'add_core_of').flatMap(({ value }) => value.type === 'scalar' ? [value.value] : []),
328
+ claims: historyBlock === undefined
329
+ ? []
330
+ : assignments(historyBlock, 'add_claim_by').flatMap(({ value }) => value.type === 'scalar' ? [value.value] : []),
331
+ victoryPoints,
332
+ provinceBuildings,
333
+ stateBuildings,
334
+ file,
335
+ document,
336
+ assignment,
337
+ block,
338
+ ...(provincesBlock === undefined ? {} : { provincesBlock }),
339
+ ...(historyBlock === undefined ? {} : { historyBlock }),
340
+ ...(resourcesBlock === undefined ? {} : { resourcesBlock }),
341
+ ...(buildingsBlock === undefined ? {} : { buildingsBlock }),
342
+ };
343
+ }
344
+ export function parseStrategicRegion(file, diagnostics) {
345
+ const document = parseClausewitz(file.bytes, file.displayPath);
346
+ addMapDiagnostics(diagnostics, document.diagnostics);
347
+ const assignment = firstTopLevelAssignment(document, 'strategic_region') ??
348
+ firstTopLevelAssignment(document, 'strategic_region_template');
349
+ if (assignment?.value.type !== 'block')
350
+ return undefined;
351
+ const block = assignment.value;
352
+ const idScalar = firstScalar(block, 'id');
353
+ const id = parseInteger(idScalar?.value);
354
+ if (id === undefined || id <= 0 || id > 2_147_483_647) {
355
+ addMapDiagnostic(diagnostics, {
356
+ code: idScalar === undefined ? 'MAP_REGION_ID_MISSING' : 'MAP_REGION_ID_INVALID',
357
+ severity: 'error',
358
+ category: 'map',
359
+ message: idScalar === undefined
360
+ ? 'Strategic region has no integer ID'
361
+ : 'Strategic-region ID must be a positive signed 32-bit integer',
362
+ location: nodeLocation(document, assignment),
363
+ });
364
+ return undefined;
365
+ }
366
+ const provincesBlock = directBlock(block, 'provinces');
367
+ const navalTerrain = firstScalar(block, 'naval_terrain')?.value;
368
+ return {
369
+ id,
370
+ name: firstScalar(block, 'name')?.value ?? `STRATEGICREGION_${id}`,
371
+ provinces: scalarList(provincesBlock).flatMap((value) => {
372
+ const parsed = parseInteger(value);
373
+ return parsed === undefined ? [] : [parsed];
374
+ }),
375
+ ...(navalTerrain === undefined ? {} : { navalTerrain }),
376
+ file,
377
+ document,
378
+ assignment,
379
+ block,
380
+ ...(provincesBlock === undefined ? {} : { provincesBlock }),
381
+ };
382
+ }
383
+ export function parseAdjacencies(file, diagnostics) {
384
+ const document = parseTextDocument(file);
385
+ const result = [];
386
+ let dataIndex = 0;
387
+ for (const line of document.lines) {
388
+ const trimmed = line.text.trim();
389
+ if (line.index === 0 || trimmed === '' || trimmed.startsWith('#'))
390
+ continue;
391
+ const parts = splitDelimitedRow(line.text, 10);
392
+ if (parts[0] === '-1')
393
+ break;
394
+ if (parts.length < 9) {
395
+ addMapDiagnostic(diagnostics, {
396
+ code: 'MAP_ADJACENCY_ROW_MALFORMED',
397
+ severity: 'error',
398
+ category: 'map',
399
+ message: 'Adjacency row has fewer than nine fields',
400
+ location: lineLocation(document, line),
401
+ });
402
+ continue;
403
+ }
404
+ const numbers = [0, 1, 3, 4, 5, 6, 7].map((index) => parseNumber(parts[index]));
405
+ if (numbers.some((value) => value === undefined)) {
406
+ addMapDiagnostic(diagnostics, {
407
+ code: 'MAP_ADJACENCY_VALUE_INVALID',
408
+ severity: 'error',
409
+ category: 'map',
410
+ message: 'Adjacency row contains a non-numeric province or coordinate field',
411
+ location: lineLocation(document, line),
412
+ });
413
+ continue;
414
+ }
415
+ const [from, to, through, startX, startY, stopX, stopY] = numbers;
416
+ result.push({
417
+ index: dataIndex,
418
+ from,
419
+ to,
420
+ type: (parts[2] ?? '') === '' ? 'sea' : (parts[2] ?? ''),
421
+ through,
422
+ startX,
423
+ startY,
424
+ stopX,
425
+ stopY,
426
+ rule: parts[8] ?? '',
427
+ comment: parts.slice(9).join(';'),
428
+ line: line.index + 1,
429
+ document,
430
+ });
431
+ dataIndex += 1;
432
+ }
433
+ return result;
434
+ }
435
+ function parseWhitespaceRows(file, diagnostics) {
436
+ const document = parseTextDocument(file);
437
+ return document.lines.flatMap((line) => {
438
+ const values = whitespaceRow(document, line, diagnostics);
439
+ return values === undefined || values.length === 0 ? [] : [{ line, values, document }];
440
+ });
441
+ }
442
+ export function parseSupplyNodes(file, diagnostics) {
443
+ return parseWhitespaceRows(file, diagnostics).flatMap(({ line, values, document }) => {
444
+ const level = parseInteger(values[0]);
445
+ const provinceId = parseInteger(values[1]);
446
+ if (values.length !== 2 || level === undefined || provinceId === undefined) {
447
+ addMapDiagnostic(diagnostics, {
448
+ code: 'MAP_SUPPLY_NODE_ROW_MALFORMED',
449
+ severity: 'error',
450
+ category: 'map',
451
+ message: 'Supply node row must be: level province',
452
+ location: lineLocation(document, line),
453
+ });
454
+ return [];
455
+ }
456
+ return [{ level, provinceId, line: line.index + 1, document }];
457
+ });
458
+ }
459
+ export function parseRailways(file, diagnostics) {
460
+ return parseWhitespaceRows(file, diagnostics).flatMap(({ line, values, document }) => {
461
+ const level = parseInteger(values[0]);
462
+ const declaredCount = parseInteger(values[1]);
463
+ const provinces = values.slice(2).map(parseInteger);
464
+ if (level === undefined ||
465
+ declaredCount === undefined ||
466
+ provinces.some((value) => value === undefined)) {
467
+ addMapDiagnostic(diagnostics, {
468
+ code: 'MAP_RAILWAY_ROW_MALFORMED',
469
+ severity: 'error',
470
+ category: 'map',
471
+ message: 'Railway row must contain an integer level, count, and province list',
472
+ location: lineLocation(document, line),
473
+ });
474
+ return [];
475
+ }
476
+ return [
477
+ {
478
+ level,
479
+ declaredCount,
480
+ provinces: provinces,
481
+ line: line.index + 1,
482
+ document,
483
+ },
484
+ ];
485
+ });
486
+ }
487
+ function parseDelimitedNumbers(file, expected, diagnostics, code) {
488
+ const document = parseTextDocument(file);
489
+ return document.lines.flatMap((line) => {
490
+ if (line.text.trim() === '' || line.text.trim().startsWith('#'))
491
+ return [];
492
+ const parts = splitDelimitedRow(line.text, expected + 1);
493
+ const numbers = parts.slice(0, expected).map(parseNumber);
494
+ if (parts.length < expected || numbers.some((value) => value === undefined)) {
495
+ addMapDiagnostic(diagnostics, {
496
+ code,
497
+ severity: 'error',
498
+ category: 'map',
499
+ message: `Position row must contain at least ${expected} semicolon-separated fields`,
500
+ location: lineLocation(document, line),
501
+ });
502
+ return [];
503
+ }
504
+ return [{ line, parts, numbers: numbers, document }];
505
+ });
506
+ }
507
+ export function parseBuildingPositions(file, diagnostics) {
508
+ const document = parseTextDocument(file);
509
+ return document.lines.flatMap((line) => {
510
+ if (line.text.trim() === '' || line.text.trim().startsWith('#'))
511
+ return [];
512
+ const parts = splitDelimitedRow(line.text, 8);
513
+ const stateId = parseInteger(parts[0]);
514
+ const numbers = parts.slice(2, 7).map(parseNumber);
515
+ if (parts.length < 7 ||
516
+ stateId === undefined ||
517
+ parts[1] === '' ||
518
+ numbers.some((value) => value === undefined)) {
519
+ addMapDiagnostic(diagnostics, {
520
+ code: 'MAP_BUILDING_POSITION_ROW_MALFORMED',
521
+ severity: 'error',
522
+ category: 'map',
523
+ message: 'Building position row is malformed',
524
+ location: lineLocation(document, line),
525
+ });
526
+ return [];
527
+ }
528
+ return [
529
+ {
530
+ stateId,
531
+ building: parts[1] ?? '',
532
+ x: requiredNumber(numbers, 0, 'building x'),
533
+ y: requiredNumber(numbers, 1, 'building y'),
534
+ z: requiredNumber(numbers, 2, 'building z'),
535
+ rotation: requiredNumber(numbers, 3, 'building rotation'),
536
+ adjacentSeaProvince: requiredNumber(numbers, 4, 'building adjacent sea'),
537
+ line: line.index + 1,
538
+ document,
539
+ },
540
+ ];
541
+ });
542
+ }
543
+ export function parseUnitPositions(file, diagnostics) {
544
+ return parseDelimitedNumbers(file, 7, diagnostics, 'MAP_UNIT_POSITION_ROW_MALFORMED').map(({ line, numbers, document }) => ({
545
+ provinceId: requiredNumber(numbers, 0, 'unit province'),
546
+ type: requiredNumber(numbers, 1, 'unit type'),
547
+ x: requiredNumber(numbers, 2, 'unit x'),
548
+ y: requiredNumber(numbers, 3, 'unit y'),
549
+ z: requiredNumber(numbers, 4, 'unit z'),
550
+ rotation: requiredNumber(numbers, 5, 'unit rotation'),
551
+ offset: requiredNumber(numbers, 6, 'unit offset'),
552
+ line: line.index + 1,
553
+ document,
554
+ }));
555
+ }
556
+ export function parseWeatherPositions(file, diagnostics) {
557
+ const document = parseTextDocument(file);
558
+ return document.lines.flatMap((line) => {
559
+ if (line.text.trim() === '' || line.text.trim().startsWith('#'))
560
+ return [];
561
+ const parts = splitDelimitedRow(line.text, 6);
562
+ const strategicRegionId = parseInteger(parts[0]);
563
+ const coordinates = parts.slice(1, 4).map(parseNumber);
564
+ if (parts.length < 5 ||
565
+ strategicRegionId === undefined ||
566
+ coordinates.some((value) => value === undefined) ||
567
+ parts[4] === '') {
568
+ addMapDiagnostic(diagnostics, {
569
+ code: 'MAP_WEATHER_POSITION_ROW_MALFORMED',
570
+ severity: 'error',
571
+ category: 'map',
572
+ message: 'Weather position row is malformed',
573
+ location: lineLocation(document, line),
574
+ });
575
+ return [];
576
+ }
577
+ return [
578
+ {
579
+ strategicRegionId,
580
+ x: requiredNumber(coordinates, 0, 'weather x'),
581
+ y: requiredNumber(coordinates, 1, 'weather y'),
582
+ z: requiredNumber(coordinates, 2, 'weather z'),
583
+ size: parts[4] ?? '',
584
+ line: line.index + 1,
585
+ document,
586
+ },
587
+ ];
588
+ });
589
+ }
590
+ export function parseEntityLocators(file, diagnostics) {
591
+ const document = parseClausewitz(file.bytes, file.displayPath);
592
+ addMapDiagnostics(diagnostics, document.diagnostics);
593
+ const result = [];
594
+ for (const entityAssignment of assignments(document.root, 'entity')) {
595
+ if (entityAssignment.value.type !== 'block')
596
+ continue;
597
+ const entity = firstScalar(entityAssignment.value, 'name')?.value;
598
+ if (entity === undefined)
599
+ continue;
600
+ for (const locator of assignments(entityAssignment.value, 'locator')) {
601
+ if (locator.value.type !== 'block')
602
+ continue;
603
+ const name = firstScalar(locator.value, 'name')?.value;
604
+ const positionBlock = directBlock(locator.value, 'position');
605
+ const values = scalarList(positionBlock).map(parseNumber);
606
+ if (name === undefined ||
607
+ positionBlock === undefined ||
608
+ values.length !== 3 ||
609
+ values.some((value) => value === undefined)) {
610
+ addMapDiagnostic(diagnostics, {
611
+ code: 'MAP_ENTITY_LOCATOR_MALFORMED',
612
+ severity: 'error',
613
+ category: 'map',
614
+ message: 'Entity locator must have a name and three-number position',
615
+ location: nodeLocation(document, locator, entity),
616
+ });
617
+ continue;
618
+ }
619
+ result.push({
620
+ entity,
621
+ name,
622
+ position: values,
623
+ file,
624
+ document,
625
+ assignment: locator,
626
+ positionBlock,
627
+ });
628
+ }
629
+ }
630
+ return result;
631
+ }
632
+ export function defaultMapSelectorValue(defaultMap, key, fallback) {
633
+ if (defaultMap === undefined)
634
+ return fallback;
635
+ const document = parseClausewitz(defaultMap.bytes, defaultMap.displayPath);
636
+ if (document.diagnostics.length > 0) {
637
+ const reasonCodes = [...new Set(document.diagnostics.map(({ code }) => code))].sort((left, right) => compareCodeUnits(left, right));
638
+ throw new ServiceError('MAP_DEFAULT_MAP_SELECTOR_BLOCKED', `The map selector cannot be trusted: ${defaultMap.displayPath}`, {
639
+ path: defaultMap.displayPath,
640
+ relativePath: defaultMap.relativePath,
641
+ rootKind: defaultMap.rootKind,
642
+ loadOrder: defaultMap.loadOrder,
643
+ reasonCodes,
644
+ diagnostics: document.diagnostics.map(({ code, severity, category, location }) => ({
645
+ code,
646
+ severity,
647
+ category,
648
+ ...(location === undefined ? {} : { location }),
649
+ })),
650
+ });
651
+ }
652
+ return firstScalar(document.root, key)?.value ?? fallback;
653
+ }
654
+ function fileByRelative(active, relativePath) {
655
+ return active.byRelativePath.get(normalizedPath(relativePath));
656
+ }
657
+ function normalizeConfiguredRoot(value) {
658
+ return normalizedPath(value).replace(/^\.\//u, '').replace(/\/$/u, '');
659
+ }
660
+ function inConfiguredRoot(relativePath, roots) {
661
+ const value = normalizedPath(relativePath);
662
+ return roots.some((root) => value === root || value.startsWith(`${root}/`));
663
+ }
664
+ function fileInRoots(active, roots, filename) {
665
+ for (const root of roots) {
666
+ const file = fileByRelative(active, path.posix.join(root, filename).replaceAll('\\', '/'));
667
+ if (file !== undefined)
668
+ return file;
669
+ }
670
+ return undefined;
671
+ }
672
+ function mapFile(active, filename, mapRoots) {
673
+ return fileInRoots(active, mapRoots, filename);
674
+ }
675
+ function sourceIdentity(file) {
676
+ return `${file.rootKind}:${file.loadOrder}`;
677
+ }
678
+ /**
679
+ * Resolve every definition database selected by a scanned root's own
680
+ * default.map. A root without a selector inherits the active selector name,
681
+ * matching the way partial dependency/mod roots supplement an active map.
682
+ */
683
+ function definitionFilesAcrossRoots(files, mapRoots, activeDefinitionsName) {
684
+ const groups = new Map();
685
+ for (const file of files) {
686
+ const key = sourceIdentity(file);
687
+ const group = groups.get(key) ?? [];
688
+ group.push(file);
689
+ groups.set(key, group);
690
+ }
691
+ const selected = new Map();
692
+ for (const group of groups.values()) {
693
+ const byPath = new Map(group.map((file) => [normalizedPath(file.relativePath), file]));
694
+ for (const root of mapRoots) {
695
+ const defaultMap = byPath.get(normalizedPath(path.posix.join(root, 'default.map')));
696
+ const definitionsName = defaultMapSelectorValue(defaultMap, 'definitions', activeDefinitionsName);
697
+ const definition = byPath.get(normalizedPath(path.posix.join(root, definitionsName).replaceAll('\\', '/')));
698
+ if (definition !== undefined)
699
+ selected.set(definition.displayPath, definition);
700
+ }
701
+ }
702
+ return [...selected.values()].sort((left, right) => left.loadOrder - right.loadOrder || compareCodeUnits(left.displayPath, right.displayPath));
703
+ }
704
+ function addNeighbor(adjacency, left, right) {
705
+ if (left < 0 || right < 0 || left === right)
706
+ return;
707
+ const leftSet = adjacency.get(left) ?? new Set();
708
+ const rightSet = adjacency.get(right) ?? new Set();
709
+ leftSet.add(right);
710
+ rightSet.add(left);
711
+ adjacency.set(left, leftSet);
712
+ adjacency.set(right, rightSet);
713
+ }
714
+ export function buildProvinceRaster(bitmap, definitionsByColor, definitionsById) {
715
+ assertRenderDimensions(bitmap.width, bitmap.height, 'map province raster', {
716
+ maximumPixels: MAP_PROVINCE_ENGINE_MAX_PIXELS,
717
+ });
718
+ const provinceIds = new Int32Array(bitmap.width * bitmap.height);
719
+ provinceIds.fill(-1);
720
+ const accumulators = new Map();
721
+ const unknown = new Map();
722
+ const unknownColorBits = new Uint8Array(1 << 21);
723
+ let unknownColorCount = 0;
724
+ for (let y = 0; y < bitmap.height; y += 1) {
725
+ for (let x = 0; x < bitmap.width; x += 1) {
726
+ const color = bitmap.rgbAt(x, y);
727
+ const definition = definitionsByColor.get(rgbKey(color));
728
+ if (definition === undefined) {
729
+ const key = rgbKey(color);
730
+ const value = (color.r << 16) | (color.g << 8) | color.b;
731
+ const byteIndex = value >>> 3;
732
+ const bit = 1 << (value & 7);
733
+ if ((unknownColorBits[byteIndex] & bit) === 0) {
734
+ unknownColorBits[byteIndex] = unknownColorBits[byteIndex] | bit;
735
+ unknownColorCount += 1;
736
+ }
737
+ const record = unknown.get(key);
738
+ if (record === undefined && unknown.size < 256)
739
+ unknown.set(key, { color, count: 1, firstX: x, firstY: y });
740
+ else if (record !== undefined)
741
+ record.count += 1;
742
+ continue;
743
+ }
744
+ const offset = y * bitmap.width + x;
745
+ provinceIds[offset] = definition.id;
746
+ const accumulator = accumulators.get(definition.id) ?? {
747
+ count: 0,
748
+ minX: x,
749
+ minY: y,
750
+ maxX: x,
751
+ maxY: y,
752
+ sumX: 0,
753
+ sumY: 0,
754
+ };
755
+ accumulator.count += 1;
756
+ accumulator.minX = Math.min(accumulator.minX, x);
757
+ accumulator.minY = Math.min(accumulator.minY, y);
758
+ accumulator.maxX = Math.max(accumulator.maxX, x);
759
+ accumulator.maxY = Math.max(accumulator.maxY, y);
760
+ accumulator.sumX += x;
761
+ accumulator.sumY += y;
762
+ accumulators.set(definition.id, accumulator);
763
+ }
764
+ }
765
+ const adjacency = new Map();
766
+ for (let y = 0; y < bitmap.height; y += 1) {
767
+ for (let x = 0; x < bitmap.width; x += 1) {
768
+ const current = provinceIds[y * bitmap.width + x] ?? -1;
769
+ const rightX = x === bitmap.width - 1 ? 0 : x + 1;
770
+ addNeighbor(adjacency, current, provinceIds[y * bitmap.width + rightX] ?? -1);
771
+ if (y + 1 < bitmap.height)
772
+ addNeighbor(adjacency, current, provinceIds[(y + 1) * bitmap.width + x] ?? -1);
773
+ }
774
+ }
775
+ const geometry = new Map();
776
+ for (const [id, value] of accumulators) {
777
+ geometry.set(id, {
778
+ id,
779
+ pixelCount: value.count,
780
+ minX: value.minX,
781
+ minY: value.minY,
782
+ maxX: value.maxX,
783
+ maxY: value.maxY,
784
+ centerX: value.sumX / value.count,
785
+ centerY: value.sumY / value.count,
786
+ });
787
+ }
788
+ const coastalProvinceIds = new Set();
789
+ for (const [id, neighbors] of adjacency) {
790
+ const definition = definitionsById.get(id);
791
+ if (definition === undefined)
792
+ continue;
793
+ if ([...neighbors].some((neighbor) => {
794
+ const other = definitionsById.get(neighbor);
795
+ return ((definition.type === 'land' && other?.type === 'sea') ||
796
+ (definition.type === 'sea' && other?.type === 'land'));
797
+ })) {
798
+ coastalProvinceIds.add(id);
799
+ }
800
+ }
801
+ return {
802
+ width: bitmap.width,
803
+ height: bitmap.height,
804
+ provinceIds,
805
+ adjacency,
806
+ geometry,
807
+ unknownColors: [...unknown.values()].sort((left, right) => compareCodeUnits(rgbKey(left.color), rgbKey(right.color))),
808
+ unknownColorCount,
809
+ coastalProvinceIds,
810
+ };
811
+ }
812
+ export class MapWorkspaceIndex {
813
+ /** Every scanned root file, including entries shadowed by a higher-load-order root. */
814
+ sourceFiles;
815
+ sourceRoots;
816
+ /** Shared cross-domain symbol/reference authority for these exact source bytes. */
817
+ sharedIndex;
818
+ activeFiles;
819
+ diagnostics = [];
820
+ definitions;
821
+ definitionsAcrossRoots;
822
+ definitionsById = new Map();
823
+ definitionsByColor = new Map();
824
+ duplicateDefinitionIds = new Map();
825
+ duplicateColors = new Map();
826
+ states;
827
+ statesAcrossRoots;
828
+ statesById = new Map();
829
+ regions;
830
+ regionsById = new Map();
831
+ statesByProvince = new Map();
832
+ regionsByProvince = new Map();
833
+ ownersByState = new Map();
834
+ controllersByState = new Map();
835
+ capitalsByState = new Map();
836
+ coresByState = new Map();
837
+ claimsByState = new Map();
838
+ victoryPointsByProvince = new Map();
839
+ provinceBuildingsByProvince = new Map();
840
+ adjacencies;
841
+ supplyNodes;
842
+ railways;
843
+ buildingPositions;
844
+ unitPositions;
845
+ weatherPositions;
846
+ entityLocators;
847
+ ports = [];
848
+ coastalProvinceIds;
849
+ localisationKeys = new Set();
850
+ localisationEntries = [];
851
+ localisationByKey = new Map();
852
+ provinceBitmapFile;
853
+ provinceBitmap;
854
+ raster;
855
+ defaultMapFile;
856
+ definitionFile;
857
+ adjacencyFile;
858
+ supplyNodeFile;
859
+ railwayFile;
860
+ constructor(files, sourceRoots = defaultMapIndexSourceRoots, sharedIndex = SymbolIndex.build(files)) {
861
+ this.sourceFiles = [...files];
862
+ this.sharedIndex = sharedIndex;
863
+ this.sourceRoots = {
864
+ map: sourceRoots.map.map(normalizeConfiguredRoot),
865
+ states: sourceRoots.states.map(normalizeConfiguredRoot),
866
+ localisation: sourceRoots.localisation.map(normalizeConfiguredRoot),
867
+ };
868
+ this.activeFiles = selectActiveFiles(files);
869
+ const modelBudget = new MapModelBudget();
870
+ modelBudget.assertScriptFiles(this.sourceFiles.filter((file) => inConfiguredRoot(file.relativePath, this.sourceRoots.states) ||
871
+ this.sourceRoots.map.some((root) => normalizedPath(file.relativePath).startsWith(`${root}/strategicregions/`)) ||
872
+ normalizedPath(file.relativePath).endsWith('.asset')).length);
873
+ this.defaultMapFile = fileInRoots(this.activeFiles, this.sourceRoots.map, 'default.map');
874
+ const definitionsName = defaultMapSelectorValue(this.defaultMapFile, 'definitions', 'definition.csv');
875
+ const provincesName = defaultMapSelectorValue(this.defaultMapFile, 'provinces', 'provinces.bmp');
876
+ this.definitionFile = mapFile(this.activeFiles, definitionsName, this.sourceRoots.map);
877
+ this.provinceBitmapFile = mapFile(this.activeFiles, provincesName, this.sourceRoots.map);
878
+ const definitionFiles = definitionFilesAcrossRoots(this.sourceFiles, this.sourceRoots.map, definitionsName);
879
+ const parsedDefinitions = new Map();
880
+ const definitionsFor = (file) => {
881
+ const cached = parsedDefinitions.get(file.displayPath);
882
+ if (cached !== undefined)
883
+ return cached;
884
+ const parsed = parseDefinitions(file, file.displayPath === this.definitionFile?.displayPath ? this.diagnostics : []);
885
+ modelBudget.addRecords(parsed.length);
886
+ parsedDefinitions.set(file.displayPath, parsed);
887
+ return parsed;
888
+ };
889
+ this.definitionsAcrossRoots = definitionFiles.flatMap(definitionsFor);
890
+ this.definitions = this.definitionFile === undefined ? [] : definitionsFor(this.definitionFile);
891
+ for (const definition of this.definitions) {
892
+ const byId = this.duplicateDefinitionIds.get(definition.id) ?? [];
893
+ byId.push(definition);
894
+ this.duplicateDefinitionIds.set(definition.id, byId);
895
+ const key = rgbKey(definition.color);
896
+ const byColor = this.duplicateColors.get(key) ?? [];
897
+ byColor.push(definition);
898
+ this.duplicateColors.set(key, byColor);
899
+ if (!this.definitionsById.has(definition.id))
900
+ this.definitionsById.set(definition.id, definition);
901
+ if (!this.definitionsByColor.has(key))
902
+ this.definitionsByColor.set(key, definition);
903
+ }
904
+ if (this.provinceBitmapFile !== undefined) {
905
+ try {
906
+ this.provinceBitmap = BmpImage.decode(this.provinceBitmapFile.bytes);
907
+ }
908
+ catch (error) {
909
+ addMapDiagnostic(this.diagnostics, {
910
+ code: error instanceof Error && 'code' in error ? String(error.code) : 'MAP_BMP_INVALID',
911
+ severity: 'error',
912
+ category: 'map',
913
+ message: error instanceof Error ? error.message : String(error),
914
+ });
915
+ }
916
+ }
917
+ if (this.provinceBitmap !== undefined) {
918
+ this.raster = buildProvinceRaster(this.provinceBitmap, this.definitionsByColor, this.definitionsById);
919
+ }
920
+ const stateFiles = this.activeFiles.all.filter((file) => inConfiguredRoot(file.relativePath, this.sourceRoots.states));
921
+ const activeStatePaths = new Set(stateFiles.map(({ displayPath }) => displayPath));
922
+ const parsedStates = new Map();
923
+ const stateFor = (file) => {
924
+ const cached = parsedStates.get(file.displayPath);
925
+ if (cached !== undefined)
926
+ return cached ?? undefined;
927
+ const state = parseState(file, activeStatePaths.has(file.displayPath) ? this.diagnostics : []);
928
+ parsedStates.set(file.displayPath, state ?? null);
929
+ if (state !== undefined) {
930
+ modelBudget.addDocument(state.document);
931
+ modelBudget.addRecords(1);
932
+ modelBudget.addMembershipEdges(state.provinces.length +
933
+ state.victoryPoints.length +
934
+ state.provinceBuildings.size +
935
+ state.cores.length +
936
+ state.claims.length);
937
+ }
938
+ return state;
939
+ };
940
+ this.statesAcrossRoots = this.sourceFiles
941
+ .filter((file) => inConfiguredRoot(file.relativePath, this.sourceRoots.states))
942
+ .flatMap((file) => {
943
+ const state = stateFor(file);
944
+ return state === undefined ? [] : [state];
945
+ });
946
+ this.states = stateFiles.flatMap((file) => {
947
+ const state = stateFor(file);
948
+ return state === undefined ? [] : [state];
949
+ });
950
+ for (const state of this.states) {
951
+ if (!this.statesById.has(state.id))
952
+ this.statesById.set(state.id, state);
953
+ if (state.owner !== undefined)
954
+ this.ownersByState.set(state.id, state.owner);
955
+ if (state.controller !== undefined)
956
+ this.controllersByState.set(state.id, state.controller);
957
+ if (state.capital !== undefined)
958
+ this.capitalsByState.set(state.id, state.capital);
959
+ this.coresByState.set(state.id, state.cores);
960
+ this.claimsByState.set(state.id, state.claims);
961
+ for (const provinceId of state.provinces) {
962
+ const memberships = this.statesByProvince.get(provinceId) ?? [];
963
+ memberships.push(state);
964
+ this.statesByProvince.set(provinceId, memberships);
965
+ }
966
+ for (const record of state.victoryPoints) {
967
+ const points = this.victoryPointsByProvince.get(record.provinceId) ?? [];
968
+ points.push({
969
+ stateId: state.id,
970
+ provinceId: record.provinceId,
971
+ value: record.value,
972
+ record,
973
+ });
974
+ this.victoryPointsByProvince.set(record.provinceId, points);
975
+ }
976
+ for (const [provinceId, buildings] of state.provinceBuildings) {
977
+ const records = this.provinceBuildingsByProvince.get(provinceId) ?? [];
978
+ records.push({ stateId: state.id, provinceId, buildings });
979
+ this.provinceBuildingsByProvince.set(provinceId, records);
980
+ }
981
+ }
982
+ const regionFiles = this.activeFiles.all.filter((file) => this.sourceRoots.map.some((root) => normalizedPath(file.relativePath).startsWith(`${root}/strategicregions/`)));
983
+ this.regions = regionFiles.flatMap((file) => {
984
+ const region = parseStrategicRegion(file, this.diagnostics);
985
+ if (region !== undefined) {
986
+ modelBudget.addDocument(region.document);
987
+ modelBudget.addRecords(1);
988
+ modelBudget.addMembershipEdges(region.provinces.length);
989
+ }
990
+ return region === undefined ? [] : [region];
991
+ });
992
+ for (const region of this.regions) {
993
+ if (!this.regionsById.has(region.id))
994
+ this.regionsById.set(region.id, region);
995
+ for (const provinceId of region.provinces) {
996
+ const memberships = this.regionsByProvince.get(provinceId) ?? [];
997
+ memberships.push(region);
998
+ this.regionsByProvince.set(provinceId, memberships);
999
+ }
1000
+ }
1001
+ this.adjacencyFile = mapFile(this.activeFiles, defaultMapSelectorValue(this.defaultMapFile, 'adjacencies', 'adjacencies.csv'), this.sourceRoots.map);
1002
+ this.adjacencies =
1003
+ this.adjacencyFile === undefined
1004
+ ? []
1005
+ : parseAdjacencies(this.adjacencyFile, this.diagnostics);
1006
+ modelBudget.addRecords(this.adjacencies.length);
1007
+ this.supplyNodeFile = mapFile(this.activeFiles, defaultMapSelectorValue(this.defaultMapFile, 'supply_nodes', 'supply_nodes.txt'), this.sourceRoots.map);
1008
+ this.supplyNodes =
1009
+ this.supplyNodeFile === undefined
1010
+ ? []
1011
+ : parseSupplyNodes(this.supplyNodeFile, this.diagnostics);
1012
+ modelBudget.addRecords(this.supplyNodes.length);
1013
+ modelBudget.addMembershipEdges(this.supplyNodes.length);
1014
+ this.railwayFile = mapFile(this.activeFiles, defaultMapSelectorValue(this.defaultMapFile, 'railways', 'railways.txt'), this.sourceRoots.map);
1015
+ this.railways =
1016
+ this.railwayFile === undefined ? [] : parseRailways(this.railwayFile, this.diagnostics);
1017
+ modelBudget.addRecords(this.railways.length);
1018
+ modelBudget.addMembershipEdges(this.railways.reduce((total, railway) => total + railway.provinces.length, 0));
1019
+ const buildingsFile = mapFile(this.activeFiles, 'buildings.txt', this.sourceRoots.map);
1020
+ this.buildingPositions =
1021
+ buildingsFile === undefined ? [] : parseBuildingPositions(buildingsFile, this.diagnostics);
1022
+ modelBudget.addRecords(this.buildingPositions.length);
1023
+ const unitstacksFile = mapFile(this.activeFiles, 'unitstacks.txt', this.sourceRoots.map);
1024
+ const positionsFile = mapFile(this.activeFiles, defaultMapSelectorValue(this.defaultMapFile, 'positions', 'positions.txt'), this.sourceRoots.map);
1025
+ this.unitPositions = [unitstacksFile, positionsFile]
1026
+ .filter((file) => file !== undefined && file.size > 0)
1027
+ .flatMap((file) => parseUnitPositions(file, this.diagnostics));
1028
+ modelBudget.addRecords(this.unitPositions.length);
1029
+ const weatherFile = mapFile(this.activeFiles, 'weatherpositions.txt', this.sourceRoots.map);
1030
+ this.weatherPositions =
1031
+ weatherFile === undefined ? [] : parseWeatherPositions(weatherFile, this.diagnostics);
1032
+ modelBudget.addRecords(this.weatherPositions.length);
1033
+ this.entityLocators = this.activeFiles.all
1034
+ .filter((file) => normalizedPath(file.relativePath).endsWith('.asset'))
1035
+ .flatMap((file) => {
1036
+ const locators = parseEntityLocators(file, this.diagnostics);
1037
+ if (locators[0] !== undefined)
1038
+ modelBudget.addDocument(locators[0].document);
1039
+ modelBudget.addRecords(locators.length);
1040
+ return locators;
1041
+ });
1042
+ for (const file of this.activeFiles.all.filter((entry) => inConfiguredRoot(entry.relativePath, this.sourceRoots.localisation) &&
1043
+ normalizedPath(entry.relativePath).endsWith('.yml'))) {
1044
+ const document = parseLocalisation(file.bytes, file.displayPath);
1045
+ addMapDiagnostics(this.diagnostics, document.diagnostics);
1046
+ modelBudget.addRecords(document.entries.length);
1047
+ for (const entry of document.entries) {
1048
+ this.localisationKeys.add(`${entry.language}:${entry.key}`);
1049
+ const indexed = { file, document, entry };
1050
+ this.localisationEntries.push(indexed);
1051
+ const key = `${entry.language}:${entry.key}`;
1052
+ const values = this.localisationByKey.get(key) ?? [];
1053
+ values.push(indexed);
1054
+ this.localisationByKey.set(key, values);
1055
+ }
1056
+ }
1057
+ this.coastalProvinceIds = this.raster?.coastalProvinceIds ?? new Set();
1058
+ const portPositionsByStateProvince = new Map();
1059
+ for (const position of this.buildingPositions) {
1060
+ if (position.building !== 'naval_base_spawn' && position.building !== 'floating_harbor') {
1061
+ continue;
1062
+ }
1063
+ const provinceId = this.provinceAtMapCoordinate(position.x, position.z);
1064
+ if (provinceId === undefined)
1065
+ continue;
1066
+ const key = `${position.stateId}:${provinceId}`;
1067
+ const positions = portPositionsByStateProvince.get(key) ?? [];
1068
+ positions.push(position);
1069
+ portPositionsByStateProvince.set(key, positions);
1070
+ }
1071
+ for (const [provinceId, records] of this.provinceBuildingsByProvince) {
1072
+ const level = records.reduce((total, { buildings }) => total + (buildings.get('naval_base') ?? 0), 0);
1073
+ if (level <= 0)
1074
+ continue;
1075
+ const firstRecord = records[0];
1076
+ if (firstRecord === undefined)
1077
+ continue;
1078
+ const stateId = firstRecord.stateId;
1079
+ const positions = portPositionsByStateProvince.get(`${stateId}:${provinceId}`) ?? [];
1080
+ this.ports.push({
1081
+ stateId,
1082
+ provinceId,
1083
+ level,
1084
+ coastal: this.coastalProvinceIds.has(provinceId),
1085
+ positions,
1086
+ adjacentSeaProvinceIds: uniqueNumbers(positions.map(({ adjacentSeaProvince }) => adjacentSeaProvince)),
1087
+ });
1088
+ }
1089
+ }
1090
+ static build(files, sourceRoots = defaultMapIndexSourceRoots, sharedIndex = SymbolIndex.build(files)) {
1091
+ return new MapWorkspaceIndex(files, sourceRoots, sharedIndex);
1092
+ }
1093
+ provinceAtMapCoordinate(x, z) {
1094
+ if (this.raster === undefined)
1095
+ return undefined;
1096
+ const pixelX = Math.floor(x);
1097
+ const pixelY = this.raster.height - 1 - Math.floor(z);
1098
+ if (pixelX < 0 || pixelX >= this.raster.width || pixelY < 0 || pixelY >= this.raster.height) {
1099
+ return undefined;
1100
+ }
1101
+ const id = this.raster.provinceIds[pixelY * this.raster.width + pixelX] ?? -1;
1102
+ return id < 0 ? undefined : id;
1103
+ }
1104
+ stateForProvince(provinceId) {
1105
+ return this.statesByProvince.get(provinceId) ?? [];
1106
+ }
1107
+ regionForProvince(provinceId) {
1108
+ return this.regionsByProvince.get(provinceId) ?? [];
1109
+ }
1110
+ }
1111
+ function uniqueNumbers(values) {
1112
+ return [...new Set(values)].sort((left, right) => left - right);
1113
+ }
1114
+ //# sourceMappingURL=model.js.map