diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index 3e38774b2f..823b3c0677 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -387,7 +387,16 @@ private static Task checkGameState(Profile profile, VersionSetting if (setting.getJavaVersionType() == JavaVersionType.VERSION) { try { int targetJavaVersionMajor = Integer.parseInt(setting.getJavaVersion()); - GameJavaVersion minimumJavaVersion = GameJavaVersion.getMinimumJavaVersion(gameVersion); + GameJavaVersion minimumJavaVersion = null; + if (gameVersion.compareTo("1.12.2") == 0) { + Optional cleanroomVersion = analyzer.getVersion(LibraryAnalyzer.LibraryType.CLEANROOM); + if (cleanroomVersion.isPresent()) { + minimumJavaVersion = GameJavaVersion.getCleanroomJavaVersion(cleanroomVersion.get()); + } + } + + if (minimumJavaVersion == null) + minimumJavaVersion = GameJavaVersion.getMinimumJavaVersion(gameVersion); if (minimumJavaVersion != null && targetJavaVersionMajor < minimumJavaVersion.majorVersion()) { Controllers.dialog( @@ -402,8 +411,17 @@ private static Task checkGameState(Profile profile, VersionSetting targetJavaVersion = GameJavaVersion.get(targetJavaVersionMajor); } catch (NumberFormatException ignored) { } - } else - targetJavaVersion = version.getJavaVersion(); + } else { + if (gameVersion.compareTo("1.12.2") == 0) { + Optional cleanroomVersion = analyzer.getVersion(LibraryAnalyzer.LibraryType.CLEANROOM); + if (cleanroomVersion.isPresent()) { + targetJavaVersion = GameJavaVersion.getCleanroomJavaVersion(cleanroomVersion.get()); + } + } + + if (targetJavaVersion == null) + targetJavaVersion = version.getJavaVersion(); + } if (targetJavaVersion != null && supportedVersions.contains(targetJavaVersion)) { downloadJava(targetJavaVersion, profile) @@ -433,7 +451,7 @@ private static Task checkGameState(Profile profile, VersionSetting if (java != null) { for (JavaVersionConstraint constraint : JavaVersionConstraint.ALL) { if (constraint.appliesToVersion(gameVersion, version, java, analyzer)) { - if (!constraint.checkJava(gameVersion, version, java)) { + if (!constraint.checkJava(gameVersion, version, java, analyzer)) { if (constraint.isMandatory()) { violatedMandatoryConstraints.add(constraint); } else { @@ -468,9 +486,14 @@ private static Task checkGameState(Profile profile, VersionSetting return result; } else { GameJavaVersion gameJavaVersion; - if (violatedMandatoryConstraints.contains(JavaVersionConstraint.CLEANROOM_JAVA_21)) - gameJavaVersion = GameJavaVersion.JAVA_21; - else if (violatedMandatoryConstraints.contains(JavaVersionConstraint.GAME_JSON)) + if (violatedMandatoryConstraints.contains(JavaVersionConstraint.CLEANROOM)) { + String cleanroomVersion = analyzer.getVersion(LibraryAnalyzer.LibraryType.CLEANROOM) + .orElse(""); + + gameJavaVersion = !cleanroomVersion.isEmpty() + ? GameJavaVersion.getCleanroomJavaVersion(cleanroomVersion) + : GameJavaVersion.JAVA_21; + } else if (violatedMandatoryConstraints.contains(JavaVersionConstraint.GAME_JSON)) gameJavaVersion = version.getJavaVersion(); else if (violatedMandatoryConstraints.contains(JavaVersionConstraint.VANILLA)) gameJavaVersion = GameJavaVersion.getMinimumJavaVersion(gameVersion); @@ -560,9 +583,14 @@ else if (violatedMandatoryConstraints.contains(JavaVersionConstraint.VANILLA)) case MODDED_JAVA_21: suggestions.add(i18n("launch.advice.modded_java", 21, gameVersion)); break; - case CLEANROOM_JAVA_21: - suggestions.add(i18n("launch.advice.cleanroom")); + case CLEANROOM: { + String cleanroomVersion = analyzer.getVersion(LibraryAnalyzer.LibraryType.CLEANROOM).orElse(""); + if (!cleanroomVersion.isEmpty()) + suggestions.add(i18n("launch.advice.cleanroom", GameJavaVersion.getCleanroomJavaVersion(cleanroomVersion).majorVersion(), cleanroomVersion)); + else + suggestions.add(i18n("launch.advice.cleanroom", 21, "")); break; + } case VANILLA_JAVA_8_51: suggestions.add(i18n("launch.advice.java8_51_1_13")); break; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManager.java b/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManager.java index 4fa82750b4..849a49b564 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManager.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManager.java @@ -304,7 +304,7 @@ public static JavaRuntime findSuitableJava(Collection javaRuntimes, for (JavaVersionConstraint constraint : JavaVersionConstraint.ALL) { if (constraint.appliesToVersion(gameVersion, version, java, analyzer)) { - if (!constraint.checkJava(gameVersion, version, java)) { + if (!constraint.checkJava(gameVersion, version, java, analyzer)) { if (constraint.isMandatory()) { violationMandatory = true; } else { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 4ac702239d..a54e5138f9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -794,7 +794,7 @@ launch.advice=%s Do you still want to continue to launch? launch.advice.multi=The following problems were detected:\n\n%s\n\nThese problems may prevent you from launching the game or affect gaming experience.\nDo you still want to continue to launch? launch.advice.java.auto=The current Java version is not compatible with the instance.\n\nClick "Yes" to automatically choose the most compatible Java version. Or, you can navigate to "Global/Instance-specific Settings → Java" to choose one yourself. launch.advice.java.modded_java_7=Minecraft 1.7.2 and previous versions require Java 7 or earlier. -launch.advice.cleanroom=Cleanroom can only be run on Java 21 or later. Please use Java 21 or later versions. +launch.advice.cleanroom=Cleanroom %2$s can only be run on Java %1$s or later. Please use Java %1$s or later versions. launch.advice.corrected=We have resolved the Java problem. If you still want to use your choice of Java version, you can disable "Do not check JVM compatibility" in "Global/Instance-specific Settings → Advanced Settings". launch.advice.uncorrected=If you still want to use your choice of Java version, you can disable "Do not check JVM compatibility" in "Global/Instance-specific Settings → Advanced Settings". launch.advice.different_platform=The 64-bit Java version is recommended for your device, but you have installed a 32-bit one. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index a7846dacf1..fe37699c70 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -598,7 +598,7 @@ launch.advice=%s 是否繼續啟動? launch.advice.multi=檢測到以下問題:\n\n%s\n\n這些問題可能導致遊戲無法正常啟動或影響遊戲體驗,是否繼續啟動? launch.advice.java.auto=目前選取的 Java 版本不滿足遊戲要求,是否自動選取合適的 Java 版本?\n或者你可以到「(全域/實例特定) 遊戲設定 → 遊戲 Java」中選取一個合適的 Java 版本。 launch.advice.java.modded_java_7=Minecraft 1.7.2 及更低版本需要 Java 7 及更低版本。 -launch.advice.cleanroom=Cleanroom 僅支援 Java 21 或更高版本。請使用 Java 21 或最新版本。 +launch.advice.cleanroom=Cleanroom %2$s 只能在 Java %1$s 或更高版本上運行。請使用 Java %1$s 或最新版本。 launch.advice.corrected=我們已經修正了 Java 版本問題。如果你確實希望使用你自訂的 Java,你可以在「(全域/實例特定) 遊戲設定 → 進階設定」中往下滑,開啟「不檢查 Java 虛擬機與遊戲的相容性」。 launch.advice.uncorrected=如果你確實希望使用你自訂的 Java,你可以在「(全域/實例特定) 遊戲設定 → 進階設定」中往下滑,開啟「不檢查 Java 虛擬機與遊戲的相容性」。 launch.advice.different_platform=你正在使用 32 位元 Java 啟動遊戲。建議更換至 64 位元 Java。 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index b4e00451ab..fcbfe99f76 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -603,7 +603,7 @@ launch.advice=%s 是否继续启动? launch.advice.multi=检测到以下问题:\n\n%s\n\n这些问题可能导致游戏无法正常启动或影响游戏体验,是否继续启动?\n你可以点击右上角帮助按钮进行求助。 launch.advice.java.auto=当前选择的 Java 版本不满足游戏要求。\n点击“是”即可由 HMCL 来自动选取合适的 Java 版本。\n或者你可以在“(全局/实例特定) 游戏设置 → 游戏 Java”中选择一个合适的 Java 版本。 launch.advice.java.modded_java_7=Minecraft 1.7.2 及更低版本需要 Java 7 及更低版本。 -launch.advice.cleanroom=Cleanroom 只能在 Java 21 或更高版本上运行。请使用 Java 21 或最新版本。 +launch.advice.cleanroom=Cleanroom %2$s 只能在 Java %1$s 或更高版本上运行。请使用 Java %1$s 或最新版本。 launch.advice.corrected=我们已经修复了 Java 版本问题。如果你确实希望使用你自定义的 Java,你可以在“(全局/实例特定) 游戏设置 → 高级设置”中往下滑,启用“不检查 Java 虚拟机与游戏的兼容性”。 launch.advice.uncorrected=如果你确实希望使用你自定义的 Java,你可以在“(全局/实例特定) 游戏设置 → 高级设置”中往下滑,启用“不检查 Java 虚拟机与游戏的兼容性”。 launch.advice.different_platform=你正在使用 32 位 Java 启动游戏。建议更换至 64 位 Java。 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameJavaVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameJavaVersion.java index f3d1dfc567..ab4927fe75 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameJavaVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameJavaVersion.java @@ -17,11 +17,13 @@ */ package org.jackhuang.hmcl.game; +import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.JsonSerializable; import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.Platform; import org.jackhuang.hmcl.util.versioning.GameVersionNumber; +import org.jackhuang.hmcl.util.versioning.VersionNumber; import java.util.Arrays; import java.util.Collections; @@ -51,6 +53,14 @@ public static GameJavaVersion getMinimumJavaVersion(GameVersionNumber gameVersio return null; } + public static GameJavaVersion getCleanroomJavaVersion(String cleanroomVersion) { + VersionNumber versionNumber = VersionNumber.asVersion(StringUtils.removeSuffix(cleanroomVersion, "-alpha")); + if (versionNumber.compareTo("0.5.0") >= 0) + return JAVA_25; + else + return JAVA_21; + } + public static GameJavaVersion get(int major) { return switch (major) { case 8 -> JAVA_8; 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 3d0ebd2487..f22f407d66 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java @@ -41,7 +41,7 @@ protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nul } @Override - public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java) { + public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java, LibraryAnalyzer analyzer) { GameJavaVersion minimumJavaVersion = GameJavaVersion.getMinimumJavaVersion(gameVersionNumber); return minimumJavaVersion == null || java.getParsedVersion() >= minimumJavaVersion.majorVersion(); } @@ -57,7 +57,7 @@ protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nul } @Override - public VersionRange getJavaVersionRange(Version version) { + public VersionRange getJavaVersionRange(Version version, LibraryAnalyzer analyzer) { String javaVersion; if (Objects.requireNonNull(version.getJavaVersion()).majorVersion() >= 9) { javaVersion = "" + version.getJavaVersion().majorVersion(); @@ -108,13 +108,26 @@ protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nul && super.appliesToVersionImpl(gameVersionNumber, version, java, analyzer); } }, - CLEANROOM_JAVA_21(true, GameVersionNumber.between("1.12.2", "1.12.999"), VersionNumber.atLeast("21")) { + CLEANROOM(true, GameVersionNumber.between("1.12.2", "1.12.999"), VersionRange.all()) { @Override - protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, - @Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) { + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaRuntime java, @Nullable LibraryAnalyzer analyzer) { return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.CLEANROOM) && super.appliesToVersionImpl(gameVersionNumber, version, java, analyzer); } + + @Override + public VersionRange getJavaVersionRange(Version version, LibraryAnalyzer analyzer) { + if (analyzer == null || !analyzer.has(LibraryAnalyzer.LibraryType.CLEANROOM)) + return VersionRange.all(); + + String cleanroomVersion = analyzer.getVersion(LibraryAnalyzer.LibraryType.CLEANROOM).orElse(""); + if (cleanroomVersion.isEmpty()) + return VersionRange.all(); + else + return VersionNumber.atLeast( + String.valueOf(GameJavaVersion.getCleanroomJavaVersion(cleanroomVersion).majorVersion()) + ); + } }, // 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")) { @@ -143,8 +156,8 @@ protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nul } @Override - public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java) { - return java.getArchitecture() != Architecture.X86_64 || super.checkJava(gameVersionNumber, version, java); + public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java, LibraryAnalyzer analyzer) { + return java.getArchitecture() != Architecture.X86_64 || super.checkJava(gameVersionNumber, version, java, analyzer); } }, // Minecraft currently does not provide official support for architectures other than x86 and x86-64. @@ -162,7 +175,7 @@ protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nul } @Override - public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java) { + public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java, LibraryAnalyzer analyzer) { return java.getArchitecture().isX86(); } }, @@ -194,7 +207,7 @@ protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nul } @Override - public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java) { + public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java, LibraryAnalyzer analyzer) { int parsedJavaVersion = java.getParsedVersion(); if (parsedJavaVersion > 17) { return false; @@ -230,7 +243,7 @@ public VersionRange getGameVersionRange() { return gameVersionRange; } - public VersionRange getJavaVersionRange(Version version) { + public VersionRange getJavaVersionRange(Version version, LibraryAnalyzer analyzer) { return javaVersionRange; } @@ -251,15 +264,15 @@ protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nul ? String.valueOf(gameJavaVersion.majorVersion()) : "1." + gameJavaVersion.majorVersion(); - VersionRange range = getJavaVersionRange(version); + VersionRange range = getJavaVersionRange(version, analyzer); VersionNumber maximum = range.getMaximum(); return maximum == null || maximum.compareTo(versionNumber) >= 0; } @SuppressWarnings("BooleanMethodIsAlwaysInverted") - public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java) { - return getJavaVersionRange(version).contains(java.getVersionNumber()); + public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaRuntime java, LibraryAnalyzer analyzer) { + return getJavaVersionRange(version, analyzer).contains(java.getVersionNumber()); } public static final List ALL = Lang.immutableListOf(values());