modwright 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/LICENSE +35 -0
  2. package/README.md +212 -0
  3. package/assets/claude/agents/mw-explore.md +46 -0
  4. package/assets/claude/agents/mw-fixture.md +33 -0
  5. package/assets/claude/agents/mw-rule-author.md +51 -0
  6. package/assets/claude/agents/mw-scaffold-author.md +48 -0
  7. package/assets/claude/skills/mw-author.md +59 -0
  8. package/assets/claude/skills/mw-new-item.md +51 -0
  9. package/assets/claude/skills/mw-new-spell.md +50 -0
  10. package/assets/claude/skills/mw-scaffold.md +59 -0
  11. package/assets/claude/skills/mw-ship.md +57 -0
  12. package/assets/claude/skills/mw-validate.md +51 -0
  13. package/assets/claude/skills/mw-verify.md +59 -0
  14. package/assets/nivalisnights/extract_resources.py +177 -0
  15. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Config.json +5 -0
  16. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapClient.lua +55 -0
  17. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapServer.lua +81 -0
  18. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Log.lua +96 -0
  19. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Probes.lua +1038 -0
  20. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/ProbesClient.lua +74 -0
  21. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Protocol.lua +985 -0
  22. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Watch.lua +175 -0
  23. package/bridges/bg3-se/Mods/ModWrightBridge/meta.lsx +45 -0
  24. package/bridges/bg3-se/README.md +99 -0
  25. package/bridges/bg3-se/bridge.json +68 -0
  26. package/bridges/cp2077-cet/ModWrightBridge/init.lua +375 -0
  27. package/bridges/cp2077-cet/ModWrightBridge/probes.lua +1104 -0
  28. package/bridges/cp2077-cet/ModWrightBridge/protocol.lua +1306 -0
  29. package/bridges/cp2077-cet/README.md +165 -0
  30. package/bridges/cp2077-cet/bridge.json +53 -0
  31. package/dist/core/bridge/arm.js +175 -0
  32. package/dist/core/bridge/cet-console.js +26 -0
  33. package/dist/core/bridge/cet-log.js +362 -0
  34. package/dist/core/bridge/index.js +11 -0
  35. package/dist/core/bridge/locate.js +35 -0
  36. package/dist/core/bridge/paths.js +34 -0
  37. package/dist/core/bridge/pending.js +89 -0
  38. package/dist/core/bridge/poll.js +155 -0
  39. package/dist/core/bridge/stage.js +100 -0
  40. package/dist/core/bridge/status.js +97 -0
  41. package/dist/core/bridge/types.js +145 -0
  42. package/dist/core/bridge/validate.js +107 -0
  43. package/dist/core/build/index.js +6 -0
  44. package/dist/core/build/manifest.js +47 -0
  45. package/dist/core/build/paths.js +32 -0
  46. package/dist/core/build/run.js +342 -0
  47. package/dist/core/build/stage.js +265 -0
  48. package/dist/core/build/steps/bg3.js +129 -0
  49. package/dist/core/build/steps/core.js +195 -0
  50. package/dist/core/build/steps/cyberpunk.js +95 -0
  51. package/dist/core/build/steps/listing.js +35 -0
  52. package/dist/core/build/types.js +13 -0
  53. package/dist/core/build/zip.js +148 -0
  54. package/dist/core/compat/check.js +113 -0
  55. package/dist/core/compat/pe.js +220 -0
  56. package/dist/core/compat/types.js +1 -0
  57. package/dist/core/compat/version.js +70 -0
  58. package/dist/core/deploy/guards.js +292 -0
  59. package/dist/core/deploy/index.js +5 -0
  60. package/dist/core/deploy/plan.js +696 -0
  61. package/dist/core/deploy/reload-apply.js +361 -0
  62. package/dist/core/deploy/reload.js +358 -0
  63. package/dist/core/deploy/sources.js +169 -0
  64. package/dist/core/deploy/types.js +1 -0
  65. package/dist/core/epic.js +54 -0
  66. package/dist/core/fsutil.js +191 -0
  67. package/dist/core/home.js +70 -0
  68. package/dist/core/knowledge/facts.js +229 -0
  69. package/dist/core/knowledge/index.js +4 -0
  70. package/dist/core/knowledge/search.js +112 -0
  71. package/dist/core/knowledge/store.js +123 -0
  72. package/dist/core/knowledge/types.js +1 -0
  73. package/dist/core/ledger/check.js +42 -0
  74. package/dist/core/ledger/hooks.js +80 -0
  75. package/dist/core/ledger/index.js +7 -0
  76. package/dist/core/ledger/query.js +17 -0
  77. package/dist/core/ledger/record.js +84 -0
  78. package/dist/core/ledger/status.js +53 -0
  79. package/dist/core/ledger/store.js +98 -0
  80. package/dist/core/ledger/types.js +108 -0
  81. package/dist/core/logs/index.js +4 -0
  82. package/dist/core/logs/registry.js +50 -0
  83. package/dist/core/logs/scan.js +195 -0
  84. package/dist/core/logs/triage.js +160 -0
  85. package/dist/core/logs/types.js +1 -0
  86. package/dist/core/lsx.js +10 -0
  87. package/dist/core/lz4.js +66 -0
  88. package/dist/core/mods.js +229 -0
  89. package/dist/core/process.js +49 -0
  90. package/dist/core/project/build-steps.js +83 -0
  91. package/dist/core/project/describe.js +74 -0
  92. package/dist/core/project/index.js +5 -0
  93. package/dist/core/project/load.js +146 -0
  94. package/dist/core/project/schema.js +264 -0
  95. package/dist/core/project/types.js +3 -0
  96. package/dist/core/prompts.js +72 -0
  97. package/dist/core/registry.js +35 -0
  98. package/dist/core/safety/backup.js +206 -0
  99. package/dist/core/safety/execute.js +188 -0
  100. package/dist/core/safety/index.js +5 -0
  101. package/dist/core/safety/plan.js +122 -0
  102. package/dist/core/safety/restore.js +172 -0
  103. package/dist/core/safety/types.js +1 -0
  104. package/dist/core/scaffold/bootstrap.js +7 -0
  105. package/dist/core/scaffold/catalog.js +28 -0
  106. package/dist/core/scaffold/claude-assets.js +271 -0
  107. package/dist/core/scaffold/collisions.js +64 -0
  108. package/dist/core/scaffold/emit.js +356 -0
  109. package/dist/core/scaffold/engine.js +680 -0
  110. package/dist/core/scaffold/ids.js +78 -0
  111. package/dist/core/scaffold/index.js +10 -0
  112. package/dist/core/scaffold/jsonpath.js +121 -0
  113. package/dist/core/scaffold/load.js +81 -0
  114. package/dist/core/scaffold/render.js +85 -0
  115. package/dist/core/scaffold/sequence.js +396 -0
  116. package/dist/core/scaffold/types.js +309 -0
  117. package/dist/core/steam.js +63 -0
  118. package/dist/core/surfaceutil.js +36 -0
  119. package/dist/core/testplan/check.js +67 -0
  120. package/dist/core/testplan/index.js +5 -0
  121. package/dist/core/testplan/load.js +100 -0
  122. package/dist/core/testplan/registry.js +317 -0
  123. package/dist/core/testplan/run.js +389 -0
  124. package/dist/core/testplan/types.js +82 -0
  125. package/dist/core/text/converters/bg3.js +50 -0
  126. package/dist/core/text/converters/cyberpunk.js +36 -0
  127. package/dist/core/text/converters/index.js +261 -0
  128. package/dist/core/text/diff/cr2w.js +180 -0
  129. package/dist/core/text/diff/index.js +16 -0
  130. package/dist/core/text/diff/loca.js +43 -0
  131. package/dist/core/text/diff/lsx.js +126 -0
  132. package/dist/core/text/handles.js +86 -0
  133. package/dist/core/text/index.js +6 -0
  134. package/dist/core/text/json.js +46 -0
  135. package/dist/core/text/templates/cache.js +71 -0
  136. package/dist/core/text/templates/index.js +3 -0
  137. package/dist/core/text/templates/library.js +245 -0
  138. package/dist/core/text/templates/types.js +51 -0
  139. package/dist/core/text/toolchain.js +16 -0
  140. package/dist/core/text/types.js +1 -0
  141. package/dist/core/text/validate.js +149 -0
  142. package/dist/core/text/xml.js +58 -0
  143. package/dist/core/toolchain/datafetch.js +151 -0
  144. package/dist/core/toolchain/env.js +63 -0
  145. package/dist/core/toolchain/features.js +170 -0
  146. package/dist/core/toolchain/index.js +8 -0
  147. package/dist/core/toolchain/install.js +191 -0
  148. package/dist/core/toolchain/locate.js +275 -0
  149. package/dist/core/toolchain/remember.js +84 -0
  150. package/dist/core/toolchain/run.js +318 -0
  151. package/dist/core/toolchain/specs.js +351 -0
  152. package/dist/core/toolchain/types.js +1 -0
  153. package/dist/core/types.js +1 -0
  154. package/dist/core/userconfig.js +66 -0
  155. package/dist/core/validate/context.js +139 -0
  156. package/dist/core/validate/index.js +5 -0
  157. package/dist/core/validate/registry.js +58 -0
  158. package/dist/core/validate/run.js +131 -0
  159. package/dist/core/validate/suppressions.js +91 -0
  160. package/dist/core/validate/types.js +2 -0
  161. package/dist/core/yamledit.js +51 -0
  162. package/dist/index.js +389 -0
  163. package/dist/server.js +1914 -0
  164. package/dist/surfaces/baldursgate3/compat.js +164 -0
  165. package/dist/surfaces/baldursgate3/identity.js +110 -0
  166. package/dist/surfaces/baldursgate3/index/build.js +331 -0
  167. package/dist/surfaces/baldursgate3/index/index.js +17 -0
  168. package/dist/surfaces/baldursgate3/index/info.js +40 -0
  169. package/dist/surfaces/baldursgate3/index/parsers/loca.js +41 -0
  170. package/dist/surfaces/baldursgate3/index/parsers/lsx.js +137 -0
  171. package/dist/surfaces/baldursgate3/index/parsers/stats.js +45 -0
  172. package/dist/surfaces/baldursgate3/index/parsers/treasuretable.js +57 -0
  173. package/dist/surfaces/baldursgate3/index/parsers/xmlutil.js +142 -0
  174. package/dist/surfaces/baldursgate3/index/queries.js +327 -0
  175. package/dist/surfaces/baldursgate3/index/schema.js +62 -0
  176. package/dist/surfaces/baldursgate3/index.js +3 -0
  177. package/dist/surfaces/baldursgate3/logs.js +278 -0
  178. package/dist/surfaces/baldursgate3/modsettings.js +115 -0
  179. package/dist/surfaces/baldursgate3/pak.js +153 -0
  180. package/dist/surfaces/baldursgate3/settings.js +49 -0
  181. package/dist/surfaces/baldursgate3/surface.js +232 -0
  182. package/dist/surfaces/baldursgate3/validators/bridge.js +7 -0
  183. package/dist/surfaces/baldursgate3/validators/files.js +476 -0
  184. package/dist/surfaces/baldursgate3/validators/items.js +1001 -0
  185. package/dist/surfaces/baldursgate3/validators/progression.js +734 -0
  186. package/dist/surfaces/baldursgate3/validators/stats.js +1076 -0
  187. package/dist/surfaces/baldursgate3/validators/story.js +790 -0
  188. package/dist/surfaces/baldursgate3/validators/templates.js +7 -0
  189. package/dist/surfaces/cyberpunk2077/compat.js +223 -0
  190. package/dist/surfaces/cyberpunk2077/index/build.js +231 -0
  191. package/dist/surfaces/cyberpunk2077/index/index.js +17 -0
  192. package/dist/surfaces/cyberpunk2077/index/info.js +51 -0
  193. package/dist/surfaces/cyberpunk2077/index/model.js +52 -0
  194. package/dist/surfaces/cyberpunk2077/index/parsers/tweak.js +483 -0
  195. package/dist/surfaces/cyberpunk2077/index/parsers/tweakxl-yaml.js +183 -0
  196. package/dist/surfaces/cyberpunk2077/index/queries.js +504 -0
  197. package/dist/surfaces/cyberpunk2077/index/resource.js +135 -0
  198. package/dist/surfaces/cyberpunk2077/index/schema.js +90 -0
  199. package/dist/surfaces/cyberpunk2077/index.js +3 -0
  200. package/dist/surfaces/cyberpunk2077/logs.js +742 -0
  201. package/dist/surfaces/cyberpunk2077/paths.js +12 -0
  202. package/dist/surfaces/cyberpunk2077/surface.js +218 -0
  203. package/dist/surfaces/cyberpunk2077/validators/bridge.js +7 -0
  204. package/dist/surfaces/cyberpunk2077/validators/cr2w.js +349 -0
  205. package/dist/surfaces/cyberpunk2077/validators/garments.js +1181 -0
  206. package/dist/surfaces/cyberpunk2077/validators/mesh.js +338 -0
  207. package/dist/surfaces/cyberpunk2077/validators/modsettings.js +120 -0
  208. package/dist/surfaces/cyberpunk2077/validators/packaging.js +463 -0
  209. package/dist/surfaces/cyberpunk2077/validators/red4ext.js +318 -0
  210. package/dist/surfaces/cyberpunk2077/validators/redscript.js +193 -0
  211. package/dist/surfaces/cyberpunk2077/validators/templates.js +7 -0
  212. package/dist/surfaces/cyberpunk2077/validators/tweaks.js +768 -0
  213. package/dist/surfaces/cyberpunk2077/validators/vehicles.js +531 -0
  214. package/dist/surfaces/cyberpunk2077/validators/xl.js +308 -0
  215. package/dist/surfaces/eldenring/binders.js +111 -0
  216. package/dist/surfaces/eldenring/compat.js +166 -0
  217. package/dist/surfaces/eldenring/dcx.js +49 -0
  218. package/dist/surfaces/eldenring/index.js +13 -0
  219. package/dist/surfaces/eldenring/loaders.js +132 -0
  220. package/dist/surfaces/eldenring/logs.js +67 -0
  221. package/dist/surfaces/eldenring/paramdef.js +256 -0
  222. package/dist/surfaces/eldenring/params.js +129 -0
  223. package/dist/surfaces/eldenring/surface.js +121 -0
  224. package/dist/surfaces/eldenring/tools.js +52 -0
  225. package/dist/surfaces/eldenring/validators/binders.js +193 -0
  226. package/dist/surfaces/eldenring/validators/packages.js +159 -0
  227. package/dist/surfaces/eldenring/validators/params.js +334 -0
  228. package/dist/surfaces/eldenring/validators/profiles.js +287 -0
  229. package/dist/surfaces/index.js +34 -0
  230. package/dist/surfaces/nivalisnights/compat.js +229 -0
  231. package/dist/surfaces/nivalisnights/index/build.js +310 -0
  232. package/dist/surfaces/nivalisnights/index/index.js +5 -0
  233. package/dist/surfaces/nivalisnights/index/queries.js +231 -0
  234. package/dist/surfaces/nivalisnights/index.js +4 -0
  235. package/dist/surfaces/nivalisnights/logs.js +473 -0
  236. package/dist/surfaces/nivalisnights/surface.js +195 -0
  237. package/dist/surfaces/skyrimse/archives.js +229 -0
  238. package/dist/surfaces/skyrimse/compat.js +163 -0
  239. package/dist/surfaces/skyrimse/index.js +12 -0
  240. package/dist/surfaces/skyrimse/loadorder.js +174 -0
  241. package/dist/surfaces/skyrimse/logs.js +241 -0
  242. package/dist/surfaces/skyrimse/plugins.js +149 -0
  243. package/dist/surfaces/skyrimse/records.js +94 -0
  244. package/dist/surfaces/skyrimse/surface.js +240 -0
  245. package/dist/surfaces/skyrimse/validators/archive-records.js +165 -0
  246. package/dist/surfaces/skyrimse/validators/archives.js +110 -0
  247. package/dist/surfaces/skyrimse/validators/plugins.js +374 -0
  248. package/dist/surfaces/skyrimse/validators/records.js +117 -0
  249. package/dist/surfaces/stardewvalley/compat.js +190 -0
  250. package/dist/surfaces/stardewvalley/config.js +42 -0
  251. package/dist/surfaces/stardewvalley/contentpatcher.js +203 -0
  252. package/dist/surfaces/stardewvalley/index/index.js +229 -0
  253. package/dist/surfaces/stardewvalley/index/wiki.js +190 -0
  254. package/dist/surfaces/stardewvalley/index.js +12 -0
  255. package/dist/surfaces/stardewvalley/logs.js +307 -0
  256. package/dist/surfaces/stardewvalley/mods.js +182 -0
  257. package/dist/surfaces/stardewvalley/surface.js +244 -0
  258. package/dist/surfaces/stardewvalley/validators/content.js +321 -0
  259. package/dist/surfaces/stardewvalley/validators/fields.js +147 -0
  260. package/dist/surfaces/stardewvalley/validators/loadorder.js +69 -0
  261. package/dist/surfaces/stardewvalley/validators/manifest.js +221 -0
  262. package/dist/surfaces/subnautica2/compat.js +138 -0
  263. package/dist/surfaces/subnautica2/index.js +5 -0
  264. package/dist/surfaces/subnautica2/logs.js +129 -0
  265. package/dist/surfaces/subnautica2/paks.js +173 -0
  266. package/dist/surfaces/subnautica2/surface.js +151 -0
  267. package/dist/surfaces/subnautica2/validators/packaging.js +298 -0
  268. package/dist/surfaces/valheim/compat.js +171 -0
  269. package/dist/surfaces/valheim/index/index.js +301 -0
  270. package/dist/surfaces/valheim/index/tables.js +103 -0
  271. package/dist/surfaces/valheim/index.js +11 -0
  272. package/dist/surfaces/valheim/logs.js +197 -0
  273. package/dist/surfaces/valheim/packaging.js +131 -0
  274. package/dist/surfaces/valheim/plugins.js +270 -0
  275. package/dist/surfaces/valheim/references.js +121 -0
  276. package/dist/surfaces/valheim/surface.js +223 -0
  277. package/dist/surfaces/valheim/validators/packaging.js +218 -0
  278. package/dist/surfaces/valheim/validators/plugins.js +287 -0
  279. package/dist/surfaces/valheim/validators/references.js +169 -0
  280. package/knowledge/baldursgate3/animations.gr2.yaml +166 -0
  281. package/knowledge/baldursgate3/audio.voice.yaml +182 -0
  282. package/knowledge/baldursgate3/audio.wwise.yaml +104 -0
  283. package/knowledge/baldursgate3/charactercreation.heads-hair.yaml +193 -0
  284. package/knowledge/baldursgate3/communitylibrary.shared-content.yaml +129 -0
  285. package/knowledge/baldursgate3/compatibilityframework.api.yaml +176 -0
  286. package/knowledge/baldursgate3/crash.causes.yaml +90 -0
  287. package/knowledge/baldursgate3/dialogue.dialogbank.yaml +120 -0
  288. package/knowledge/baldursgate3/dialogue.files.yaml +236 -0
  289. package/knowledge/baldursgate3/dialogue.osiris-goals.yaml +386 -0
  290. package/knowledge/baldursgate3/dialogue.yaml +122 -0
  291. package/knowledge/baldursgate3/feats.classes.yaml +164 -0
  292. package/knowledge/baldursgate3/items.cloth-physics.yaml +167 -0
  293. package/knowledge/baldursgate3/items.roottemplates.yaml +320 -0
  294. package/knowledge/baldursgate3/items.visualbank.yaml +628 -0
  295. package/knowledge/baldursgate3/journal.quests.yaml +214 -0
  296. package/knowledge/baldursgate3/loadorder.modsettings.yaml +128 -0
  297. package/knowledge/baldursgate3/localization.handles.yaml +92 -0
  298. package/knowledge/baldursgate3/misc.encoding-and-practice.yaml +111 -0
  299. package/knowledge/baldursgate3/origins.companions.yaml +144 -0
  300. package/knowledge/baldursgate3/osiris.signatures.yaml +211 -0
  301. package/knowledge/baldursgate3/packaging.meta.yaml +155 -0
  302. package/knowledge/baldursgate3/packaging.paks.yaml +79 -0
  303. package/knowledge/baldursgate3/process.launch.yaml +34 -0
  304. package/knowledge/baldursgate3/progressions.yaml +92 -0
  305. package/knowledge/baldursgate3/publishing.modio-nexus.yaml +170 -0
  306. package/knowledge/baldursgate3/publishing.toolkit-modio.yaml +135 -0
  307. package/knowledge/baldursgate3/races.progression.yaml +228 -0
  308. package/knowledge/baldursgate3/scriptextender.console.yaml +257 -0
  309. package/knowledge/baldursgate3/scriptextender.yaml +252 -0
  310. package/knowledge/baldursgate3/stats.boosts.yaml +293 -0
  311. package/knowledge/baldursgate3/stats.equipment-kits.yaml +69 -0
  312. package/knowledge/baldursgate3/stats.interrupts.yaml +45 -0
  313. package/knowledge/baldursgate3/stats.itemcombos.yaml +65 -0
  314. package/knowledge/baldursgate3/stats.spells.yaml +293 -0
  315. package/knowledge/baldursgate3/stats.weapons.yaml +210 -0
  316. package/knowledge/baldursgate3/toolchain.divine.yaml +179 -0
  317. package/knowledge/baldursgate3/toolchain.lslib-formats.yaml +242 -0
  318. package/knowledge/baldursgate3/toolkit.levels.yaml +177 -0
  319. package/knowledge/baldursgate3/ui.icons-atlas.yaml +78 -0
  320. package/knowledge/baldursgate3/ui.icons.yaml +412 -0
  321. package/knowledge/baldursgate3/ui.mcm.yaml +161 -0
  322. package/knowledge/baldursgate3/vfx.materials.yaml +174 -0
  323. package/knowledge/baldursgate3/visuals.characterfix.yaml +73 -0
  324. package/knowledge/cyberpunk2077/animations.anims.yaml +118 -0
  325. package/knowledge/cyberpunk2077/anims.archivexl.yaml +163 -0
  326. package/knowledge/cyberpunk2077/anims.authoring.yaml +579 -0
  327. package/knowledge/cyberpunk2077/anims.encoder.yaml +156 -0
  328. package/knowledge/cyberpunk2077/anims.graph.yaml +629 -0
  329. package/knowledge/cyberpunk2077/anims.method.yaml +360 -0
  330. package/knowledge/cyberpunk2077/anims.pipeline.yaml +352 -0
  331. package/knowledge/cyberpunk2077/anims.roundtrip.yaml +222 -0
  332. package/knowledge/cyberpunk2077/anims.sets.yaml +176 -0
  333. package/knowledge/cyberpunk2077/archivexl.bodytypes.yaml +149 -0
  334. package/knowledge/cyberpunk2077/archivexl.dynamic-appearances.yaml +218 -0
  335. package/knowledge/cyberpunk2077/archivexl.manifest.yaml +214 -0
  336. package/knowledge/cyberpunk2077/audio.events.yaml +168 -0
  337. package/knowledge/cyberpunk2077/audio.sounds.yaml +164 -0
  338. package/knowledge/cyberpunk2077/audio.voicesets.yaml +146 -0
  339. package/knowledge/cyberpunk2077/cet.sandbox.yaml +219 -0
  340. package/knowledge/cyberpunk2077/clothing.garments.yaml +283 -0
  341. package/knowledge/cyberpunk2077/clothing.refits.yaml +215 -0
  342. package/knowledge/cyberpunk2077/codeware.overview.yaml +111 -0
  343. package/knowledge/cyberpunk2077/codeware.systems.yaml +192 -0
  344. package/knowledge/cyberpunk2077/drones.combat.yaml +416 -0
  345. package/knowledge/cyberpunk2077/drones.control.yaml +552 -0
  346. package/knowledge/cyberpunk2077/entities.appearance.yaml +166 -0
  347. package/knowledge/cyberpunk2077/equipmentex.slots.yaml +151 -0
  348. package/knowledge/cyberpunk2077/fx.effects.yaml +246 -0
  349. package/knowledge/cyberpunk2077/fx.lights.yaml +171 -0
  350. package/knowledge/cyberpunk2077/hair.modding.yaml +145 -0
  351. package/knowledge/cyberpunk2077/items.wiring.yaml +246 -0
  352. package/knowledge/cyberpunk2077/loadorder.archives.yaml +71 -0
  353. package/knowledge/cyberpunk2077/mesh.blender.yaml +209 -0
  354. package/knowledge/cyberpunk2077/nativedb.dump.yaml +98 -0
  355. package/knowledge/cyberpunk2077/npc.appearance.yaml +275 -0
  356. package/knowledge/cyberpunk2077/npc.behaviour.yaml +128 -0
  357. package/knowledge/cyberpunk2077/npc.locomotion.yaml +490 -0
  358. package/knowledge/cyberpunk2077/packaging.deploy.yaml +175 -0
  359. package/knowledge/cyberpunk2077/packaging.variants.yaml +176 -0
  360. package/knowledge/cyberpunk2077/player.control.yaml +918 -0
  361. package/knowledge/cyberpunk2077/process.assetbuild.yaml +154 -0
  362. package/knowledge/cyberpunk2077/process.lessons.yaml +276 -0
  363. package/knowledge/cyberpunk2077/quests.minor.yaml +46 -0
  364. package/knowledge/cyberpunk2077/quests.scenes.yaml +282 -0
  365. package/knowledge/cyberpunk2077/quickhacks.tiers.yaml +41 -0
  366. package/knowledge/cyberpunk2077/red4ext.api.yaml +645 -0
  367. package/knowledge/cyberpunk2077/red4ext.plugins.yaml +124 -0
  368. package/knowledge/cyberpunk2077/redhottools.hotreload.yaml +245 -0
  369. package/knowledge/cyberpunk2077/redscript.compile-log.yaml +76 -0
  370. package/knowledge/cyberpunk2077/redscript.modules.yaml +118 -0
  371. package/knowledge/cyberpunk2077/toolchain.wolvenkit.yaml +163 -0
  372. package/knowledge/cyberpunk2077/tweakdb.loot-recipes.yaml +184 -0
  373. package/knowledge/cyberpunk2077/tweakdb.melee.yaml +352 -0
  374. package/knowledge/cyberpunk2077/tweakdb.weapons.yaml +325 -0
  375. package/knowledge/cyberpunk2077/tweakxl.hotreload.yaml +151 -0
  376. package/knowledge/cyberpunk2077/tweakxl.yaml-syntax.yaml +208 -0
  377. package/knowledge/cyberpunk2077/ui.icons.yaml +259 -0
  378. package/knowledge/cyberpunk2077/ui.inkatlas.yaml +81 -0
  379. package/knowledge/cyberpunk2077/ui.modsettings.yaml +204 -0
  380. package/knowledge/cyberpunk2077/vehicles.control.yaml +475 -0
  381. package/knowledge/cyberpunk2077/vehicles.dashboard-ui.yaml +203 -0
  382. package/knowledge/cyberpunk2077/vehicles.entities.yaml +195 -0
  383. package/knowledge/cyberpunk2077/vehicles.wiring.yaml +137 -0
  384. package/knowledge/cyberpunk2077/wolvenkit.cli.yaml +167 -0
  385. package/knowledge/cyberpunk2077/workspot.system.yaml +55 -0
  386. package/knowledge/cyberpunk2077/world.interactions.yaml +41 -0
  387. package/knowledge/cyberpunk2077/world.loot-container.yaml +167 -0
  388. package/knowledge/cyberpunk2077/world.sectors.yaml +233 -0
  389. package/knowledge/eldenring/formats.binders.yaml +237 -0
  390. package/knowledge/eldenring/launcher.me3.yaml +230 -0
  391. package/knowledge/eldenring/launcher.modengine2.yaml +119 -0
  392. package/knowledge/eldenring/params.paramdef.yaml +149 -0
  393. package/knowledge/eldenring/params.regulation.yaml +142 -0
  394. package/knowledge/eldenring/saves.online.yaml +118 -0
  395. package/knowledge/eldenring/toolchain.cli.yaml +256 -0
  396. package/knowledge/nivalisnights/modding.runtime.yaml +157 -0
  397. package/knowledge/skyrimse/archives.bsa.yaml +212 -0
  398. package/knowledge/skyrimse/install.detection.yaml +41 -0
  399. package/knowledge/skyrimse/loadorder.files.yaml +242 -0
  400. package/knowledge/skyrimse/plugins.esl.yaml +189 -0
  401. package/knowledge/skyrimse/plugins.format.yaml +224 -0
  402. package/knowledge/skyrimse/skse.runtime.yaml +283 -0
  403. package/knowledge/skyrimse/toolchain.xedit-spriggit.yaml +336 -0
  404. package/knowledge/stardewvalley/contentpatcher.format.yaml +338 -0
  405. package/knowledge/stardewvalley/distribution.channels.yaml +236 -0
  406. package/knowledge/stardewvalley/game.versions.yaml +202 -0
  407. package/knowledge/stardewvalley/install.layout.yaml +277 -0
  408. package/knowledge/stardewvalley/smapi.loader.yaml +284 -0
  409. package/knowledge/stardewvalley/smapi.logs.yaml +329 -0
  410. package/knowledge/stardewvalley/smapi.manifest.yaml +293 -0
  411. package/knowledge/stardewvalley/toolchain.build.yaml +261 -0
  412. package/knowledge/stardewvalley/wiki.dataformat.yaml +130 -0
  413. package/knowledge/subnautica2/game.build.yaml +331 -0
  414. package/knowledge/subnautica2/modding.state.yaml +210 -0
  415. package/knowledge/subnautica2/ue5.containers.yaml +72 -0
  416. package/knowledge/subnautica2/ue5.paks.yaml +203 -0
  417. package/knowledge/subnautica2/ue5.tooling.yaml +175 -0
  418. package/knowledge/subnautica2/ue5.ue4ss.yaml +203 -0
  419. package/knowledge/valheim/bepinex.loader.yaml +247 -0
  420. package/knowledge/valheim/bepinex.plugins.yaml +251 -0
  421. package/knowledge/valheim/game.versions.yaml +321 -0
  422. package/knowledge/valheim/install.layout.yaml +216 -0
  423. package/knowledge/valheim/jotunn.library.yaml +334 -0
  424. package/knowledge/valheim/thunderstore.packaging.yaml +217 -0
  425. package/knowledge/valheim/toolchain.build.yaml +111 -0
  426. package/package.json +29 -0
  427. package/scaffolds/baldursgate3/new-class-injection.yaml +148 -0
  428. package/scaffolds/baldursgate3/new-item.yaml +264 -0
  429. package/scaffolds/baldursgate3/new-mod.yaml +174 -0
  430. package/scaffolds/baldursgate3/new-passive.yaml +100 -0
  431. package/scaffolds/baldursgate3/new-project.yaml +118 -0
  432. package/scaffolds/baldursgate3/new-quest-stub.yaml +159 -0
  433. package/scaffolds/baldursgate3/new-spell.yaml +102 -0
  434. package/scaffolds/baldursgate3/new-status.yaml +119 -0
  435. package/scaffolds/baldursgate3/sequences/subclass-kit.yaml +50 -0
  436. package/scaffolds/cyberpunk2077/edit-tweak.yaml +70 -0
  437. package/scaffolds/cyberpunk2077/mesh-export-preset.yaml +170 -0
  438. package/scaffolds/cyberpunk2077/new-entity-patch.yaml +255 -0
  439. package/scaffolds/cyberpunk2077/new-garment-refit.yaml +279 -0
  440. package/scaffolds/cyberpunk2077/new-item-chain.yaml +548 -0
  441. package/scaffolds/cyberpunk2077/new-localization.yaml +130 -0
  442. package/scaffolds/cyberpunk2077/new-mod-settings.yaml +133 -0
  443. package/scaffolds/cyberpunk2077/new-player-replacer.yaml +1003 -0
  444. package/scaffolds/cyberpunk2077/new-project.yaml +157 -0
  445. package/scaffolds/cyberpunk2077/new-sector-node.yaml +156 -0
  446. package/scaffolds/cyberpunk2077/new-tweak.yaml +121 -0
  447. package/scaffolds/cyberpunk2077/new-vehicle-livery.yaml +148 -0
  448. package/scaffolds/cyberpunk2077/new-workspot-entity.yaml +177 -0
  449. package/scaffolds/cyberpunk2077/sequences/iconic-weapon.yaml +72 -0
  450. package/scaffolds/cyberpunk2077/sequences/quickhack-takeover.yaml +213 -0
  451. package/scaffolds/stardewvalley/new-cp-patch.yaml +106 -0
  452. package/scaffolds/stardewvalley/new-csharp-mod.yaml +195 -0
  453. package/scaffolds/stardewvalley/new-project.yaml +184 -0
  454. package/scaffolds/stardewvalley/sequences/content-pack.yaml +31 -0
  455. package/scripts/mw-tool.mjs +184 -0
@@ -0,0 +1,351 @@
1
+ import { homePath, localAppData } from "../fsutil.js";
2
+ export const TOOL_SPECS = [
3
+ {
4
+ id: "divine",
5
+ label: "LSLib Divine (divine.exe)",
6
+ executables: ["divine.exe", "Divine.exe", "divine"],
7
+ candidates: [
8
+ "C:/ExportTool*/Tools/divine.exe",
9
+ "C:/ExportTool*/divine.exe",
10
+ homePath("LSLib*", "Tools", "divine.exe"),
11
+ ],
12
+ envVar: "MODWRIGHT_TOOL_DIVINE",
13
+ usedBy: ["baldursgate3"],
14
+ homepage: "https://github.com/Norbyte/lslib",
15
+ notes: "create-package silently writes an empty 48-byte package when any directory in the -s path " +
16
+ "starts with a dot (measured); stage BG3 builds outside dot-prefixed dirs. " +
17
+ "No CLI version flag exists (verified against Divine's CommandLineArguments.cs; " +
18
+ "`--version` answers `[FATAL] Unknown argument found: version.`). The PE and .NET " +
19
+ "assembly versions of Divine.exe and LSLib.dll are both 0.0.0.0 (measured), so " +
20
+ "the only version source is the ExportTool-vX.Y.Z zip name it was extracted from. " +
21
+ "Ships as a portable zip; no installer, no fixed path.",
22
+ },
23
+ {
24
+ id: "wolvenkit-cli",
25
+ label: "WolvenKit CLI",
26
+ executables: ["WolvenKit.CLI.exe", "WolvenKit.CLI"],
27
+ candidates: [
28
+ "C:/Cyberpunk2077Mod/WolvenKit.CLI/WolvenKit.CLI.exe",
29
+ localAppData("Programs", "WolvenKit*", "WolvenKit.CLI.exe"),
30
+ ],
31
+ envVar: "MODWRIGHT_TOOL_WOLVENKIT_CLI",
32
+ versionArgs: ["--version"],
33
+ versionPattern: /(\d+\.\d+(?:\.\d+)?)/,
34
+ usedBy: ["cyberpunk2077"],
35
+ homepage: "https://wiki.redmodding.org/wolvenkit/",
36
+ notes: "`--version` prints the bare version (verified on 8.20.0). " +
37
+ "Ships as a portable zip (WolvenKit.Console-<version>.zip), no installer, no fixed path.",
38
+ },
39
+ {
40
+ id: "blender",
41
+ label: "Blender",
42
+ executables: ["blender.exe", "blender"],
43
+ candidates: [
44
+ "C:/Program Files/Blender Foundation/Blender */blender.exe",
45
+ "C:/Program Files (x86)/Blender Foundation/Blender */blender.exe",
46
+ "C:/Program Files (x86)/Steam/steamapps/common/Blender/blender.exe",
47
+ "/usr/bin/blender",
48
+ "/snap/bin/blender",
49
+ ],
50
+ envVar: "MODWRIGHT_TOOL_BLENDER",
51
+ versionArgs: ["--version"],
52
+ versionPattern: /Blender\s+(\d+\.\d+(?:\.\d+)?)/,
53
+ usedBy: ["baldursgate3", "cyberpunk2077"],
54
+ homepage: "https://www.blender.org/download/",
55
+ notes: "`--version` output confirmed against Blender's official manual.",
56
+ },
57
+ {
58
+ id: "vgmstream",
59
+ label: "vgmstream-cli",
60
+ executables: ["vgmstream-cli.exe", "vgmstream-cli", "vgmstream_cli.exe", "vgmstream_cli"],
61
+ candidates: [
62
+ "C:/vgmstream/vgmstream-cli.exe",
63
+ homePath("vgmstream*", "vgmstream-cli.exe"),
64
+ "/usr/bin/vgmstream-cli",
65
+ "/usr/local/bin/vgmstream-cli",
66
+ ],
67
+ envVar: "MODWRIGHT_TOOL_VGMSTREAM",
68
+ versionArgs: ["-h"],
69
+ versionPattern: /vgmstream CLI decoder\s+(\S+)/,
70
+ usedBy: ["baldursgate3"],
71
+ homepage: "https://vgmstream.org/",
72
+ notes: "-h/-V print a version only when the binary was built with " +
73
+ "VGMSTREAM_VERSION set (most release builds are); a from-source build " +
74
+ "without it reports \"unknown version\" and this adapter reports \"unknown\".",
75
+ },
76
+ {
77
+ id: "sseedit",
78
+ label: "SSEEdit (xEdit for Skyrim SE)",
79
+ executables: ["SSEEdit64.exe", "SSEEdit.exe", "xEdit64.exe", "xEdit.exe"],
80
+ candidates: [
81
+ "C:/Modding/SSEEdit*/SSEEdit64.exe",
82
+ "C:/Modding/xEdit*/SSEEdit64.exe",
83
+ "C:/Games/SSEEdit*/SSEEdit64.exe",
84
+ ],
85
+ envVar: "MODWRIGHT_TOOL_SSEEDIT",
86
+ usedBy: ["skyrimse"],
87
+ homepage: "https://github.com/TES5Edit/TES5Edit",
88
+ notes: "No version flag is documented (the About dialog only). Unattended use: the check modes " +
89
+ "and `-qac -autoload <plugin> -autoexit`, whose exit code is the error/ITM/UDR count capped " +
90
+ "at 127. A fresh machine can still show the donation modal and a first-64-bit-start " +
91
+ "confirmation, so a first unattended run may hang; `-script:` with a missing path opens a " +
92
+ "file dialog rather than failing. The binary picks its game from its own filename, so an " +
93
+ "xEdit.exe that has not been renamed to SSEEdit needs `-sse`.",
94
+ },
95
+ {
96
+ id: "spriggit",
97
+ label: "Spriggit CLI",
98
+ executables: ["Spriggit.CLI.exe", "Spriggit.CLI", "spriggit"],
99
+ candidates: [homePath("Spriggit*", "Spriggit.CLI.exe"), "C:/Modding/Spriggit*/Spriggit.CLI.exe"],
100
+ envVar: "MODWRIGHT_TOOL_SPRIGGIT",
101
+ usedBy: ["skyrimse"],
102
+ homepage: "https://github.com/Mutagen-Modding/Spriggit",
103
+ notes: "Plugin <-> YAML/JSON for version control; a first-party Linux binary and a dotnet tool " +
104
+ "exist. No version flag documented: the `.spriggit` file and `spriggit-meta.json` record the " +
105
+ "package version instead. GPL-3.0: run as a tool, never linked.",
106
+ },
107
+ {
108
+ id: "bsarch",
109
+ label: "BSArch",
110
+ executables: ["bsarch.exe", "bsarch"],
111
+ candidates: ["C:/Modding/SSEEdit*/Tools/BSArchive/bsarch.exe", "C:/Modding/xEdit*/Tools/BSArchive/bsarch.exe", "C:/Games/SSEEdit*/Tools/BSArchive/bsarch.exe"],
112
+ envVar: "MODWRIGHT_TOOL_BSARCH",
113
+ usedBy: ["skyrimse"],
114
+ homepage: "https://github.com/TES5Edit/TES5Edit/tree/dev/Tools/BSArchive",
115
+ notes: "Ships inside xEdit's Tools/BSArchive. Prints `sVersion = '0.7'` in its help banner (the " +
116
+ "banner's argv is not sourced, so no probe is declared). Exit 1 only on an unhandled exception.",
117
+ },
118
+ {
119
+ id: "papyrus-compiler",
120
+ label: "Papyrus Compiler",
121
+ executables: ["PapyrusCompiler.exe"],
122
+ candidates: [
123
+ "C:/Program Files (x86)/Steam/steamapps/common/Skyrim Special Edition/Papyrus Compiler/PapyrusCompiler.exe",
124
+ ],
125
+ envVar: "MODWRIGHT_TOOL_PAPYRUS_COMPILER",
126
+ usedBy: ["skyrimse"],
127
+ homepage: "https://ck.uesp.net/wiki/Papyrus_Compiler_Reference",
128
+ notes: "Per-script invocation with -f=<flags> -i=<import dirs> -o=<output dir>; a version flag is " +
129
+ "not sourced. Lives under the game root once the Creation Kit is installed.",
130
+ },
131
+ {
132
+ id: "loot",
133
+ label: "LOOT",
134
+ executables: ["LOOT.exe", "loot"],
135
+ candidates: ["C:/Program Files/LOOT/LOOT.exe", localAppData("Programs", "LOOT", "LOOT.exe")],
136
+ envVar: "MODWRIGHT_TOOL_LOOT",
137
+ usedBy: ["skyrimse"],
138
+ homepage: "https://loot.github.io/",
139
+ notes: "`--game=\"Skyrim Special Edition\" --auto-sort` sorts and quits; the exit code is " +
140
+ "undocumented, and no version flag is documented on the CLI. Candidate paths are the " +
141
+ "installer's conventions, not verified.",
142
+ },
143
+ {
144
+ id: "creationkit",
145
+ label: "Creation Kit (Skyrim SE)",
146
+ executables: ["CreationKit.exe"],
147
+ candidates: ["C:/Program Files (x86)/Steam/steamapps/common/Skyrim Special Edition/CreationKit.exe"],
148
+ envVar: "MODWRIGHT_TOOL_CREATIONKIT",
149
+ usedBy: ["skyrimse"],
150
+ homepage: "https://ck.uesp.net/",
151
+ notes: "GUI only: detected and reported, never driven. Its PE FileVersion is the version; no CLI flag.",
152
+ },
153
+ {
154
+ id: "witchybnd",
155
+ label: "WitchyBND",
156
+ executables: ["WitchyBND.exe", "WitchyBND"],
157
+ candidates: [
158
+ "C:/Modding/WitchyBND*/WitchyBND.exe",
159
+ "C:/Games/WitchyBND*/WitchyBND.exe",
160
+ homePath("Downloads", "WitchyBND*", "WitchyBND.exe"),
161
+ ],
162
+ envVar: "MODWRIGHT_TOOL_WITCHYBND",
163
+ versionArgs: ["-v"],
164
+ versionPattern: /WitchyBND v(\d+(?:\.\d+)+)/,
165
+ usedBy: ["eldenring"],
166
+ homepage: "https://github.com/ividyon/WitchyBND",
167
+ notes: "Unpacks and repacks binders, DCX, TPF and params, and decrypts regulation.bin itself. " +
168
+ "Unattended use is `-p` (passive: no prompts or delays) or `-s` (silent, implies passive), " +
169
+ "with `-u`/`-r` pinning the direction; `-c` is recursive, not a CLI switch, and there is " +
170
+ "no --cli. Its round trip writes a `_witchy-<tag>.xml` sidecar the repack validates " +
171
+ "against. A second version axis, which no flag prints, is the newest regulation its " +
172
+ "bundled Paramdex can repack: Assets/Paramdex/ER/Upgrader/version.txt beside the exe. " +
173
+ "Its README warns against PARAM repacking for serious work; params are read-only here.",
174
+ },
175
+ {
176
+ id: "dsmsportable",
177
+ label: "DSMSPortable",
178
+ executables: ["DSMSPortable.exe"],
179
+ candidates: ["C:/Modding/DSMSPortable*/DSMSPortable.exe", homePath("Downloads", "DSMSPortable*", "DSMSPortable.exe")],
180
+ envVar: "MODWRIGHT_TOOL_DSMSPORTABLE",
181
+ usedBy: ["eldenring"],
182
+ homepage: "https://github.com/mountlover/DSMSPortable",
183
+ notes: "The one unattended param CLI: applies CSV and mass-edit scripts to regulation.bin, " +
184
+ "exports, diffs and upgrades params, and merges FMG/TPF/BND/HKS/EMEVD/TAE files. No " +
185
+ "version flag (VERSION is a literal in Program.cs, 1.9); needs the .NET 6 Desktop " +
186
+ "Runtime, and a negative exit code means it is missing. Its README's exit-code table " +
187
+ "(0 success .. 20 massedit parse error) is mapped in surfaces/eldenring/tools.ts. Last " +
188
+ "release 2024-07-01, absent from the community wiki's tool list: viable, not a safe default.",
189
+ },
190
+ {
191
+ id: "me3",
192
+ label: "me3 (mod loader CLI)",
193
+ executables: ["me3.exe", "me3"],
194
+ candidates: [localAppData("Programs", "me3", "bin", "me3.exe"), "C:/Program Files/me3/bin/me3.exe"],
195
+ envVar: "MODWRIGHT_TOOL_ME3",
196
+ versionArgs: ["--version"],
197
+ versionPattern: /me3 (\d+\.\d+\.\d+(?:[-+][\w.]+)?)/,
198
+ usedBy: ["eldenring"],
199
+ homepage: "https://github.com/garyttierney/me3",
200
+ notes: "The maintained loader, driven as a CLI: `me3 launch -p <profile.me3>`, `me3 info` " +
201
+ "(prints the profile and logs directories and whether Steam was found), " +
202
+ "`me3 profile create|list|show`. Candidate paths are guesses at the installer's layout, " +
203
+ "not verified; the installer registers .me3 files so the exe is normally on PATH.",
204
+ },
205
+ {
206
+ id: "dotnet",
207
+ label: ".NET SDK",
208
+ executables: ["dotnet.exe", "dotnet"],
209
+ candidates: ["C:/Program Files/dotnet/dotnet.exe", "/usr/bin/dotnet", "/usr/local/share/dotnet/dotnet"],
210
+ envVar: "MODWRIGHT_TOOL_DOTNET",
211
+ versionArgs: ["--version"],
212
+ versionPattern: /^\s*(\d+\.\d+\.\d+(?:-[\w.]+)?)/m,
213
+ usedBy: ["valheim", "stardewvalley", "nivalisnights"],
214
+ homepage: "https://dotnet.microsoft.com/download",
215
+ notes: "`dotnet build -c Release` compiles a BepInEx plugin (a net48 class library referencing " +
216
+ "BepInEx and the developer's own publicized game assemblies). `--version` prints the SDK " +
217
+ "version alone. Which SDK band a project needs is its global.json's business.",
218
+ },
219
+ {
220
+ id: "cpp2il",
221
+ label: "Cpp2IL",
222
+ executables: ["Cpp2IL.exe", "Cpp2IL"],
223
+ candidates: [],
224
+ envVar: "MODWRIGHT_TOOL_CPP2IL",
225
+ versionArgs: ["--version"],
226
+ versionPattern: /Version (\S+)/,
227
+ usedBy: ["nivalisnights"],
228
+ homepage: "https://github.com/SamboyCoding/Cpp2IL/releases",
229
+ notes: "Rebuilds dummy .NET assemblies from an IL2CPP game's GameAssembly.dll and global-metadata.dat. " +
230
+ "The Nivalis Nights index runs it with `--use-processor attributeanalyzer,attributeinjector " +
231
+ "--output-as dummydll`; without the attribute processors private [SerializeField] fields are " +
232
+ "missing and asset decoding goes wrong. It writes a Plugins folder into its " +
233
+ "working directory, so it is run from the cache, never from a repo. Tested: pre-release.21.",
234
+ managed: {
235
+ kind: "download",
236
+ version: "2022.1.0-pre-release.21",
237
+ license: "MIT",
238
+ fileName: { win32: "Cpp2IL.exe", other: "Cpp2IL" },
239
+ assets: [
240
+ { platform: "win32", arch: "x64", url: "https://github.com/SamboyCoding/Cpp2IL/releases/download/2022.1.0-pre-release.21/Cpp2IL-2022.1.0-pre-release.21-Windows.exe", sizeBytes: 15137811, sha256: "663fb432433b4371fd1ee0ebc321a8fff2a9aac5ac4230c843f9e03ddee4e04c" },
241
+ { platform: "win32", arch: "arm64", url: "https://github.com/SamboyCoding/Cpp2IL/releases/download/2022.1.0-pre-release.21/Cpp2IL-2022.1.0-pre-release.21-Windows-ARM64.exe", sizeBytes: 15585309, sha256: "8986f219b5992f9290cb13e1f49431756cbd8865f1cf1f5a38ba61acc27cc1fb" },
242
+ { platform: "linux", arch: "x64", url: "https://github.com/SamboyCoding/Cpp2IL/releases/download/2022.1.0-pre-release.21/Cpp2IL-2022.1.0-pre-release.21-Linux", sizeBytes: 17257994, sha256: "526998e593c52c029c5a6215c5c6c9f9d963706bfc409fc9ff80a95c4c500349" },
243
+ { platform: "linux", arch: "arm64", url: "https://github.com/SamboyCoding/Cpp2IL/releases/download/2022.1.0-pre-release.21/Cpp2IL-2022.1.0-pre-release.21-Linux-ARM64", sizeBytes: 16608573, sha256: "2d8e76b11f52fd85440ec60abf87d5c3455ea54f5104e0af51da15ba4440871b" },
244
+ { platform: "darwin", arch: "x64", url: "https://github.com/SamboyCoding/Cpp2IL/releases/download/2022.1.0-pre-release.21/Cpp2IL-2022.1.0-pre-release.21-OSX", sizeBytes: 16522622, sha256: "15faab020698512807f792aef32a89fe529d41d2cc03955dd3516f0519fe8f72" },
245
+ { platform: "darwin", arch: "arm64", url: "https://github.com/SamboyCoding/Cpp2IL/releases/download/2022.1.0-pre-release.21/Cpp2IL-2022.1.0-pre-release.21-OSX-ARM64", sizeBytes: 15719263, sha256: "6670ddb93f28d4e7f329251d2597d2abbc6ba23e46382f7ca7b5e437ec93606a" },
246
+ ],
247
+ },
248
+ },
249
+ {
250
+ id: "unitypy-python",
251
+ label: "Python with UnityPy and TypeTreeGeneratorAPI",
252
+ executables: ["python.exe", "python3", "python"],
253
+ candidates: [],
254
+ envVar: "MODWRIGHT_TOOL_UNITYPY_PYTHON",
255
+ versionArgs: ["-c", "import UnityPy, TypeTreeGeneratorAPI; print('UnityPy', UnityPy.__version__)"],
256
+ versionPattern: /UnityPy (\S+)/,
257
+ usedBy: ["nivalisnights"],
258
+ homepage: "https://github.com/K0lb3/UnityPy",
259
+ notes: "Any Python 3.8+ with `pip install UnityPy TypeTreeGeneratorAPI` (tested: UnityPy 1.25.3, " +
260
+ "TypeTreeGeneratorAPI 0.0.10, Python 3.14). A venv is the clean route: point " +
261
+ "MODWRIGHT_TOOL_UNITYPY_PYTHON at its python.exe. Runs assets/nivalisnights/extract_resources.py " +
262
+ "for the Nivalis Nights index.",
263
+ managed: {
264
+ kind: "python-venv",
265
+ version: "1.25.3",
266
+ license: "MIT (UnityPy, TypeTreeGeneratorAPI)",
267
+ pythonMin: [3, 8],
268
+ packages: ["UnityPy==1.25.3", "TypeTreeGeneratorAPI==0.0.10"],
269
+ constraints: [
270
+ "archspec==0.2.6", "astc-encoder-py==0.1.12", "attrs==26.1.0", "brotli==1.2.0", "etcpak==0.9.15",
271
+ "fmod_toolkit==0.1.3", "fsspec==2026.9.0", "lz4==4.4.5", "pillow==12.3.0", "pyfmodex==0.7.2",
272
+ "texture2ddecoder==1.0.6", "tpk_ar==0.2.4", "TypeTreeGeneratorAPI==0.0.10", "UnityPy==1.25.3",
273
+ ],
274
+ index: "https://pypi.org/simple",
275
+ },
276
+ },
277
+ {
278
+ id: "tcli",
279
+ label: "Thunderstore CLI (tcli)",
280
+ executables: ["tcli.exe", "tcli"],
281
+ candidates: [homePath(".dotnet", "tools", "tcli.exe"), homePath(".dotnet", "tools", "tcli")],
282
+ envVar: "MODWRIGHT_TOOL_TCLI",
283
+ usedBy: ["valheim"],
284
+ homepage: "https://github.com/thunderstore-io/thunderstore-cli",
285
+ notes: "Installed with `dotnet tool install -g tcli` into ~/.dotnet/tools. `tcli init|build|publish` " +
286
+ "over a thunderstore.toml; it assembles manifest.json and the zip and compiles nothing " +
287
+ "(\"any actual build actions ... must be performed separately\", tcli wiki, Building). Its own " +
288
+ "wiki shows `--version` on every verb and a `version` command, but the shape of that output " +
289
+ "was never read from a run, so nothing is probed rather than a pattern being guessed.",
290
+ },
291
+ {
292
+ id: "retoc",
293
+ label: "retoc (IoStore pack/unpack, Zen <-> Legacy)",
294
+ executables: ["retoc.exe", "retoc"],
295
+ candidates: ["C:/Modding/retoc*/retoc.exe", homePath("Downloads", "retoc*", "retoc.exe"), homePath(".cargo", "bin", "retoc.exe")],
296
+ envVar: "MODWRIGHT_TOOL_RETOC",
297
+ usedBy: ["subnautica2"],
298
+ homepage: "https://github.com/trumank/retoc",
299
+ notes: "The load-bearing tool for an IoStore game: `to-legacy` (Zen assets to a legacy pak, for " +
300
+ "inspection and editing) and `to-zen` (legacy pak to .utoc/.ucas the game mounts), plus " +
301
+ "info, list, verify, manifest, unpack, pack-raw, gen-script-objects; `--version` names the " +
302
+ "target engine (UE5_6 here) and `--aes-key` the key. v0.1.5 (2026-01-02). No version probe: " +
303
+ "not checked against the binary.",
304
+ },
305
+ {
306
+ id: "repak",
307
+ label: "repak (legacy .pak)",
308
+ executables: ["repak.exe", "repak"],
309
+ candidates: ["C:/Modding/repak*/repak.exe", homePath("Downloads", "repak*", "repak.exe"), homePath(".cargo", "bin", "repak.exe")],
310
+ envVar: "MODWRIGHT_TOOL_REPAK",
311
+ usedBy: ["subnautica2"],
312
+ homepage: "https://github.com/trumank/repak",
313
+ notes: "Legacy .pak only (versions 2-11, UE 4.0 to 5.3): info, list, hash-list, unpack, pack, get. " +
314
+ "Its default mount point ../../../ matches this game's. It cannot write compressed paks or " +
315
+ "an encrypted index, and it neither reads nor writes .utoc/.ucas, so it is the legacy half " +
316
+ "of a retoc pipeline. v0.2.3 (2026-01-02). No version probe: not checked against the binary.",
317
+ },
318
+ {
319
+ id: "uassetgui",
320
+ label: "UAssetGUI (UAssetAPI JSON round trip)",
321
+ executables: ["UAssetGUI.exe"],
322
+ candidates: ["C:/Modding/UAssetGUI*/UAssetGUI.exe", homePath("Downloads", "UAssetGUI*", "UAssetGUI.exe")],
323
+ envVar: "MODWRIGHT_TOOL_UASSETGUI",
324
+ usedBy: ["subnautica2"],
325
+ homepage: "https://github.com/atenfyr/UAssetGUI",
326
+ notes: "A .NET GUI with a CLI alongside it; UAssetAPI's JSON export/import is the cooked-asset " +
327
+ "analogue of the cr2w-json round trip and advertises binary equality. Needs a .usmap " +
328
+ "mappings file for a UE5 game, which only a running game can dump. As of 1.1.0 it embeds " +
329
+ "retoc for direct .utoc/.ucas access. No version probe: not checked against the binary.",
330
+ },
331
+ {
332
+ id: "stardewxnbhack",
333
+ label: "StardewXnbHack",
334
+ executables: ["StardewXnbHack.exe", "StardewXnbHack"],
335
+ candidates: [
336
+ "C:/Program Files/GOG Galaxy/Games/Stardew Valley/StardewXnbHack.exe",
337
+ "C:/Program Files (x86)/GOG Galaxy/Games/Stardew Valley/StardewXnbHack.exe",
338
+ "C:/Program Files (x86)/Steam/steamapps/common/Stardew Valley/StardewXnbHack.exe",
339
+ homePath(".steam", "steam", "steamapps", "common", "Stardew Valley", "StardewXnbHack"),
340
+ homePath("Library", "Application Support", "Steam", "steamapps", "common", "Stardew Valley", "StardewXnbHack"),
341
+ ],
342
+ envVar: "MODWRIGHT_TOOL_STARDEWXNBHACK",
343
+ usedBy: ["stardewvalley"],
344
+ homepage: "https://github.com/Pathoschild/StardewXnbHack",
345
+ notes: "Unpacks the game's Content/*.xnb into a 'Content (unpacked)' folder beside the game, in a " +
346
+ "form Content Patcher can already read; it is a second launcher for the installed game, not a " +
347
+ "converter, so it needs the game and lives in the game folder. It cannot repack, which is by " +
348
+ "design (Content Patcher edits assets in place). xnbcli is deliberately not listed: the wiki " +
349
+ "steers away from it.",
350
+ },
351
+ ];
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,66 @@
1
+ import { promises as fs } from "node:fs";
2
+ import * as path from "node:path";
3
+ import { z } from "zod";
4
+ import { userConfigDir, userDataDir } from "./home.js";
5
+ import { planFile, planMkdir } from "./safety/index.js";
6
+ export const USER_CONFIG_SCHEMA_VERSION = 1;
7
+ const toolEntrySchema = z.object({
8
+ path: z.string().min(1),
9
+ installedBy: z.enum(["user", "modwright"]).default("user"),
10
+ version: z.string().optional(),
11
+ sha256: z.string().optional(),
12
+ source: z.string().optional(),
13
+ rememberedAt: z.string().optional(),
14
+ });
15
+ const dataEntrySchema = z.object({
16
+ path: z.string().min(1),
17
+ rememberedAt: z.string().optional(),
18
+ });
19
+ const userConfigSchema = z.object({
20
+ schemaVersion: z.literal(USER_CONFIG_SCHEMA_VERSION),
21
+ tools: z.record(toolEntrySchema).default({}),
22
+ data: z.record(dataEntrySchema).default({}),
23
+ });
24
+ export function emptyUserConfig() {
25
+ return { schemaVersion: USER_CONFIG_SCHEMA_VERSION, tools: {}, data: {} };
26
+ }
27
+ export async function resolveDataDir(id, envVar, options = {}) {
28
+ const fromEnv = (options.env ?? process.env)[envVar];
29
+ if (fromEnv)
30
+ return { path: fromEnv, source: "env" };
31
+ const remembered = (await loadUserConfig(options.configFile)).config.data[id];
32
+ return remembered ? { path: remembered.path, source: "user" } : undefined;
33
+ }
34
+ export function userConfigFile() {
35
+ return path.join(userConfigDir(), "config.json");
36
+ }
37
+ export async function loadUserConfig(file = userConfigFile()) {
38
+ let text;
39
+ try {
40
+ text = await fs.readFile(file, "utf8");
41
+ }
42
+ catch (error) {
43
+ const missing = error.code === "ENOENT";
44
+ return { config: emptyUserConfig(), file, exists: !missing, problems: missing ? [] : [`${file} could not be read: ${error.message}`] };
45
+ }
46
+ let raw;
47
+ try {
48
+ raw = JSON.parse(text.replace(/^/, ""));
49
+ }
50
+ catch (error) {
51
+ return { config: emptyUserConfig(), file, exists: true, problems: [`${file} is not valid JSON (${error.message}); it is ignored until fixed.`] };
52
+ }
53
+ const parsed = userConfigSchema.safeParse(raw);
54
+ if (!parsed.success) {
55
+ const issues = parsed.error.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ");
56
+ return { config: emptyUserConfig(), file, exists: true, problems: [`${file} does not match schemaVersion ${USER_CONFIG_SCHEMA_VERSION} (${issues}); it is ignored until fixed.`] };
57
+ }
58
+ return { config: parsed.data, file, exists: true, problems: [] };
59
+ }
60
+ export function userConfigWritePlan(config, purpose, file = userConfigFile()) {
61
+ return {
62
+ purpose,
63
+ operations: [planMkdir(path.dirname(file)), planFile(file, JSON.stringify(config, null, 2) + "\n")],
64
+ backupRoot: path.join(userDataDir(), "backups"),
65
+ };
66
+ }
@@ -0,0 +1,139 @@
1
+ import { promises as fs } from "node:fs";
2
+ import * as path from "node:path";
3
+ import { pathExists, walk } from "../fsutil.js";
4
+ function toPosix(p) {
5
+ return p.split(path.sep).join("/");
6
+ }
7
+ export function isExcludedByGlobs(res, relSource, relProject) {
8
+ if (res.length === 0)
9
+ return false;
10
+ const candidates = new Set();
11
+ for (const rel of [relSource, relProject]) {
12
+ if (!rel)
13
+ continue;
14
+ const parts = rel.split("/");
15
+ for (let i = 1; i <= parts.length; i++)
16
+ candidates.add(parts.slice(0, i).join("/"));
17
+ }
18
+ for (const c of candidates)
19
+ if (res.some((re) => re.test(c)))
20
+ return true;
21
+ return false;
22
+ }
23
+ export function globToRegExp(glob) {
24
+ return new RegExp(`^${globBody(glob.replace(/\\/g, "/"))}$`, "i");
25
+ }
26
+ const SEP = "[\\\\/]";
27
+ const NOT_SEP = "[^\\\\/]";
28
+ function globBody(g) {
29
+ let out = "";
30
+ for (let i = 0; i < g.length; i++) {
31
+ const c = g[i];
32
+ if (c === "*") {
33
+ if (g[i + 1] === "*") {
34
+ i++;
35
+ if (g[i + 1] === "/") {
36
+ i++;
37
+ out += `(?:.*${SEP})?`;
38
+ }
39
+ else if (out.endsWith(SEP) && i === g.length - 1) {
40
+ out = `${out.slice(0, -SEP.length)}(?:${SEP}.*)?`;
41
+ }
42
+ else {
43
+ out += ".*";
44
+ }
45
+ }
46
+ else {
47
+ out += `${NOT_SEP}*`;
48
+ }
49
+ }
50
+ else if (c === "/") {
51
+ out += SEP;
52
+ }
53
+ else if (c === "?") {
54
+ out += NOT_SEP;
55
+ }
56
+ else if (c === "{") {
57
+ const close = g.indexOf("}", i + 1);
58
+ if (close === -1) {
59
+ out += "\\{";
60
+ continue;
61
+ }
62
+ const alternatives = g.slice(i + 1, close).split(",");
63
+ out += `(?:${alternatives.map(globBody).join("|")})`;
64
+ i = close;
65
+ }
66
+ else if ("\\^$.|+()[]{}".includes(c)) {
67
+ out += `\\${c}`;
68
+ }
69
+ else {
70
+ out += c;
71
+ }
72
+ }
73
+ return out;
74
+ }
75
+ export function buildContext(inputs) {
76
+ const { project, surface, install, store, changedFiles, listFilesOverride } = inputs;
77
+ const textCache = new Map();
78
+ const existsCache = new Map();
79
+ function readText(absPath) {
80
+ let cached = textCache.get(absPath);
81
+ if (!cached) {
82
+ cached = fs.readFile(absPath, "utf8");
83
+ textCache.set(absPath, cached);
84
+ }
85
+ return cached;
86
+ }
87
+ function exists(absPath) {
88
+ let cached = existsCache.get(absPath);
89
+ if (!cached) {
90
+ cached = pathExists(absPath);
91
+ existsCache.set(absPath, cached);
92
+ }
93
+ return cached;
94
+ }
95
+ async function lookup(kind, params) {
96
+ if (!store || !surface.index) {
97
+ throw new Error(`ValidationContext.lookup: no vanilla index open for "${surface.id}". A validator declaring ` +
98
+ `needs.index is never invoked without one — this call means a rule called lookup() despite not ` +
99
+ `declaring that need, or the runner failed to honour it.`);
100
+ }
101
+ return surface.index.query(store, kind, params);
102
+ }
103
+ const toRelative = (absPath) => toPosix(path.relative(project.root, absPath));
104
+ const toAbsolute = (relPath) => path.join(project.root, relPath);
105
+ async function listFiles() {
106
+ if (listFilesOverride)
107
+ return listFilesOverride;
108
+ const excludeRes = (project.build?.exclude ?? []).map(globToRegExp);
109
+ const isExcluded = (abs, sourceRoot) => isExcludedByGlobs(excludeRes, sourceRoot ? toPosix(path.relative(sourceRoot, abs)) : toRelative(abs), toRelative(abs));
110
+ const out = [];
111
+ for (const source of project.sources) {
112
+ if (!source.exists)
113
+ continue;
114
+ let isFile;
115
+ try {
116
+ isFile = (await fs.stat(source.absPath)).isFile();
117
+ }
118
+ catch {
119
+ continue;
120
+ }
121
+ if (isFile) {
122
+ if (!isExcluded(source.absPath))
123
+ out.push(source.absPath);
124
+ continue;
125
+ }
126
+ const walked = await walk(source.absPath, { limit: 20_000 });
127
+ for (const rel of walked.files) {
128
+ const abs = path.join(source.absPath, rel);
129
+ if (!isExcluded(abs, source.absPath))
130
+ out.push(abs);
131
+ }
132
+ }
133
+ return out;
134
+ }
135
+ function forTarget(target) {
136
+ return { project, surface, install, store, changedFiles, target, readText, exists, lookup };
137
+ }
138
+ return { project, surface, install, store, changedFiles, listFiles, forTarget, toRelative, toAbsolute };
139
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./types.js";
2
+ export { createValidatorRegistry } from "./registry.js";
3
+ export { buildContext, globToRegExp, isExcludedByGlobs } from "./context.js";
4
+ export { applySuppressions, findMatchingSuppression, loadSuppressions } from "./suppressions.js";
5
+ export { runValidators } from "./run.js";
@@ -0,0 +1,58 @@
1
+ import { idPrefixFor } from "../knowledge/facts.js";
2
+ class DefaultValidatorRegistry {
3
+ byId = new Map();
4
+ byGame = new Map();
5
+ register(game, validators) {
6
+ const prefix = idPrefixFor(game);
7
+ for (const v of validators) {
8
+ if (this.byId.has(v.id)) {
9
+ throw new Error(`ValidatorRegistry.register: duplicate validator id "${v.id}". Ids are never renamed or merged — ` +
10
+ `pick a new slug or fix the double registration.`);
11
+ }
12
+ if (v.game !== game) {
13
+ throw new Error(`ValidatorRegistry.register: validator "${v.id}" declares game "${v.game}" but was registered under "${game}".`);
14
+ }
15
+ if (!v.id.startsWith(prefix)) {
16
+ throw new Error(`ValidatorRegistry.register: validator id "${v.id}" does not start with "${prefix}", the id prefix ` +
17
+ `game "${game}" requires ("<game>.<group>.<slug>" with the ` +
18
+ `short game prefix the knowledge base and log signatures already use).`);
19
+ }
20
+ }
21
+ for (const v of validators)
22
+ this.byId.set(v.id, v);
23
+ const existing = this.byGame.get(game) ?? [];
24
+ this.byGame.set(game, [...existing, ...validators]);
25
+ }
26
+ forGame(game) {
27
+ return this.byGame.get(game) ?? [];
28
+ }
29
+ forGroup(group, game) {
30
+ return this.pool(game).filter((v) => v.groups.includes(group));
31
+ }
32
+ cheap(game) {
33
+ return this.pool(game).filter((v) => v.cost === "edit");
34
+ }
35
+ select(filter) {
36
+ let pool = this.pool(filter.game);
37
+ if (filter.groups && filter.groups.length > 0) {
38
+ const groups = new Set(filter.groups);
39
+ pool = pool.filter((v) => v.groups.some((g) => groups.has(g)));
40
+ }
41
+ if (filter.cheapOnly)
42
+ pool = pool.filter((v) => v.cost === "edit");
43
+ if (filter.ids && filter.ids.length > 0) {
44
+ const ids = new Set(filter.ids);
45
+ pool = pool.filter((v) => ids.has(v.id));
46
+ }
47
+ return pool;
48
+ }
49
+ get(id) {
50
+ return this.byId.get(id);
51
+ }
52
+ pool(game) {
53
+ return game ? this.forGame(game) : [...this.byId.values()];
54
+ }
55
+ }
56
+ export function createValidatorRegistry() {
57
+ return new DefaultValidatorRegistry();
58
+ }