@modwrench/workbench 0.0.1
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.
- package/data/conflicts/README.md +39 -0
- package/data/conflicts/fallout4.json +1 -0
- package/data/conflicts/lethalcompany.json +1 -0
- package/data/conflicts/skyrimspecialedition.json +1 -0
- package/dist/conflicts/community.d.ts +3 -0
- package/dist/conflicts/community.d.ts.map +1 -0
- package/dist/conflicts/community.js +96 -0
- package/dist/conflicts/community.js.map +1 -0
- package/dist/conflicts/index.d.ts +6 -0
- package/dist/conflicts/index.d.ts.map +1 -0
- package/dist/conflicts/index.js +114 -0
- package/dist/conflicts/index.js.map +1 -0
- package/dist/conflicts/loot.d.ts +19 -0
- package/dist/conflicts/loot.d.ts.map +1 -0
- package/dist/conflicts/loot.js +148 -0
- package/dist/conflicts/loot.js.map +1 -0
- package/dist/conflicts/types.d.ts +31 -0
- package/dist/conflicts/types.d.ts.map +1 -0
- package/dist/conflicts/types.js +6 -0
- package/dist/conflicts/types.js.map +1 -0
- package/dist/crashlog/bepinex.d.ts +3 -0
- package/dist/crashlog/bepinex.d.ts.map +1 -0
- package/dist/crashlog/bepinex.js +105 -0
- package/dist/crashlog/bepinex.js.map +1 -0
- package/dist/crashlog/crashlogger-sse.d.ts +3 -0
- package/dist/crashlog/crashlogger-sse.d.ts.map +1 -0
- package/dist/crashlog/crashlogger-sse.js +226 -0
- package/dist/crashlog/crashlogger-sse.js.map +1 -0
- package/dist/crashlog/detect.d.ts +3 -0
- package/dist/crashlog/detect.d.ts.map +1 -0
- package/dist/crashlog/detect.js +44 -0
- package/dist/crashlog/detect.js.map +1 -0
- package/dist/crashlog/index.d.ts +15 -0
- package/dist/crashlog/index.d.ts.map +1 -0
- package/dist/crashlog/index.js +65 -0
- package/dist/crashlog/index.js.map +1 -0
- package/dist/crashlog/minecraft.d.ts +3 -0
- package/dist/crashlog/minecraft.d.ts.map +1 -0
- package/dist/crashlog/minecraft.js +145 -0
- package/dist/crashlog/minecraft.js.map +1 -0
- package/dist/crashlog/netscriptframework.d.ts +3 -0
- package/dist/crashlog/netscriptframework.d.ts.map +1 -0
- package/dist/crashlog/netscriptframework.js +109 -0
- package/dist/crashlog/netscriptframework.js.map +1 -0
- package/dist/crashlog/types.d.ts +35 -0
- package/dist/crashlog/types.d.ts.map +1 -0
- package/dist/crashlog/types.js +9 -0
- package/dist/crashlog/types.js.map +1 -0
- package/dist/detect/environment.d.ts +35 -0
- package/dist/detect/environment.d.ts.map +1 -0
- package/dist/detect/environment.js +65 -0
- package/dist/detect/environment.js.map +1 -0
- package/dist/detect/games.d.ts +21 -0
- package/dist/detect/games.d.ts.map +1 -0
- package/dist/detect/games.js +159 -0
- package/dist/detect/games.js.map +1 -0
- package/dist/detect/loader.d.ts +12 -0
- package/dist/detect/loader.d.ts.map +1 -0
- package/dist/detect/loader.js +20 -0
- package/dist/detect/loader.js.map +1 -0
- package/dist/detect/manager.d.ts +26 -0
- package/dist/detect/manager.d.ts.map +1 -0
- package/dist/detect/manager.js +157 -0
- package/dist/detect/manager.js.map +1 -0
- package/dist/detect/os.d.ts +21 -0
- package/dist/detect/os.d.ts.map +1 -0
- package/dist/detect/os.js +58 -0
- package/dist/detect/os.js.map +1 -0
- package/dist/detect/steam.d.ts +32 -0
- package/dist/detect/steam.d.ts.map +1 -0
- package/dist/detect/steam.js +155 -0
- package/dist/detect/steam.js.map +1 -0
- package/dist/detect/vdf.d.ts +12 -0
- package/dist/detect/vdf.d.ts.map +1 -0
- package/dist/detect/vdf.js +112 -0
- package/dist/detect/vdf.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/loadorder/index.d.ts +20 -0
- package/dist/loadorder/index.d.ts.map +1 -0
- package/dist/loadorder/index.js +76 -0
- package/dist/loadorder/index.js.map +1 -0
- package/dist/loadorder/mo2.d.ts +21 -0
- package/dist/loadorder/mo2.d.ts.map +1 -0
- package/dist/loadorder/mo2.js +201 -0
- package/dist/loadorder/mo2.js.map +1 -0
- package/dist/loadorder/r2modman.d.ts +12 -0
- package/dist/loadorder/r2modman.d.ts.map +1 -0
- package/dist/loadorder/r2modman.js +115 -0
- package/dist/loadorder/r2modman.js.map +1 -0
- package/dist/loadorder/types.d.ts +30 -0
- package/dist/loadorder/types.d.ts.map +1 -0
- package/dist/loadorder/types.js +5 -0
- package/dist/loadorder/types.js.map +1 -0
- package/dist/loadorder/vortex.d.ts +8 -0
- package/dist/loadorder/vortex.d.ts.map +1 -0
- package/dist/loadorder/vortex.js +77 -0
- package/dist/loadorder/vortex.js.map +1 -0
- package/dist/metadata/clients.d.ts +11 -0
- package/dist/metadata/clients.d.ts.map +1 -0
- package/dist/metadata/clients.js +90 -0
- package/dist/metadata/clients.js.map +1 -0
- package/dist/metadata/index.d.ts +3 -0
- package/dist/metadata/index.d.ts.map +1 -0
- package/dist/metadata/index.js +149 -0
- package/dist/metadata/index.js.map +1 -0
- package/dist/metadata/normalize.d.ts +43 -0
- package/dist/metadata/normalize.d.ts.map +1 -0
- package/dist/metadata/normalize.js +88 -0
- package/dist/metadata/normalize.js.map +1 -0
- package/dist/metadata/types.d.ts +57 -0
- package/dist/metadata/types.d.ts.map +1 -0
- package/dist/metadata/types.js +9 -0
- package/dist/metadata/types.js.map +1 -0
- package/dist/register.d.ts +13 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +209 -0
- package/dist/register.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { findGameById } from "../detect/games.js";
|
|
2
|
+
import { detectInstalledManagers, inferManagerForGame, } from "../detect/manager.js";
|
|
3
|
+
import { readMo2LoadOrder } from "./mo2.js";
|
|
4
|
+
import { readR2modmanLoadOrder } from "./r2modman.js";
|
|
5
|
+
import { readVortexLoadOrder } from "./vortex.js";
|
|
6
|
+
export function readLoadOrder(input) {
|
|
7
|
+
const game = findGameById(input.gameId);
|
|
8
|
+
if (!game) {
|
|
9
|
+
return {
|
|
10
|
+
ok: false,
|
|
11
|
+
reason: `Unknown gameId "${input.gameId}". Known IDs are listed in ` +
|
|
12
|
+
"@modwrench/workbench's KNOWN_GAMES catalogue. Use mw_detect_environment " +
|
|
13
|
+
"to see detected games on this machine.",
|
|
14
|
+
attemptedManagers: [],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
// Build the list of managers to try, in priority order.
|
|
18
|
+
let order;
|
|
19
|
+
if (input.modManager && input.modManager !== "auto") {
|
|
20
|
+
order = [input.modManager];
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const managers = detectInstalledManagers();
|
|
24
|
+
const inferred = inferManagerForGame(game, managers);
|
|
25
|
+
// Fall back across the rest in family-sensible order.
|
|
26
|
+
const familyOrder = game.family === "bethesda"
|
|
27
|
+
? ["mo2", "vortex"]
|
|
28
|
+
: game.family === "unity-coop"
|
|
29
|
+
? ["r2modman", "thunderstore-mm"]
|
|
30
|
+
: [];
|
|
31
|
+
const seen = new Set();
|
|
32
|
+
order = [];
|
|
33
|
+
for (const m of [inferred, ...familyOrder]) {
|
|
34
|
+
if (m && !seen.has(m)) {
|
|
35
|
+
seen.add(m);
|
|
36
|
+
order.push(m);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const attempted = [];
|
|
41
|
+
for (const manager of order) {
|
|
42
|
+
attempted.push(manager);
|
|
43
|
+
let result = null;
|
|
44
|
+
if (manager === "mo2") {
|
|
45
|
+
result = readMo2LoadOrder(game, {
|
|
46
|
+
instancePath: input.instancePath,
|
|
47
|
+
profileName: input.profileName,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else if (manager === "r2modman") {
|
|
51
|
+
result = readR2modmanLoadOrder(game, {
|
|
52
|
+
profileName: input.profileName,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else if (manager === "vortex") {
|
|
56
|
+
result = readVortexLoadOrder(game);
|
|
57
|
+
}
|
|
58
|
+
if (result)
|
|
59
|
+
return { ok: true, ...result };
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
game,
|
|
64
|
+
attemptedManagers: attempted,
|
|
65
|
+
reason: attempted.length === 0
|
|
66
|
+
? "No mod manager could be inferred for this game's family. " +
|
|
67
|
+
"Specify modManager explicitly or install one of: " +
|
|
68
|
+
(game.family === "bethesda"
|
|
69
|
+
? "MO2, Vortex"
|
|
70
|
+
: game.family === "unity-coop"
|
|
71
|
+
? "r2modman, Thunderstore Mod Manager"
|
|
72
|
+
: "a supported manager")
|
|
73
|
+
: `Tried ${attempted.join(", ")} but no readable state was found for ${game.displayName}.`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/loadorder/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { GameDef } from "../detect/games.js";
|
|
2
|
+
import type { LoadOrderResult } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Find the MO2 instance directory for a given game. Walks the default
|
|
5
|
+
* instances root, reads each ModOrganizer.ini, and matches gameName against
|
|
6
|
+
* the game's known MO2 name aliases.
|
|
7
|
+
*
|
|
8
|
+
* Returns null if MO2 isn't installed or no matching instance is found.
|
|
9
|
+
*/
|
|
10
|
+
export declare function findMo2InstanceForGame(game: GameDef, explicitPath?: string): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Read the load order for a game's active MO2 instance + profile. For
|
|
13
|
+
* Bethesda games, the primary mods[] entries are .esp/.esl/.esm plugins from
|
|
14
|
+
* plugins.txt (in load order). The mod-folder view from modlist.txt is
|
|
15
|
+
* returned as modFolders[] so the LLM can map plugin → mod when needed.
|
|
16
|
+
*/
|
|
17
|
+
export declare function readMo2LoadOrder(game: GameDef, opts: {
|
|
18
|
+
instancePath?: string;
|
|
19
|
+
profileName?: string;
|
|
20
|
+
}): LoadOrderResult | null;
|
|
21
|
+
//# sourceMappingURL=mo2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mo2.d.ts","sourceRoot":"","sources":["../../src/loadorder/mo2.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAC;AAgEhE;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,OAAO,EACb,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,GAAG,IAAI,CA4Bf;AAwCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,OAAO,EACb,IAAI,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD,eAAe,GAAG,IAAI,CAmDxB"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { pathExists } from "../detect/os.js";
|
|
5
|
+
// ─── Minimal INI parser ───────────────────────────────────────────────────────
|
|
6
|
+
// MO2 stores instance metadata in ModOrganizer.ini. The file is small and
|
|
7
|
+
// well-formed Qt-style INI; we only need a few keys, so a tiny parser keeps us
|
|
8
|
+
// dep-free.
|
|
9
|
+
function parseIni(text) {
|
|
10
|
+
const out = {};
|
|
11
|
+
let section = "_default";
|
|
12
|
+
out[section] = {};
|
|
13
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
14
|
+
const line = rawLine.trim();
|
|
15
|
+
if (!line || line.startsWith(";") || line.startsWith("#"))
|
|
16
|
+
continue;
|
|
17
|
+
if (line.startsWith("[") && line.endsWith("]")) {
|
|
18
|
+
section = line.slice(1, -1);
|
|
19
|
+
out[section] ??= {};
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const eq = line.indexOf("=");
|
|
23
|
+
if (eq === -1)
|
|
24
|
+
continue;
|
|
25
|
+
const key = line.slice(0, eq).trim();
|
|
26
|
+
let value = line.slice(eq + 1).trim();
|
|
27
|
+
// Qt's @ByteArray(...) wrapper appears around some values. Unwrap it.
|
|
28
|
+
const qtMatch = value.match(/^@ByteArray\((.*)\)$/);
|
|
29
|
+
if (qtMatch)
|
|
30
|
+
value = qtMatch[1] ?? value;
|
|
31
|
+
(out[section] ??= {})[key] = value;
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
// ─── Instance discovery ───────────────────────────────────────────────────────
|
|
36
|
+
function defaultMo2InstancesRoot() {
|
|
37
|
+
if (process.platform !== "win32")
|
|
38
|
+
return null;
|
|
39
|
+
const local = process.env.LOCALAPPDATA;
|
|
40
|
+
if (!local)
|
|
41
|
+
return null;
|
|
42
|
+
return join(local, "ModOrganizer");
|
|
43
|
+
}
|
|
44
|
+
function readInstanceGameName(instancePath) {
|
|
45
|
+
const iniPath = join(instancePath, "ModOrganizer.ini");
|
|
46
|
+
if (!pathExists(iniPath))
|
|
47
|
+
return null;
|
|
48
|
+
try {
|
|
49
|
+
const ini = parseIni(readFileSync(iniPath, "utf8"));
|
|
50
|
+
const general = ini["General"] ?? {};
|
|
51
|
+
return general["gameName"] ?? null;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function readInstanceActiveProfile(instancePath) {
|
|
58
|
+
const iniPath = join(instancePath, "ModOrganizer.ini");
|
|
59
|
+
if (!pathExists(iniPath))
|
|
60
|
+
return null;
|
|
61
|
+
try {
|
|
62
|
+
const ini = parseIni(readFileSync(iniPath, "utf8"));
|
|
63
|
+
const general = ini["General"] ?? {};
|
|
64
|
+
return general["selected_profile"] ?? general["profile"] ?? null;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Find the MO2 instance directory for a given game. Walks the default
|
|
72
|
+
* instances root, reads each ModOrganizer.ini, and matches gameName against
|
|
73
|
+
* the game's known MO2 name aliases.
|
|
74
|
+
*
|
|
75
|
+
* Returns null if MO2 isn't installed or no matching instance is found.
|
|
76
|
+
*/
|
|
77
|
+
export function findMo2InstanceForGame(game, explicitPath) {
|
|
78
|
+
if (explicitPath) {
|
|
79
|
+
return pathExists(join(explicitPath, "ModOrganizer.ini"))
|
|
80
|
+
? explicitPath
|
|
81
|
+
: null;
|
|
82
|
+
}
|
|
83
|
+
const root = defaultMo2InstancesRoot();
|
|
84
|
+
if (!root || !pathExists(root))
|
|
85
|
+
return null;
|
|
86
|
+
const aliases = (game.mo2GameNames ?? []).map((n) => n.toLowerCase());
|
|
87
|
+
if (aliases.length === 0)
|
|
88
|
+
return null;
|
|
89
|
+
let candidates;
|
|
90
|
+
try {
|
|
91
|
+
candidates = readdirSync(root).map((name) => join(root, name));
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
for (const candidate of candidates) {
|
|
97
|
+
try {
|
|
98
|
+
if (!statSync(candidate).isDirectory())
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const gameName = readInstanceGameName(candidate);
|
|
105
|
+
if (!gameName)
|
|
106
|
+
continue;
|
|
107
|
+
if (aliases.includes(gameName.toLowerCase()))
|
|
108
|
+
return candidate;
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
function parseModlist(text) {
|
|
113
|
+
// modlist.txt is LIFO: top line is highest-priority. We reverse so index 0
|
|
114
|
+
// is the lowest-priority mod and indices grow with priority — easier to
|
|
115
|
+
// reason about as "load order index."
|
|
116
|
+
const lines = text.split(/\r?\n/);
|
|
117
|
+
const entries = [];
|
|
118
|
+
for (const raw of lines) {
|
|
119
|
+
const line = raw.trim();
|
|
120
|
+
if (!line || line.startsWith("#"))
|
|
121
|
+
continue;
|
|
122
|
+
const prefix = line[0];
|
|
123
|
+
const name = line.slice(1);
|
|
124
|
+
// Separators (---xxx_separator) and backup markers can be skipped — they
|
|
125
|
+
// aren't real mods. MO2 marks them with name ending "_separator".
|
|
126
|
+
if (name.endsWith("_separator"))
|
|
127
|
+
continue;
|
|
128
|
+
if (prefix === "+")
|
|
129
|
+
entries.push({ name, enabled: true });
|
|
130
|
+
else if (prefix === "-")
|
|
131
|
+
entries.push({ name, enabled: false });
|
|
132
|
+
// Other prefixes (*) are markers we don't care about.
|
|
133
|
+
}
|
|
134
|
+
return entries.reverse();
|
|
135
|
+
}
|
|
136
|
+
function parsePlugins(text) {
|
|
137
|
+
const out = [];
|
|
138
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
139
|
+
const line = raw.trim();
|
|
140
|
+
if (!line || line.startsWith("#"))
|
|
141
|
+
continue;
|
|
142
|
+
if (line.startsWith("*"))
|
|
143
|
+
out.push({ name: line.slice(1), enabled: true });
|
|
144
|
+
else
|
|
145
|
+
out.push({ name: line, enabled: false });
|
|
146
|
+
}
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Read the load order for a game's active MO2 instance + profile. For
|
|
151
|
+
* Bethesda games, the primary mods[] entries are .esp/.esl/.esm plugins from
|
|
152
|
+
* plugins.txt (in load order). The mod-folder view from modlist.txt is
|
|
153
|
+
* returned as modFolders[] so the LLM can map plugin → mod when needed.
|
|
154
|
+
*/
|
|
155
|
+
export function readMo2LoadOrder(game, opts) {
|
|
156
|
+
const instancePath = findMo2InstanceForGame(game, opts.instancePath);
|
|
157
|
+
if (!instancePath)
|
|
158
|
+
return null;
|
|
159
|
+
const profile = opts.profileName ?? readInstanceActiveProfile(instancePath) ?? "Default";
|
|
160
|
+
const profileDir = join(instancePath, "profiles", profile);
|
|
161
|
+
if (!pathExists(profileDir))
|
|
162
|
+
return null;
|
|
163
|
+
const modlistPath = join(profileDir, "modlist.txt");
|
|
164
|
+
const pluginsPath = join(profileDir, "plugins.txt");
|
|
165
|
+
let modFolders = [];
|
|
166
|
+
if (pathExists(modlistPath)) {
|
|
167
|
+
const entries = parseModlist(readFileSync(modlistPath, "utf8"));
|
|
168
|
+
modFolders = entries.map((e, i) => ({
|
|
169
|
+
name: e.name,
|
|
170
|
+
enabled: e.enabled,
|
|
171
|
+
modlistIndex: i,
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
const mods = [];
|
|
175
|
+
if (pathExists(pluginsPath)) {
|
|
176
|
+
const plugins = parsePlugins(readFileSync(pluginsPath, "utf8"));
|
|
177
|
+
for (let i = 0; i < plugins.length; i++) {
|
|
178
|
+
const p = plugins[i];
|
|
179
|
+
mods.push({
|
|
180
|
+
name: p.name,
|
|
181
|
+
enabled: p.enabled,
|
|
182
|
+
loadOrderIndex: i,
|
|
183
|
+
pluginFile: p.name,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const totalCount = mods.length || modFolders.length;
|
|
188
|
+
const enabledCount = mods.length > 0
|
|
189
|
+
? mods.filter((m) => m.enabled).length
|
|
190
|
+
: modFolders.filter((f) => f.enabled).length;
|
|
191
|
+
return {
|
|
192
|
+
modManager: "mo2",
|
|
193
|
+
profile,
|
|
194
|
+
sourcePath: profileDir,
|
|
195
|
+
mods,
|
|
196
|
+
modFolders,
|
|
197
|
+
enabledCount,
|
|
198
|
+
totalCount,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=mo2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mo2.js","sourceRoot":"","sources":["../../src/loadorder/mo2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GameDef } from "../detect/games.js";
|
|
2
|
+
import type { LoadOrderResult } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Read the load order for a game's r2modman profile. r2modman profiles live
|
|
5
|
+
* at <root>/<gameFolder>/profiles/<profile>/mods.yml. Active profile isn't
|
|
6
|
+
* recorded in disk state (it's a UI session value), so we default to the
|
|
7
|
+
* first profile alphabetically (typically "Default") unless one is named.
|
|
8
|
+
*/
|
|
9
|
+
export declare function readR2modmanLoadOrder(game: GameDef, opts: {
|
|
10
|
+
profileName?: string;
|
|
11
|
+
}): LoadOrderResult | null;
|
|
12
|
+
//# sourceMappingURL=r2modman.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"r2modman.d.ts","sourceRoot":"","sources":["../../src/loadorder/r2modman.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAC;AA+DhE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,OAAO,EACb,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,eAAe,GAAG,IAAI,CA+DxB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { load as yamlLoad } from "js-yaml";
|
|
5
|
+
import { pathExists } from "../detect/os.js";
|
|
6
|
+
function r2modmanRootCandidates() {
|
|
7
|
+
const home = homedir();
|
|
8
|
+
switch (process.platform) {
|
|
9
|
+
case "win32":
|
|
10
|
+
return [
|
|
11
|
+
process.env.APPDATA
|
|
12
|
+
? join(process.env.APPDATA, "r2modmanPlus-local")
|
|
13
|
+
: "",
|
|
14
|
+
].filter(Boolean);
|
|
15
|
+
case "darwin":
|
|
16
|
+
return [
|
|
17
|
+
join(home, "Library", "Application Support", "r2modmanPlus-local"),
|
|
18
|
+
];
|
|
19
|
+
default:
|
|
20
|
+
return [
|
|
21
|
+
join(home, ".config", "r2modmanPlus-local"),
|
|
22
|
+
join(home, ".var", "app", "com.kalindudc.r2modmanPlus", "config", "r2modmanPlus-local"),
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function findR2modmanRoot() {
|
|
27
|
+
for (const candidate of r2modmanRootCandidates()) {
|
|
28
|
+
if (pathExists(candidate))
|
|
29
|
+
return candidate;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function formatVersion(v) {
|
|
34
|
+
if (typeof v === "string")
|
|
35
|
+
return v;
|
|
36
|
+
if (v && typeof v === "object") {
|
|
37
|
+
const parts = [v.Major ?? 0, v.Minor ?? 0, v.Patch ?? 0];
|
|
38
|
+
return parts.join(".");
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Read the load order for a game's r2modman profile. r2modman profiles live
|
|
44
|
+
* at <root>/<gameFolder>/profiles/<profile>/mods.yml. Active profile isn't
|
|
45
|
+
* recorded in disk state (it's a UI session value), so we default to the
|
|
46
|
+
* first profile alphabetically (typically "Default") unless one is named.
|
|
47
|
+
*/
|
|
48
|
+
export function readR2modmanLoadOrder(game, opts) {
|
|
49
|
+
const folder = game.r2modmanFolder;
|
|
50
|
+
if (!folder)
|
|
51
|
+
return null;
|
|
52
|
+
const root = findR2modmanRoot();
|
|
53
|
+
if (!root)
|
|
54
|
+
return null;
|
|
55
|
+
const gameDir = join(root, folder);
|
|
56
|
+
const profilesDir = join(gameDir, "profiles");
|
|
57
|
+
if (!pathExists(profilesDir))
|
|
58
|
+
return null;
|
|
59
|
+
let profile = opts.profileName;
|
|
60
|
+
if (!profile) {
|
|
61
|
+
try {
|
|
62
|
+
const profiles = readdirSync(profilesDir).sort();
|
|
63
|
+
profile = profiles[0];
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!profile)
|
|
70
|
+
return null;
|
|
71
|
+
const profileDir = join(profilesDir, profile);
|
|
72
|
+
const manifestPath = join(profileDir, "mods.yml");
|
|
73
|
+
if (!pathExists(manifestPath))
|
|
74
|
+
return null;
|
|
75
|
+
let entries = [];
|
|
76
|
+
try {
|
|
77
|
+
const parsed = yamlLoad(readFileSync(manifestPath, "utf8"));
|
|
78
|
+
if (Array.isArray(parsed))
|
|
79
|
+
entries = parsed;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const mods = entries.map((e, i) => {
|
|
85
|
+
const author = e.AuthorName;
|
|
86
|
+
const displayName = e.DisplayName ?? e.Name ?? "(unnamed)";
|
|
87
|
+
// Thunderstore's canonical mod id is "Author-ModName". Reconstruct it
|
|
88
|
+
// from the manifest fields when possible — this is what downstream tools
|
|
89
|
+
// need to resolve attribution.
|
|
90
|
+
const sourceModId = author && e.Name ? `${author}-${e.Name}` : e.Name ?? undefined;
|
|
91
|
+
const mod = {
|
|
92
|
+
name: displayName,
|
|
93
|
+
enabled: e.Enabled ?? true,
|
|
94
|
+
loadOrderIndex: i,
|
|
95
|
+
sourcePlatform: "thunderstore",
|
|
96
|
+
};
|
|
97
|
+
const version = formatVersion(e.Version);
|
|
98
|
+
if (version)
|
|
99
|
+
mod.version = version;
|
|
100
|
+
if (author)
|
|
101
|
+
mod.author = author;
|
|
102
|
+
if (sourceModId)
|
|
103
|
+
mod.sourceModId = sourceModId;
|
|
104
|
+
return mod;
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
modManager: "r2modman",
|
|
108
|
+
profile,
|
|
109
|
+
sourcePath: profileDir,
|
|
110
|
+
mods,
|
|
111
|
+
enabledCount: mods.filter((m) => m.enabled).length,
|
|
112
|
+
totalCount: mods.length,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=r2modman.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"r2modman.js","sourceRoot":"","sources":["../../src/loadorder/r2modman.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type SourcePlatform = "nexus" | "modio" | "thunderstore" | "curseforge" | "unknown";
|
|
2
|
+
export type LoadOrderMod = {
|
|
3
|
+
name: string;
|
|
4
|
+
enabled: boolean | null;
|
|
5
|
+
loadOrderIndex?: number;
|
|
6
|
+
pluginFile?: string;
|
|
7
|
+
version?: string;
|
|
8
|
+
sourcePlatform?: SourcePlatform;
|
|
9
|
+
sourceModId?: string;
|
|
10
|
+
author?: string;
|
|
11
|
+
installedAt?: string;
|
|
12
|
+
};
|
|
13
|
+
export type LoadOrderResult = {
|
|
14
|
+
modManager: "vortex" | "mo2" | "r2modman";
|
|
15
|
+
profile: string;
|
|
16
|
+
/** Absolute path of the manager-specific state directory we read from. */
|
|
17
|
+
sourcePath: string;
|
|
18
|
+
mods: LoadOrderMod[];
|
|
19
|
+
/** Bethesda mod-folder list (MO2 only). Null for Unity / Vortex. */
|
|
20
|
+
modFolders?: Array<{
|
|
21
|
+
name: string;
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
modlistIndex: number;
|
|
24
|
+
}>;
|
|
25
|
+
enabledCount: number;
|
|
26
|
+
totalCount: number;
|
|
27
|
+
/** Honest about limitations — Vortex's LevelDB state can't be parsed yet. */
|
|
28
|
+
warning?: string;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/loadorder/types.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,cAAc,GACtB,OAAO,GACP,OAAO,GACP,cAAc,GACd,YAAY,GACZ,SAAS,CAAC;AAEd,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,QAAQ,GAAG,KAAK,GAAG,UAAU,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,oEAAoE;IACpE,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/loadorder/types.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,2EAA2E;AAC3E,6DAA6D"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GameDef } from "../detect/games.js";
|
|
2
|
+
import type { LoadOrderResult } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Best-effort enumeration of installed mod folders for a game under Vortex.
|
|
5
|
+
* Returns null if Vortex isn't installed or the game has no Vortex data dir.
|
|
6
|
+
*/
|
|
7
|
+
export declare function readVortexLoadOrder(game: GameDef): LoadOrderResult | null;
|
|
8
|
+
//# sourceMappingURL=vortex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vortex.d.ts","sourceRoot":"","sources":["../../src/loadorder/vortex.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAC;AAqBhE;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAkDzE"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { pathExists } from "../detect/os.js";
|
|
5
|
+
// Vortex stores its canonical state in a LevelDB store at
|
|
6
|
+
// %APPDATA%/Vortex/state.v2/ — not directly parseable without a LevelDB
|
|
7
|
+
// library (which would add ~5MB native deps). Until we add that path, this
|
|
8
|
+
// reader does a best-effort directory scan of the per-game mods folder:
|
|
9
|
+
//
|
|
10
|
+
// %APPDATA%/Vortex/<gameId>/mods/<mod-folder>/
|
|
11
|
+
//
|
|
12
|
+
// We return mod folder names with enabled=null and a warning so the LLM
|
|
13
|
+
// knows enable-state and load order are unavailable through this view.
|
|
14
|
+
function vortexRoot() {
|
|
15
|
+
if (process.platform === "win32") {
|
|
16
|
+
return process.env.APPDATA ? join(process.env.APPDATA, "Vortex") : null;
|
|
17
|
+
}
|
|
18
|
+
// Vortex on Linux is Wine-only and uncommon; check the standard config
|
|
19
|
+
// location as a courtesy.
|
|
20
|
+
return join(homedir(), ".config", "Vortex");
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Best-effort enumeration of installed mod folders for a game under Vortex.
|
|
24
|
+
* Returns null if Vortex isn't installed or the game has no Vortex data dir.
|
|
25
|
+
*/
|
|
26
|
+
export function readVortexLoadOrder(game) {
|
|
27
|
+
const root = vortexRoot();
|
|
28
|
+
if (!root || !pathExists(root))
|
|
29
|
+
return null;
|
|
30
|
+
const gameDir = join(root, game.gameId);
|
|
31
|
+
const modsDir = join(gameDir, "mods");
|
|
32
|
+
if (!pathExists(modsDir))
|
|
33
|
+
return null;
|
|
34
|
+
let entries;
|
|
35
|
+
try {
|
|
36
|
+
entries = readdirSync(modsDir);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const mods = [];
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
const fullPath = join(modsDir, entry);
|
|
44
|
+
try {
|
|
45
|
+
if (!statSync(fullPath).isDirectory())
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
// Vortex names mod folders like "ModName-12345-1-0-1700000000". The
|
|
52
|
+
// numeric run at the end is typically <nexus_mod_id>-<version>-<unixts>.
|
|
53
|
+
// We try a soft parse, but it's best-effort only.
|
|
54
|
+
const nexusIdMatch = entry.match(/-(\d{2,7})-/);
|
|
55
|
+
const mod = {
|
|
56
|
+
name: entry,
|
|
57
|
+
enabled: null,
|
|
58
|
+
};
|
|
59
|
+
if (nexusIdMatch) {
|
|
60
|
+
mod.sourcePlatform = "nexus";
|
|
61
|
+
mod.sourceModId = nexusIdMatch[1];
|
|
62
|
+
}
|
|
63
|
+
mods.push(mod);
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
modManager: "vortex",
|
|
67
|
+
profile: "(unknown)",
|
|
68
|
+
sourcePath: modsDir,
|
|
69
|
+
mods,
|
|
70
|
+
enabledCount: 0,
|
|
71
|
+
totalCount: mods.length,
|
|
72
|
+
warning: "Vortex stores enable-state and load order in a LevelDB store (state.v2). " +
|
|
73
|
+
"ModWrench currently lists installed mod folders only — enable/disable " +
|
|
74
|
+
"state is not visible. For full state visibility on Bethesda games, use MO2.",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=vortex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vortex.js","sourceRoot":"","sources":["../../src/loadorder/vortex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C,0DAA0D;AAC1D,wEAAwE;AACxE,2EAA2E;AAC3E,wEAAwE;AACxE,EAAE;AACF,iDAAiD;AACjD,EAAE;AACF,wEAAwE;AACxE,uEAAuE;AAEvE,SAAS,UAAU;IACjB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,CAAC;IACD,uEAAuE;IACvE,0BAA0B;IAC1B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAa;IAC/C,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAE5C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAmB,EAAE,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE;gBAAE,SAAS;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,oEAAoE;QACpE,yEAAyE;QACzE,kDAAkD;QAClD,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAChD,MAAM,GAAG,GAAiB;YACxB,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,IAAI;SACd,CAAC;QACF,IAAI,YAAY,EAAE,CAAC;YACjB,GAAG,CAAC,cAAc,GAAG,OAAO,CAAC;YAC7B,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC;IAED,OAAO;QACL,UAAU,EAAE,QAAQ;QACpB,OAAO,EAAE,WAAW;QACpB,UAAU,EAAE,OAAO;QACnB,IAAI;QACJ,YAAY,EAAE,CAAC;QACf,UAAU,EAAE,IAAI,CAAC,MAAM;QACvB,OAAO,EACL,2EAA2E;YAC3E,wEAAwE;YACxE,6EAA6E;KAChF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type NexusClient = {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
request<T>(path: string): Promise<T>;
|
|
4
|
+
};
|
|
5
|
+
export declare function tryCreateNexusClient(): NexusClient | null;
|
|
6
|
+
export type ModioClient = {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
request<T>(path: string, query?: Record<string, string | number | undefined>): Promise<T>;
|
|
9
|
+
};
|
|
10
|
+
export declare function tryCreateModioClient(): ModioClient | null;
|
|
11
|
+
//# sourceMappingURL=clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../src/metadata/clients.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACtC,CAAC;AAEF,wBAAgB,oBAAoB,IAAI,WAAW,GAAG,IAAI,CA8BzD;AAID,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,CAAC,EACP,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAClD,OAAO,CAAC,CAAC,CAAC,CAAC;CACf,CAAC;AAEF,wBAAgB,oBAAoB,IAAI,WAAW,GAAG,IAAI,CA8CzD"}
|