Skip to content

Commit 75d8215

Browse files
committed
Fix accidentally installing incompatible mods (wrong loader/version)
1 parent 35c70e9 commit 75d8215

File tree

3 files changed

+83
-43
lines changed

3 files changed

+83
-43
lines changed

src/common/modals/ModOverview.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ const ModOverview = ({
417417
} else if (source === MODRINTH) {
418418
const version = await getModrinthVersion(selectedItem);
419419
const newFile = dispatch(
420-
installModrinthMod(version, instanceName)
420+
installModrinthMod(version, instanceName, gameVersion)
421421
);
422422
setInstalledData({ fileID: selectedItem, fileName: newFile });
423423
}

src/common/modals/ModrinthModsBrowser.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ const ModsListWrapper = ({
102102
searchQuery,
103103
width,
104104
height,
105-
itemData
105+
itemData,
106+
instance
106107
}) => {
107108
// If there are more items to be loaded then add an extra row to hold a loading indicator.
108109
const itemCount = hasNextPage ? items.length + 3 : items.length;
@@ -217,7 +218,11 @@ const ModsListWrapper = ({
217218
item.project_id
218219
);
219220
const compatibleModVersions = availableModVersions
220-
.filter(v => v.game_versions.includes(gameVersion))
221+
.filter(
222+
v =>
223+
v.game_versions.includes(gameVersion) &&
224+
v.loaders.includes(instance.loader?.loaderType)
225+
)
221226
.sort((a, b) => a.date_published - b.date_published);
222227
// prioritise stable releases, fall back to unstable releases if no compatible stable releases exist
223228
const latestCompatibleModVersion =
@@ -239,6 +244,7 @@ const ModsListWrapper = ({
239244
installModrinthMod(
240245
latestCompatibleModVersion,
241246
instanceName,
247+
gameVersion,
242248
p => {
243249
if (parseInt(p, 10) !== prev) {
244250
prev = parseInt(p, 10);
@@ -513,6 +519,7 @@ const ModrinthModsBrowser = ({ instanceName, gameVersion }) => {
513519
installedMods={installedMods}
514520
instanceName={instanceName}
515521
itemData={itemData}
522+
instance={instance}
516523
/>
517524
)}
518525
</AutoSizer>

src/common/reducers/actions.js

+73-40
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ import {
6060
getJavaLatestManifest,
6161
getJavaManifest,
6262
getMcManifest,
63-
getModrinthVersionManifest,
6463
getModrinthCategories,
64+
getModrinthProject,
65+
getModrinthVersionManifest,
66+
getModrinthVersions,
6567
getMultipleAddons,
6668
mcAuthenticate,
6769
mcInvalidate,
@@ -73,7 +75,6 @@ import {
7375
msExchangeCodeForAccessToken,
7476
msMinecraftProfile,
7577
msOAuthRefresh,
76-
getModrinthVersions,
7778
getVersionsFromHashes
7879
} from '../api';
7980
import {
@@ -3600,9 +3601,15 @@ export function installMod(
36003601
/**
36013602
* @param {ModrinthVersion} version
36023603
* @param {string} instanceName
3604+
* @param {string} gameVersion
36033605
* @param {Function} onProgress
36043606
*/
3605-
export function installModrinthMod(version, instanceName, onProgress) {
3607+
export function installModrinthMod(
3608+
version,
3609+
instanceName,
3610+
gameVersion,
3611+
onProgress
3612+
) {
36063613
return async (dispatch, getState) => {
36073614
const state = getState();
36083615
const instancesPath = _getInstancesPath(state);
@@ -3617,45 +3624,48 @@ export function installModrinthMod(version, instanceName, onProgress) {
36173624
})
36183625
);
36193626

3620-
const dependencies = (await resolveModrinthDependencies(version)).filter(
3627+
// TODO: this array sometimes contains an empty array?
3628+
const dependencies = (
3629+
await resolveModrinthDependencies(version, gameVersion)
3630+
).filter(
36213631
dep => existingMods.find(mod => mod.fileID === dep.id) === undefined
36223632
);
36233633

36243634
// install dependencies and the mod that we want
36253635
await pMap(
36263636
[...dependencies, version],
3627-
async v => {
3628-
const primaryFile = v.files.find(f => f.primary);
3629-
3630-
const destFile = path.join(instancePath, 'mods', primaryFile.filename);
3631-
const tempFile = path.join(_getTempPath(state), primaryFile.filename);
3632-
3633-
// download the mod
3634-
await downloadFile(tempFile, primaryFile.url, onProgress);
3635-
3636-
// add mod to the mods list in the instance's config file
3637-
await dispatch(
3638-
updateInstanceConfig(instanceName, config => {
3639-
return {
3640-
...config,
3641-
mods: [
3642-
...config.mods,
3643-
...[
3644-
{
3645-
source: MODRINTH,
3646-
projectID: v.project_id,
3647-
fileID: v.id,
3648-
fileName: primaryFile.filename,
3649-
displayName: primaryFile.filename,
3650-
downloadUrl: primaryFile.url
3651-
}
3637+
v => {
3638+
v.files?.forEach(async file => {
3639+
const destFile = path.join(instancePath, 'mods', file.filename);
3640+
const tempFile = path.join(_getTempPath(state), file.filename);
3641+
3642+
// download the mod
3643+
await downloadFile(tempFile, file.url, onProgress);
3644+
3645+
// add mod to the mods list in the instance's config file
3646+
await dispatch(
3647+
updateInstanceConfig(instanceName, config => {
3648+
return {
3649+
...config,
3650+
mods: [
3651+
...config.mods,
3652+
...[
3653+
{
3654+
source: MODRINTH,
3655+
projectID: v.project_id,
3656+
fileID: v.id,
3657+
fileName: file.filename,
3658+
displayName: file.filename,
3659+
downloadUrl: file.url
3660+
}
3661+
]
36523662
]
3653-
]
3654-
};
3655-
})
3656-
);
3663+
};
3664+
})
3665+
);
36573666

3658-
await fse.move(tempFile, destFile, { overwrite: true });
3667+
await fse.move(tempFile, destFile, { overwrite: true });
3668+
});
36593669
},
36603670
{ concurrency: 2 }
36613671
);
@@ -3664,24 +3674,46 @@ export function installModrinthMod(version, instanceName, onProgress) {
36643674

36653675
/**
36663676
* Recursively gets all the dependent versions of a given version and returns them in one array
3667-
* @param {ModrinthVersion} version
3677+
* @param {ModrinthVersion} version The mod version to get the dependencies for
3678+
* @param {string} gameVersion The required Minecraft version, so we can ensure dependencies are compatible
36683679
* @returns {Promise<ModrinthVersion[]>}
36693680
*/
3670-
async function resolveModrinthDependencies(version) {
3681+
async function resolveModrinthDependencies(version, gameVersion) {
36713682
// TODO: Ideally this function should be aware of mods the user already has installed and ignore them
36723683

3684+
// Note: version.dependencies[].version_id can sometimes be null.
3685+
// In this case we use the given project_id and select the most recent compatible version.
3686+
36733687
// Get the IDs for this version's required dependencies
3674-
const depVersionIDs = version.dependencies
3675-
.filter(v => v.dependency_type === 'required')
3676-
.map(v => v.version_id);
3688+
const depVersionIDs = await pMap(
3689+
version.dependencies.filter(dep => dep.dependency_type === 'required'),
3690+
async dep => {
3691+
if (dep.version_id) return dep.version_id;
3692+
3693+
const project = await getModrinthProject(dep.project_id);
3694+
const availableModVersions = await getModrinthVersions(project.versions);
3695+
3696+
// Get the latest compatible version
3697+
const compatibleModVersions = availableModVersions
3698+
.filter(v => v.game_versions.includes(gameVersion))
3699+
.sort((a, b) => a.date_published - b.date_published);
3700+
// prioritise stable releases, fall back to unstable releases if no compatible stable releases exist
3701+
const latestCompatibleModVersion =
3702+
compatibleModVersions.find(v => v.version_type === 'release') ??
3703+
compatibleModVersions.find(v => v.version_type === 'beta') ??
3704+
compatibleModVersions.find(v => v.version_type === 'alpha');
3705+
3706+
return latestCompatibleModVersion.id;
3707+
}
3708+
);
36773709

36783710
// If this version does not depend on anything, return nothing
36793711
if (depVersionIDs.length === 0) return [];
36803712

36813713
// If we do have dependencies, get the version objects for each of those and recurse on those
36823714
const depVersions = await getModrinthVersions(depVersionIDs);
36833715
const subDepVersions = await pMap(depVersions, async v =>
3684-
resolveModrinthDependencies(v)
3716+
resolveModrinthDependencies(v, gameVersion)
36853717
);
36863718

36873719
return [...depVersions, ...subDepVersions];
@@ -3702,6 +3734,7 @@ export const deleteMod = (instanceName, mod) => {
37023734
};
37033735
};
37043736

3737+
// TODO: Support Modrinth here
37053738
export const updateMod = (
37063739
instanceName,
37073740
mod,

0 commit comments

Comments
 (0)