(
instanceUuid: string,
modId: string,
type: "mod" | "plugin",
fileName?: string
)
| 416 | } |
| 417 | |
| 418 | public async getModConfig( |
| 419 | instanceUuid: string, |
| 420 | modId: string, |
| 421 | type: "mod" | "plugin", |
| 422 | fileName?: string |
| 423 | ): Promise<ModConfigFile[]> { |
| 424 | const instance = InstanceSubsystem.getInstance(instanceUuid)!; |
| 425 | const cwd = instance.absoluteCwdPath(); |
| 426 | const fileManager = new FileManager( |
| 427 | resolveMCDRServerRoot(instance.config.type, cwd) ?? cwd, |
| 428 | instance.config?.fileCode |
| 429 | ); |
| 430 | if (fileName && !fileManager.checkPath(fileName)) throw new Error("Invalid file name"); |
| 431 | if (modId && !fileManager.checkPath(modId)) throw new Error("Invalid mod ID"); |
| 432 | const rootDir = fileManager.toAbsolutePath("."); |
| 433 | const configFiles: ModConfigFile[] = []; |
| 434 | |
| 435 | const searchTerms = new Set<string>(); |
| 436 | if (modId) searchTerms.add(modId.toLowerCase()); |
| 437 | if (fileName) { |
| 438 | let nameOnly = fileName.replace(/\.jar(\.disabled)?$/i, ""); |
| 439 | // Try to remove version info (e.g., -1.18.2 or _1.18.2) |
| 440 | nameOnly = nameOnly.replace(/[-_]v?\d+\.\d+.*$/i, ""); |
| 441 | searchTerms.add(nameOnly.toLowerCase()); |
| 442 | const parts = nameOnly.split(/[-_]/); |
| 443 | if (parts[0]) searchTerms.add(parts[0].toLowerCase()); |
| 444 | } |
| 445 | |
| 446 | if (type === "mod") { |
| 447 | // Mods usually have configs in /config directory |
| 448 | const configDir = path.join(rootDir, "config"); |
| 449 | if (await fs.pathExists(configDir)) { |
| 450 | const files = await fs.readdir(configDir); |
| 451 | for (const file of files) { |
| 452 | const lowerFile = file.toLowerCase(); |
| 453 | const fullPath = path.join(configDir, file); |
| 454 | const stat = await fs.stat(fullPath); |
| 455 | |
| 456 | let matched = false; |
| 457 | for (const term of searchTerms) { |
| 458 | if (lowerFile.includes(term)) { |
| 459 | matched = true; |
| 460 | break; |
| 461 | } |
| 462 | } |
| 463 | |
| 464 | if (matched) { |
| 465 | if (stat.isFile()) { |
| 466 | configFiles.push({ |
| 467 | name: file, |
| 468 | path: path.join("config", file) |
| 469 | }); |
| 470 | } else if (stat.isDirectory()) { |
| 471 | const subFiles = await fs.readdir(fullPath); |
| 472 | for (const subFile of subFiles) { |
| 473 | const subFullPath = path.join(fullPath, subFile); |
| 474 | if ((await fs.stat(subFullPath)).isFile()) { |
| 475 | configFiles.push({ |
no test coverage detected