From ef1941f7c8d5d9b90c2bcba96bb86357d93422aa Mon Sep 17 00:00:00 2001 From: IDCs Date: Thu, 16 May 2024 09:18:08 +0100 Subject: [PATCH] improved installer options comparison functionality part of nexus-mods/vortex#15703 --- .../mod_management/InstallManager.ts | 25 ++++++++++++++++++- .../mod_management/util/dependencies.ts | 2 +- .../mod_management/util/testModReference.ts | 9 ++++--- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/extensions/mod_management/InstallManager.ts b/src/extensions/mod_management/InstallManager.ts index a59ee2e3e..9f8ffec17 100644 --- a/src/extensions/mod_management/InstallManager.ts +++ b/src/extensions/mod_management/InstallManager.ts @@ -1672,8 +1672,11 @@ class InstallManager { }); }; + const mod = mods[0]; const modReference: IModReference = { + id: mod.id, fileList: installOptions?.fileList, + archiveId: mod.archiveId, gameId, installerChoices: installOptions?.choices, patches: installOptions?.patches, @@ -2118,6 +2121,22 @@ class InstallManager { attributes['fileList'] = extra.fileList; } + // if (extra.installerChoices !== undefined) { + // This actually masks a long standing bug and can barely be considered a fix. + // Consider the following case: + // 1. User1 creates a fomod with a specific structure and uploads it to the site. + // 2. Curator uploads a collection and adds the fomod. + // 3. User2 downloads the collection - everything works fine. + // 4. User1 changes the fomod structure significantly (i.e. some installer steps become optional or removed entirely) and uploads his update to the site. + // 5. Curator downloads the update and uploads a new revision of his collection. Due to memoization functionality in the collections extension, the same fomod options as in the + // first version of the mod are uploaded as part of the collection instead of the newer generated options. + // 6. User2 updates to the new revision of the collection, the install manager attempts to install the mod but will only generate instructions based on + // the new fomod's structure, ommitting installer options that are not present in the new fomod. + // 7. User2 now has a correct installation of the mod which should work fine depending on the new fomod structure, but our installer option comparisons will fail + // making it impossible for the collection to be considered fully installed/complete. + // attributes['installerChoices'] = extra.installerChoices; + //} + api.store.dispatch(setModAttributes(gameId, modId, attributes)); } @@ -2200,7 +2219,11 @@ class InstallManager { api.store.dispatch(setModEnabled(prof.id, modId, true)); }); - this.applyExtraFromRule(api, gameId, modId, dep.extra); + this.applyExtraFromRule(api, gameId, modId, { + ...dep.extra, + fileList: dep.fileList ?? dep.extra.fileList, + installerChoices: dep.installerChoices, + patches: dep.patches ?? dep.extra.patches, }); const mods = api.store.getState().persistent.mods[gameId]; return { ...dep, mod: mods[modId] }; diff --git a/src/extensions/mod_management/util/dependencies.ts b/src/extensions/mod_management/util/dependencies.ts index 83abfedc1..d283da2b8 100644 --- a/src/extensions/mod_management/util/dependencies.ts +++ b/src/extensions/mod_management/util/dependencies.ts @@ -323,7 +323,7 @@ function gatherDependenciesGraph( ...rule.reference, fileList: rule.fileList, patches: rule.extra?.patches ?? {}, - installerChoices: rule.installerChoices, + installerChoices: rule.installerChoices ?? {}, } const mod = findModByRef(modReference, state.persistent.mods[gameMode] ?? {}); diff --git a/src/extensions/mod_management/util/testModReference.ts b/src/extensions/mod_management/util/testModReference.ts index 419db3585..e263ac1ae 100644 --- a/src/extensions/mod_management/util/testModReference.ts +++ b/src/extensions/mod_management/util/testModReference.ts @@ -1,3 +1,4 @@ +/* eslint-disable */ import { truthy } from '../../../util/util'; import { log } from '../../../util/log'; @@ -128,7 +129,7 @@ function testRef(mod: IModLookupInfo, modId: string, ref: IModReference, } // Right installer choices? - if ((ref.installerChoices !== undefined && Object.keys(ref.installerChoices).length > 0) && (!_.isEqual(ref.installerChoices, mod.installerChoices))) { + if ((ref.installerChoices !== undefined && Object.keys(ref.installerChoices).length > 0) && (!_.isEqualWith(mod.installerChoices, ref.installerChoices))) { return false; } @@ -138,8 +139,10 @@ function testRef(mod: IModLookupInfo, modId: string, ref: IModReference, } // Right patches? - if ((ref.patches !== undefined && Object.keys(ref.patches).length > 0) && (!_.isEqual(ref.patches, mod.patches))) { - return false; + if ((ref.patches !== undefined && Object.keys(ref.patches).length > 0 && ref.tag !== undefined) && ((!_.isEqual(mod.patches, ref.patches)))) { + if (mod?.patches !== undefined) { + return false; + } } if (ref.tag !== undefined) {