diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java index 589f9ef80..7185f19e2 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java @@ -34,62 +34,18 @@ import static org.jackhuang.hmcl.download.LibraryAnalyzer.LAUNCH_WRAPPER_MAIN; public enum JavaVersionConstraint { 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 public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java) { GameJavaVersion minimumJavaVersion = GameJavaVersion.getMinimumJavaVersion(gameVersionNumber); 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. GAME_JSON(true, VersionRange.all(), VersionRange.all()) { @Override @@ -111,6 +67,61 @@ public enum JavaVersionConstraint { 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. // 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")) { @@ -151,7 +162,8 @@ public enum JavaVersionConstraint { @Override protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @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) .map(VersionNumber::asVersion) .orElse(null); @@ -221,7 +233,19 @@ public enum JavaVersionConstraint { protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @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 range = getJavaVersionRange(version); + VersionNumber maximum = range.getMaximum(); + + return maximum == null || maximum.compareTo(versionNumber) >= 0; } @SuppressWarnings("BooleanMethodIsAlwaysInverted")