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

@@ -179,6 +179,56 @@ pub enum Os {
Unknown,
}
impl Os {
/// Returns the native OS of the build
pub fn native() -> Self {
match std::env::consts::OS {
"windows" => Self::Windows,
"macos" => Self::Osx,
"linux" => Self::Linux,
_ => Self::Unknown,
}
}
/// Returns the native OS variant of the build, taking into account the architecture of its Java runtime
pub fn native_arch(java_arch: &str) -> Self {
if std::env::consts::OS == "windows" {
if java_arch == "aarch64" {
Os::WindowsArm64
} else {
Os::Windows
}
} else if std::env::consts::OS == "linux" {
if java_arch == "aarch64" {
Os::LinuxArm64
} else if java_arch == "arm" {
Os::LinuxArm32
} else {
Os::Linux
}
} else if std::env::consts::OS == "macos" {
if java_arch == "aarch64" {
Os::OsxArm64
} else {
Os::Osx
}
} else {
Os::Unknown
}
}
/// Returns the base OS of a variant (e.g. OsxArm64 -> Osx)
pub fn get_os(&self) -> Self {
match self {
Os::OsxArm64 => Os::Osx,
Os::LinuxArm32 => Os::Linux,
Os::LinuxArm64 => Os::Linux,
Os::WindowsArm64 => Os::Windows,
_ => self.clone(),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A rule which depends on what OS the user is on
pub struct OsRule {
@@ -277,6 +327,24 @@ pub struct Library {
pub downloadable: bool,
}
impl Library {
/// Returns the OS key and classifiers for downloading natives, if applicable
pub fn natives_os_key_and_classifiers(
&self,
java_arch: &str,
) -> Option<(&str, &HashMap<String, LibraryDownload>)> {
self.natives
.as_ref()
.and_then(|natives| natives.get(&Os::native_arch(java_arch)))
.and_then(|natives| {
self.downloads
.as_ref()
.and_then(|downloads| downloads.classifiers.as_ref())
.map(|classifiers| (natives.as_str(), classifiers))
})
}
}
#[derive(Deserialize, Debug, Clone)]
/// A partial library which should be merged with a full library
pub struct PartialLibrary {