Manage dependencies of mods

This commit is contained in:
Kallum Jones 2022-08-09 13:50:03 +01:00
parent db16eb7dd1
commit fdc880e7fc
No known key found for this signature in database
GPG Key ID: D7F4589C4D7F81A9
5 changed files with 79 additions and 8 deletions

View File

@ -11,7 +11,7 @@ import {ListCommand} from "./commands/list_command.js";
import UninstallCommand from "./commands/uninstall_command.js"; import UninstallCommand from "./commands/uninstall_command.js";
import EssentialCommand from "./commands/essential_command.js"; import EssentialCommand from "./commands/essential_command.js";
import {readFileSync, unlinkSync} from "fs"; import {readFileSync, unlinkSync} from "fs";
import UpdateCommand from "./commands/upgrade_command.js"; import UpdateCommand from "./commands/update_command.js";
import MigratePossibleCommand from "./commands/migrate_possible.js"; import MigratePossibleCommand from "./commands/migrate_possible.js";
import MigrateCommand from "./commands/migrate_command.js"; import MigrateCommand from "./commands/migrate_command.js";
import ModrinthSource from "./mods/sources/modrinth_source.js"; import ModrinthSource from "./mods/sources/modrinth_source.js";

1
src/mods/mod.d.ts vendored
View File

@ -7,6 +7,7 @@ declare global {
version: string version: string
source: string, source: string,
essential: boolean, essential: boolean,
dependencies: Array<string>
} }
type Version = { type Version = {

View File

@ -91,7 +91,7 @@ export default class Mods {
writeFileSync(ModManager.FilePaths.MOD_FILE_PATH, JSON.stringify(mods, null, 4)); writeFileSync(ModManager.FilePaths.MOD_FILE_PATH, JSON.stringify(mods, null, 4));
} }
private static isModInstalled(id: string): boolean { public static isModInstalled(id: string): boolean {
const modsWithId: Array<TrackedMod> = this.getTrackedMods().filter(mod => mod.id == id); const modsWithId: Array<TrackedMod> = this.getTrackedMods().filter(mod => mod.id == id);
return !Util.isArrayEmpty(modsWithId) return !Util.isArrayEmpty(modsWithId)
} }
@ -105,6 +105,16 @@ export default class Mods {
// IF a matching mod is found, remove it // IF a matching mod is found, remove it
if (modToUninstall != undefined) { if (modToUninstall != undefined) {
this.silentUninstall(modToUninstall); this.silentUninstall(modToUninstall);
for (let dependency of modToUninstall.dependencies) {
if (!this.isDependedOn(dependency)) {
const dependencyMod = this.findMod(dependency);
if (dependencyMod != undefined) {
this.silentUninstall(dependencyMod)
}
}
}
spinner.succeed(`${modToUninstall.name} successfully uninstalled!`) spinner.succeed(`${modToUninstall.name} successfully uninstalled!`)
} else { } else {
spinner.error(`${mod} was not found.`) spinner.error(`${mod} was not found.`)
@ -128,6 +138,10 @@ export default class Mods {
const modToMark = this.findMod(mod); const modToMark = this.findMod(mod);
if (modToMark != undefined) { if (modToMark != undefined) {
for (let dependency of modToMark.dependencies) {
this.toggleEssential(dependency)
}
let mods = this.getTrackedMods(); let mods = this.getTrackedMods();
// Remove mod from list // Remove mod from list
mods = mods.filter(item => !Mods.areModsEqual(item, modToMark)); mods = mods.filter(item => !Mods.areModsEqual(item, modToMark));
@ -147,9 +161,15 @@ export default class Mods {
} }
} }
/**
* Finds the mod based on the provided id or name
* @param mod the id or mod name
* @return the found Mod, or undefined if no mod was found
*/
private static findMod(mod: string): TrackedMod | undefined { private static findMod(mod: string): TrackedMod | undefined {
// Replace underscores with spaces // Replace underscores and dashes with spaces
mod = mod.replaceAll("_", " "); mod = mod.replaceAll("_", " ");
mod = mod.replaceAll("-", " ")
let mods: Array<TrackedMod> = this.getTrackedMods(); let mods: Array<TrackedMod> = this.getTrackedMods();
for (let modEle of mods) { for (let modEle of mods) {
@ -272,8 +292,8 @@ export default class Mods {
/** /**
* Migrates to the provided version of minecraft * Migrates to the provided version of minecraft
* @param version * @param version the Minecraft version to migrate to
* @param force * @param force true if this is a force migration, false otherwise
*/ */
static async migrate(version: string, force: boolean) { static async migrate(version: string, force: boolean) {
const mods = this.getTrackedMods(); const mods = this.getTrackedMods();
@ -322,4 +342,15 @@ export default class Mods {
await MinecraftUtils.updateCurrentMinecraftVersion(version) await MinecraftUtils.updateCurrentMinecraftVersion(version)
PrintUtils.success(`Successfully migrated to ${version}`) PrintUtils.success(`Successfully migrated to ${version}`)
} }
private static isDependedOn(dependency: string) {
const trackedMods = this.getTrackedMods();
for (let trackedMod of trackedMods) {
if (trackedMod.dependencies.includes(dependency)) {
return true;
}
}
return false;
}
} }

View File

@ -96,9 +96,15 @@ export default class ModrinthSource implements ModSource {
*/ */
async install(version: Version, essential: boolean): Promise<void> { async install(version: Version, essential: boolean): Promise<void> {
try { try {
if (Mods.isModInstalled(version.modId)) {
return;
}
const dependencies = [];
if (!Util.isArrayEmpty(version.dependencies)) { if (!Util.isArrayEmpty(version.dependencies)) {
for (let dependency of version.dependencies) { for (let dependency of version.dependencies) {
await this.install(dependency, essential); await this.install(dependency, essential);
dependencies.push(dependency.modId)
} }
} }
FileDownloader.downloadMod(version) FileDownloader.downloadMod(version)
@ -110,6 +116,7 @@ export default class ModrinthSource implements ModSource {
version: version.versionNumber, version: version.versionNumber,
source: this.getSourceName(), source: this.getSourceName(),
essential: essential, essential: essential,
dependencies: dependencies
} }
Mods.trackMod(mod); Mods.trackMod(mod);
@ -246,7 +253,37 @@ export default class ModrinthSource implements ModSource {
} }
const latestVersion = results[0]; const latestVersion = results[0];
return this.getVersionFromId(latestVersion.id); const dependencies = [];
if (!Util.isArrayEmpty(latestVersion.dependencies)) {
for (let dependency of latestVersion.dependencies) {
if (dependency.dependency_type === "required") {
const projectId = dependency.project_id;
const versionId = dependency.version_id;
dependencies.push(await this.getDependency(projectId, versionId, mcVersion))
}
}
}
const latestFile = latestVersion.files[0];
return {
modId: latestVersion.project_id,
versionNumber: latestVersion.version_number,
fileName: latestFile.filename,
url: latestFile.url,
dependencies: dependencies
};
}
async getDependency(projectId: string | undefined, versionId: string | undefined, mcVersion: string): Promise<Version> {
if (projectId != undefined) {
return this.getLatestVersion(projectId, mcVersion)
} else if (versionId != undefined) {
return this.getVersionFromVersionId(versionId, projectId, mcVersion)
} else {
throw new Error("Dependency found with no project or version id")
}
} }
/** /**
@ -285,9 +322,11 @@ export default class ModrinthSource implements ModSource {
* ] * ]
* } * }
* @param versionId the version id to transform into an object * @param versionId the version id to transform into an object
* @param projectId the project id of this version
* @param mcVersion the Minecraft version we are downloading for
* @return the Version object * @return the Version object
*/ */
async getVersionFromId(versionId: string): Promise<Version> { async getVersionFromVersionId(versionId: string, projectId: string | undefined, mcVersion: string): Promise<Version> {
const response = await axios.get(format(ModrinthSource.SINGLE_VERSION_URL, versionId)); const response = await axios.get(format(ModrinthSource.SINGLE_VERSION_URL, versionId));
const latestVersion = await response.data; const latestVersion = await response.data;
@ -296,7 +335,7 @@ export default class ModrinthSource implements ModSource {
const dependencies = []; const dependencies = [];
if (!Util.isArrayEmpty(latestVersion.dependencies)) { if (!Util.isArrayEmpty(latestVersion.dependencies)) {
for (let dependency of latestVersion.dependencies) { for (let dependency of latestVersion.dependencies) {
dependencies.push(await this.getVersionFromId(dependency.version_id)) dependencies.push(await this.getDependency(projectId, dependency.version_id, mcVersion))
} }
} }