fix(app): make MC <1.12.2 downloadable again (#4494)

PR #4270 modified the internal `fetch` function used by the application
to download version artifacts in a way that 4xx HTTP errors also caused
an abnormal return, instead of just 5xx errors. That was a good change,
but it had the unintended side effect of exposing our faulty logic
elsewhere of trying to download non-native JAR library artifacts when
only native artifacts are appropriate, at least according to the
PrismLauncher source code I've read. Such a download always returned a
404 error, but because such error was considered successful, a dummy
library file was still created and things worked seemingly fine.

These changes bring the Modrinth App behavior in this regard more in
line with PrismLauncher's, avoiding downloading non-native artifacts for
dependencies that have native artifacts available. (Reference:
8b5e91920d/launcher/minecraft/Library.cpp (L163))

I've tested these changes to work successfully with a variety of old
vanilla and modded Minecraft versions.

Fixes #4464.
This commit is contained in:
Alejandro González
2025-10-04 23:27:41 +02:00
committed by GitHub
parent d98394d8d5
commit fd80f1217d
4 changed files with 206 additions and 151 deletions

View File

@@ -15,7 +15,7 @@ use daedalus::{
};
use dunce::canonicalize;
use itertools::Itertools;
use std::io::{BufRead, BufReader};
use std::io::{BufRead, BufReader, ErrorKind};
use std::net::SocketAddr;
use std::{collections::HashMap, path::Path};
use uuid::Uuid;
@@ -60,7 +60,11 @@ pub fn get_class_paths(
return None;
}
Some(get_lib_path(libraries_path, &library.name, false))
Some(get_lib_path(
libraries_path,
&library.name,
library.natives_os_key_and_classifiers(java_arch).is_some(),
))
}))
.process_results(|iter| {
iter.unique().join(classpath_separator(java_arch))
@@ -85,21 +89,21 @@ pub fn get_lib_path(
lib: &str,
allow_not_exist: bool,
) -> crate::Result<String> {
let path = libraries_path
.to_path_buf()
.join(get_path_from_artifact(lib)?);
let path = libraries_path.join(get_path_from_artifact(lib)?);
if !path.exists() && allow_not_exist {
return Ok(path.to_string_lossy().to_string());
}
let path = &canonicalize(&path).map_err(|_| {
crate::ErrorKind::LauncherError(format!(
"Library file at path {} does not exist",
path.to_string_lossy()
))
.as_error()
})?;
let path = match canonicalize(&path) {
Ok(p) => p,
Err(err) if err.kind() == ErrorKind::NotFound && allow_not_exist => {
path
}
Err(err) => {
return Err(crate::ErrorKind::LauncherError(format!(
"Could not canonicalize library path {}: {err}",
path.display()
))
.as_error());
}
};
Ok(path.to_string_lossy().to_string())
}