优化 JavaVersionConstraint (#3981)

This commit is contained in:
Glavo 2025-06-08 20:21:05 +08:00 committed by GitHub
parent 8889cca878
commit a0e9a20782
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -34,62 +34,18 @@ import static org.jackhuang.hmcl.download.LibraryAnalyzer.LAUNCH_WRAPPER_MAIN;
public enum JavaVersionConstraint { public enum JavaVersionConstraint {
VANILLA(true, VersionRange.all(), VersionRange.all()) { VANILLA(true, VersionRange.all(), VersionRange.all()) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
// Give priority to the Java version requirements specified in the version JSON
return version == null || version.getJavaVersion() == null;
}
@Override @Override
public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java) { public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java) {
GameJavaVersion minimumJavaVersion = GameJavaVersion.getMinimumJavaVersion(gameVersionNumber); GameJavaVersion minimumJavaVersion = GameJavaVersion.getMinimumJavaVersion(gameVersionNumber);
return minimumJavaVersion == null || java.getParsedVersion() >= minimumJavaVersion.getMajorVersion(); return minimumJavaVersion == null || java.getParsedVersion() >= minimumJavaVersion.getMajorVersion();
} }
}, },
// Minecraft<=1.7.2+Forge requires Java<=7, But LegacyModFixer may fix that problem. So only suggest user using Java 7.
MODDED_JAVA_7(false, GameVersionNumber.atMost("1.7.2"), VersionNumber.atMost("1.7.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return version != null && analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE);
}
},
MODDED_JAVA_8(false, GameVersionNumber.between("1.7.10", "1.16.999"), VersionNumber.between("1.8", "1.8.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE);
}
},
MODDED_JAVA_16(false, GameVersionNumber.between("1.17", "1.17.999"), VersionNumber.between("16", "16.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE);
}
},
MODDED_JAVA_17(false, GameVersionNumber.between("1.18", "1.20.4"), VersionNumber.between("17", "17.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE);
}
},
MODDED_JAVA_21(false, GameVersionNumber.atLeast("1.20.5"), VersionNumber.between("21", "21.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE);
}
},
// LaunchWrapper<=1.12 will crash because LaunchWrapper assumes the system class loader is an instance of URLClassLoader (Java 8)
LAUNCH_WRAPPER(true, GameVersionNumber.atMost("1.12.999"), VersionNumber.atMost("1.8.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
if (version == null) return false;
return LAUNCH_WRAPPER_MAIN.equals(version.getMainClass()) &&
version.getLibraries().stream()
.filter(library -> "launchwrapper".equals(library.getArtifactId()))
.anyMatch(library -> VersionNumber.asVersion(library.getVersion()).compareTo(VersionNumber.asVersion("1.13")) < 0);
}
},
// Minecraft>=1.13 may crash when generating world on Java [1.8,1.8.0_51)
VANILLA_JAVA_8_51(false, GameVersionNumber.atLeast("1.13"), VersionNumber.atLeast("1.8.0_51")),
// Minecraft with suggested java version recorded in game json is restrictedly constrained. // Minecraft with suggested java version recorded in game json is restrictedly constrained.
GAME_JSON(true, VersionRange.all(), VersionRange.all()) { GAME_JSON(true, VersionRange.all(), VersionRange.all()) {
@Override @Override
@ -111,6 +67,61 @@ public enum JavaVersionConstraint {
return VersionNumber.atLeast(javaVersion); return VersionNumber.atLeast(javaVersion);
} }
}, },
// Minecraft<=1.7.2+Forge requires Java<=7, But LegacyModFixer may fix that problem. So only suggest user using Java 7.
MODDED_JAVA_7(false, GameVersionNumber.atMost("1.7.2"), VersionNumber.atMost("1.7.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)
&& super.appliesToVersionImpl(gameVersionNumber, version, java, analyzer);
}
},
MODDED_JAVA_8(false, GameVersionNumber.between("1.7.10", "1.16.999"), VersionNumber.between("1.8", "1.8.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)
&& super.appliesToVersionImpl(gameVersionNumber, version, java, analyzer);
}
},
MODDED_JAVA_16(false, GameVersionNumber.between("1.17", "1.17.999"), VersionNumber.between("16", "16.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)
&& super.appliesToVersionImpl(gameVersionNumber, version, java, analyzer);
}
},
MODDED_JAVA_17(false, GameVersionNumber.between("1.18", "1.20.4"), VersionNumber.between("17", "17.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)
&& super.appliesToVersionImpl(gameVersionNumber, version, java, analyzer);
}
},
MODDED_JAVA_21(false, GameVersionNumber.atLeast("1.20.5"), VersionNumber.between("21", "21.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)
&& super.appliesToVersionImpl(gameVersionNumber, version, java, analyzer);
}
},
// LaunchWrapper<=1.12 will crash because LaunchWrapper assumes the system class loader is an instance of URLClassLoader (Java 8)
LAUNCH_WRAPPER(true, GameVersionNumber.atMost("1.12.999"), VersionNumber.atMost("1.8.999")) {
@Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
if (version == null) return false;
return super.appliesToVersionImpl(gameVersionNumber, version, java, analyzer) && LAUNCH_WRAPPER_MAIN.equals(version.getMainClass()) &&
version.getLibraries().stream()
.filter(library -> "launchwrapper".equals(library.getArtifactId()))
.anyMatch(library -> VersionNumber.asVersion(library.getVersion()).compareTo(VersionNumber.asVersion("1.13")) < 0);
}
},
// Minecraft>=1.13 may crash when generating world on Java [1.8,1.8.0_51)
VANILLA_JAVA_8_51(false, GameVersionNumber.atLeast("1.13"), VersionNumber.atLeast("1.8.0_51")),
// On Linux, JDK 9+ cannot launch Minecraft<=1.12.2, since JDK 9+ does not accept loading native library built in different arch. // On Linux, JDK 9+ cannot launch Minecraft<=1.12.2, since JDK 9+ does not accept loading native library built in different arch.
// For example, JDK 9+ 64-bit cannot load 32-bit lwjgl native library. // For example, JDK 9+ 64-bit cannot load 32-bit lwjgl native library.
VANILLA_LINUX_JAVA_8(true, GameVersionNumber.atMost("1.12.999"), VersionNumber.atMost("1.8.999")) { VANILLA_LINUX_JAVA_8(true, GameVersionNumber.atMost("1.12.999"), VersionNumber.atMost("1.8.999")) {
@ -151,7 +162,8 @@ public enum JavaVersionConstraint {
@Override @Override
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) { @Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
if (version == null || java == null || analyzer == null) return false; if (version == null || java == null || analyzer == null || !super.appliesToVersionImpl(gameVersionNumber, version, java, analyzer))
return false;
VersionNumber forgePatchVersion = analyzer.getVersion(LibraryAnalyzer.LibraryType.FORGE) VersionNumber forgePatchVersion = analyzer.getVersion(LibraryAnalyzer.LibraryType.FORGE)
.map(VersionNumber::asVersion) .map(VersionNumber::asVersion)
.orElse(null); .orElse(null);
@ -221,7 +233,19 @@ public enum JavaVersionConstraint {
protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version,
@Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) { @Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) {
return true; GameJavaVersion gameJavaVersion;
if (version == null || (gameJavaVersion = version.getJavaVersion()) == null) {
return true;
}
String versionNumber = gameJavaVersion.getMajorVersion() >= 9
? String.valueOf(gameJavaVersion.getMajorVersion())
: "1." + gameJavaVersion.getMajorVersion();
VersionRange<VersionNumber> range = getJavaVersionRange(version);
VersionNumber maximum = range.getMaximum();
return maximum == null || maximum.compareTo(versionNumber) >= 0;
} }
@SuppressWarnings("BooleanMethodIsAlwaysInverted") @SuppressWarnings("BooleanMethodIsAlwaysInverted")