From 9196bda537e455411d270f99a7a19d5b726c5474 Mon Sep 17 00:00:00 2001 From: Glavo Date: Wed, 9 Oct 2024 00:19:06 +0800 Subject: [PATCH 001/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20FXUtils.testLinuxC?= =?UTF-8?q?ommand=20(#3315)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index b7394c40e7..cbedf9fb40 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -84,6 +84,7 @@ import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -411,15 +412,20 @@ else if (OperatingSystem.CURRENT_OS.isLinuxOrBSD() && new File("/usr/bin/xdg-ope }); } - private static boolean testLinuxCommand(String command) { - try (final InputStream is = Runtime.getRuntime().exec(new String[]{"which", command}).getInputStream()) { - if (is.read() != -1) { - return true; + private static String which(String command) { + String path = System.getenv("PATH"); + if (path == null) + return null; + + for (String item : path.split(OperatingSystem.PATH_SEPARATOR)) { + try { + Path program = Paths.get(item, command); + if (Files.isExecutable(program)) + return program.toRealPath().toString(); + } catch (Throwable ignored) { } - } catch (Throwable ignored) { } - - return false; + return null; } public static void showFileInExplorer(Path file) { @@ -430,7 +436,7 @@ public static void showFileInExplorer(Path file) { openCommands = new String[]{"explorer.exe", "/select,", path}; else if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) openCommands = new String[]{"/usr/bin/open", "-R", path}; - else if (OperatingSystem.CURRENT_OS.isLinuxOrBSD() && testLinuxCommand("dbus-send")) + else if (OperatingSystem.CURRENT_OS.isLinuxOrBSD() && which("dbus-send") != null) openCommands = new String[]{ "dbus-send", "--print-reply", @@ -496,12 +502,13 @@ public static void openLink(String link) { } if (OperatingSystem.CURRENT_OS.isLinuxOrBSD()) { for (String browser : linuxBrowsers) { - try (final InputStream is = Runtime.getRuntime().exec(new String[]{"which", browser}).getInputStream()) { - if (is.read() != -1) { + String path = which(browser); + if (path != null) { + try { Runtime.getRuntime().exec(new String[]{browser, link}); return; + } catch (Throwable ignored) { } - } catch (Throwable ignored) { } LOG.warning("No known browser found"); } From 74926704bd2001a7962f19f666a83cd05c630f07 Mon Sep 17 00:00:00 2001 From: Glavo Date: Wed, 9 Oct 2024 00:35:07 +0800 Subject: [PATCH 002/169] =?UTF-8?q?Close=20#3209:=20=E6=90=9C=E7=B4=A2=20I?= =?UTF-8?q?ntelliJ=20IDEA=20=E5=AE=89=E8=A3=85=E7=9A=84=20Java=20(#3316)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManager.java | 5 +++-- HMCLCore/src/main/java/org/jackhuang/hmcl/java/JavaInfo.java | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) 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 3b9e86e815..a5592e6a9b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManager.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManager.java @@ -404,9 +404,9 @@ private static Map searchPotentialJavaExecutables() { FileUtils.tryGetPath(Lang.requireNonNullElse(System.getenv("ProgramFiles(x86)"), "C:\\Program Files (x86)"), "Minecraft Launcher\\runtime") .ifPresent(it -> searchAllOfficialJava(javaRuntimes, it, false)); } else if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX && Architecture.SYSTEM_ARCH == Architecture.X86_64) { - searchAllOfficialJava(javaRuntimes, Paths.get(System.getProperty("user.home")).resolve(".minecraft/runtime"), false); + searchAllOfficialJava(javaRuntimes, Paths.get(System.getProperty("user.home"), ".minecraft/runtime"), false); } else if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) { - searchAllOfficialJava(javaRuntimes, Paths.get(System.getProperty("user.home")).resolve("Library/Application Support/minecraft/runtime"), false); + searchAllOfficialJava(javaRuntimes, Paths.get(System.getProperty("user.home"), "Library/Application Support/minecraft/runtime"), false); } searchAllOfficialJava(javaRuntimes, CacheRepository.getInstance().getCacheDirectory().resolve("java"), true); @@ -430,6 +430,7 @@ private static Map searchPotentialJavaExecutables() { } } } + searchAllJavaInDirectory(javaRuntimes, Paths.get(System.getProperty("user.home"), ".jdks")); for (String javaPath : ConfigHolder.globalConfig().getUserJava()) { try { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/java/JavaInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/java/JavaInfo.java index 160a152bb7..dc4be6700b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/java/JavaInfo.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/java/JavaInfo.java @@ -129,6 +129,8 @@ public static String normalizeVendor(String vendor) { return "IBM"; case "Eclipse Adoptium": return "Adoptium"; + case "Amazon.com Inc.": + return "Amazon"; default: return vendor; } From 7937f8ddf568b19d5d926f2b502f4926d14b7f72 Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Wed, 9 Oct 2024 01:03:56 +0800 Subject: [PATCH 003/169] =?UTF-8?q?=E5=8F=91=E7=8E=B0=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=BC=B9=E7=AA=97=E6=B7=BB=E5=8A=A0=E5=8F=96=E6=B6=88=E6=8C=89?= =?UTF-8?q?=E9=92=AE=20(#3282)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java index 6f1cf7f176..f0e651e301 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java @@ -237,10 +237,10 @@ private void showUpdate(boolean show) { doAnimation(show); if (show && getLatestVersion() != null && !Objects.equals(config().getPromptedVersion(), getLatestVersion().getVersion())) { - Controllers.dialog("", i18n("update.bubble.title", getLatestVersion().getVersion()), MessageDialogPane.MessageType.INFO, () -> { + Controllers.confirm("", i18n("update.bubble.title", getLatestVersion().getVersion()), MessageDialogPane.MessageType.INFO, () -> { config().setPromptedVersion(getLatestVersion().getVersion()); onUpgrade(); - }); + }, null); } } From c7f248a092bd332702d638fef464470f8ce7fd4b Mon Sep 17 00:00:00 2001 From: Glavo Date: Wed, 9 Oct 2024 01:40:26 +0800 Subject: [PATCH 004/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=20(#3317)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 优化更新窗口 * fix NPE --- .../hmcl/ui/construct/MessageDialogPane.java | 10 ++++++++++ .../java/org/jackhuang/hmcl/ui/main/MainPage.java | 11 +++++++---- HMCL/src/main/resources/assets/lang/I18N.properties | 1 + .../src/main/resources/assets/lang/I18N_zh.properties | 1 + .../main/resources/assets/lang/I18N_zh_CN.properties | 1 + 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java index dd70b735b6..a709305f1a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java @@ -166,6 +166,16 @@ public Builder addAction(Node actionNode) { return this; } + public Builder addAction(String text, @Nullable Runnable action) { + JFXButton btnAction = new JFXButton(text); + btnAction.getStyleClass().add("dialog-accept"); + if (action != null) { + btnAction.setOnAction(e -> action.run()); + } + dialog.addButton(btnAction); + return this; + } + public Builder ok(@Nullable Runnable ok) { JFXButton btnOk = new JFXButton(i18n("button.ok")); btnOk.getStyleClass().add("dialog-accept"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java index f0e651e301..d97a0a9aa4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java @@ -237,10 +237,13 @@ private void showUpdate(boolean show) { doAnimation(show); if (show && getLatestVersion() != null && !Objects.equals(config().getPromptedVersion(), getLatestVersion().getVersion())) { - Controllers.confirm("", i18n("update.bubble.title", getLatestVersion().getVersion()), MessageDialogPane.MessageType.INFO, () -> { - config().setPromptedVersion(getLatestVersion().getVersion()); - onUpgrade(); - }, null); + Controllers.dialog(new MessageDialogPane.Builder("", i18n("update.bubble.title", getLatestVersion().getVersion()), MessageDialogPane.MessageType.INFO) + .addAction(i18n("button.view"), () -> { + config().setPromptedVersion(getLatestVersion().getVersion()); + onUpgrade(); + }) + .addCancel(null) + .build()); } } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 195c935006..cb911a30d4 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -183,6 +183,7 @@ button.retry=Retry button.save=Save button.save_as=Save As button.select_all=Select All +button.view=View button.yes=Yes chat=Join Group Chat diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index a8c474fdd3..e8abf4f47b 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -192,6 +192,7 @@ button.retry=重試 button.save=儲存 button.save_as=另存為 button.select_all=全選 +button.view=查看 button.yes=是 chat=官方群組 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 442513ab26..42a448e238 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -193,6 +193,7 @@ button.retry=重试 button.save=保存 button.save_as=另存为 button.select_all=全选 +button.view=查看 button.yes=是 chat=官方群组 From 541f2e26199dae5cdf2bff42ebc3ce1a5c5a665d Mon Sep 17 00:00:00 2001 From: Glavo Date: Wed, 9 Oct 2024 02:00:53 +0800 Subject: [PATCH 005/169] =?UTF-8?q?=E6=B8=85=E7=90=86=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=20i18n=20=E6=9D=A1=E7=9B=AE=20(#331?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/resources/assets/lang/I18N.properties | 2 -- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 1 - HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 1 - 3 files changed, 4 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index cb911a30d4..c455bbff31 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -354,8 +354,6 @@ extension.mod=Mod File extension.png=Image File extension.ps1=Windows PowerShell Script(.ps1) extension.sh=Shell Script(.sh) -fatal.fractureiser=Hello Minecraft! Launcher has detected that your computer has been infected with the Fraureiser virus, which poses a serious security issue.\n\ -Please use antivirus software to perform a full scan immediately, and then change the passwords of all accounts you have logged in on this computer. fatal.javafx.incompatible=Missing JavaFX environment.\n\ HMCL cannot automatically install JavaFX under Java versions below 11.\n\ Please update your Java to version 11 or higher. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index e8abf4f47b..bfbda91368 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -362,7 +362,6 @@ extension.png=圖片檔案 extension.ps1=PowerShell 指令碼 extension.sh=Bash 指令碼 -fatal.fractureiser=Hello Minecraft! Launcher 檢測到你的電腦被 Fractureiser 病毒感染,存在嚴重安全問題。\n請立即使用殺毒軟體進行全盤查殺,隨後修改你在此電腦上登入過的所有帳號的密碼。 fatal.javafx.incompatible=缺少 JavaFX 運行環境。\nHMCL 無法在低於 Java 11 的 Java 環境上自行補全 JavaFX 運行環境,請更新到 Java 11 或更高版本。 fatal.javafx.incomplete=JavaFX 運行環境不完整,請嘗試更換你的 Java 或者重新安裝 OpenJFX。 fatal.javafx.missing=缺少 JavaFX 運行環境,請使用包含 OpenJFX 的 Java 運行環境啟動 Hello Minecraft! Launcher。\n你可以訪問 https://docs.hmcl.net/help.html 頁面尋求幫助。 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 42a448e238..21090c4d4d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -364,7 +364,6 @@ extension.png=图片文件 extension.ps1=PowerShell 脚本 extension.sh=Bash 脚本 -fatal.fractureiser=Hello Minecraft! Launcher 检测到你的电脑被 Fractureiser 病毒感染,存在严重安全问题。\n请立即使用杀毒软件进行全盘查杀,随后修改你在此电脑上登陆过的所有账户的密码。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 fatal.javafx.incompatible=缺少 JavaFX 运行环境。\nHello Minecraft! Launcher 无法在低于 Java 11 的 Java 环境上自行补全 JavaFX 运行环境,请更新到 Java 11 或更高版本。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 fatal.javafx.incomplete=JavaFX 运行环境不完整,请尝试更换你的 Java 或者重新安装 OpenJFX。 fatal.javafx.missing=缺少 JavaFX 运行环境,请使用包含 OpenJFX 的 Java 运行环境启动 Hello Minecraft! Launcher。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 From ef9159666cc5f6e919b0edf820ec71a4cd61d1bc Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 11 Oct 2024 20:50:58 +0800 Subject: [PATCH 006/169] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20TypeToken=20?= =?UTF-8?q?=E6=9B=BF=E4=BB=A3=20Type=20(#3320)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/game/HMCLModpackInstallTask.java | 4 +- .../jackhuang/hmcl/game/ModpackHelper.java | 4 +- .../org/jackhuang/hmcl/java/JavaManifest.java | 6 +-- .../org/jackhuang/hmcl/setting/Accounts.java | 8 ++-- .../org/jackhuang/hmcl/ui/main/HelpPage.java | 5 +-- .../jackhuang/hmcl/util/NativePatcher.java | 6 +-- .../hmcl/util/SelfDependencyPatcher.java | 11 ++--- .../hmcl/auth/offline/YggdrasilServer.java | 5 +-- .../download/fabric/FabricVersionList.java | 7 ++-- .../download/forge/ForgeBMCLVersionList.java | 6 +-- .../java/mojang/MojangJavaDownloads.java | 7 ++-- .../neoforge/NeoForgeBMCLVersionList.java | 6 +-- .../optifine/OptiFineBMCLVersionList.java | 7 ++-- .../hmcl/download/quilt/QuiltVersionList.java | 7 ++-- .../hmcl/game/DefaultGameRepository.java | 7 +--- .../jackhuang/hmcl/game/RuledArgument.java | 9 ++-- .../hmcl/mod/ModpackConfiguration.java | 6 +++ .../curse/CurseForgeRemoteModRepository.java | 30 +++++++------ .../hmcl/mod/curse/CurseInstallTask.java | 4 +- .../mod/mcbbs/McbbsModpackCompletionTask.java | 4 +- .../mcbbs/McbbsModpackLocalInstallTask.java | 4 +- .../hmcl/mod/mcbbs/McbbsModpackProvider.java | 4 +- .../mcbbs/McbbsModpackRemoteInstallTask.java | 4 +- .../hmcl/mod/modinfo/ForgeOldModMetadata.java | 7 ++-- .../mod/modrinth/ModrinthInstallTask.java | 5 +-- .../modrinth/ModrinthRemoteModRepository.java | 15 ++++--- .../multimc/MultiMCModpackInstallTask.java | 4 +- .../server/ServerModpackCompletionTask.java | 4 +- .../server/ServerModpackLocalInstallTask.java | 4 +- .../ServerModpackRemoteInstallTask.java | 6 +-- .../jackhuang/hmcl/util/CacheRepository.java | 17 ++++---- .../jackhuang/hmcl/util/gson/JsonUtils.java | 33 ++++++++++----- .../jackhuang/hmcl/util/io/HttpRequest.java | 6 +-- .../hmcl/util/gson/JsonUtilsTest.java | 42 +++++++++++++++++++ 34 files changed, 165 insertions(+), 139 deletions(-) create mode 100644 HMCLCore/src/test/java/org/jackhuang/hmcl/util/gson/JsonUtilsTest.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java index 19c8147ad1..494e9b6490 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLModpackInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.game; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.mod.MinecraftInstanceTask; @@ -67,8 +66,7 @@ public HMCLModpackInstallTask(Profile profile, File zipFile, Modpack modpack, St ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(Modpack.class)); if (!HMCLModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a HMCL modpack. Cannot update this version."); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index c076765976..78b96db501 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.game; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.apache.commons.compress.archivers.zip.ZipFile; import org.jackhuang.hmcl.mod.*; import org.jackhuang.hmcl.mod.curse.CurseModpackProvider; @@ -141,8 +140,7 @@ public static ModpackConfiguration readModpackConfiguration(File file) throws throw new FileNotFoundException(file.getPath()); else try { - return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken>() { - }.getType()); + return JsonUtils.GSON.fromJson(FileUtils.readText(file), ModpackConfiguration.class); } catch (JsonParseException e) { throw new IOException("Malformed modpack configuration"); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManifest.java b/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManifest.java index 974ed92cd1..856b2a7195 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManifest.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManifest.java @@ -19,7 +19,6 @@ import com.google.gson.*; import com.google.gson.annotations.JsonAdapter; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.Platform; @@ -29,6 +28,8 @@ import java.util.Map; import java.util.Optional; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; + /** * @author Glavo */ @@ -63,8 +64,7 @@ public Map getFiles() { public static final class Serializer implements JsonSerializer, JsonDeserializer { - private static final Type LOCAL_FILES_TYPE = new TypeToken>() { - }.getType(); + private static final Type LOCAL_FILES_TYPE = mapTypeOf(String.class, JavaLocalFiles.Local.class).getType(); @Override public JsonElement serialize(JavaManifest src, Type typeOfSrc, JsonSerializationContext context) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java index 6223c6da8f..009cf6b40e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.setting; -import com.google.gson.reflect.TypeToken; import javafx.beans.InvalidationListener; import javafx.beans.Observable; import javafx.beans.property.ObjectProperty; @@ -55,6 +54,8 @@ import static org.jackhuang.hmcl.util.Lang.immutableListOf; import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -171,14 +172,11 @@ private static void updateAccountStorages() { config().getAccountStorages().setAll(portable); } - @SuppressWarnings("unchecked") private static void loadGlobalAccountStorages() { Path globalAccountsFile = Metadata.HMCL_DIRECTORY.resolve("accounts.json"); if (Files.exists(globalAccountsFile)) { try (Reader reader = Files.newBufferedReader(globalAccountsFile)) { - globalAccountStorages.setAll((List>) - Config.CONFIG_GSON.fromJson(reader, new TypeToken>>() { - }.getType())); + globalAccountStorages.setAll(Config.CONFIG_GSON.fromJson(reader, listTypeOf(mapTypeOf(Object.class, Object.class)))); } catch (Throwable e) { LOG.warning("Failed to load global accounts", e); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/HelpPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/HelpPage.java index 33f7935e30..75223967c3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/HelpPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/HelpPage.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.ui.main; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import javafx.geometry.Insets; import javafx.scene.control.ScrollPane; import javafx.scene.layout.VBox; @@ -34,6 +33,7 @@ import java.util.Collections; import java.util.List; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class HelpPage extends SpinnerPane { @@ -63,8 +63,7 @@ public HelpPage() { private void loadHelp() { showSpinner(); - Task.>supplyAsync(() -> HttpRequest.GET("https://docs.hmcl.net/index.json").getJson(new TypeToken>() { - }.getType())) + Task.supplyAsync(() -> HttpRequest.GET("https://docs.hmcl.net/index.json").getJson(listTypeOf(HelpCategory.class))) .thenAcceptAsync(Schedulers.javafx(), helpCategories -> { for (HelpCategory category : helpCategories) { ComponentList categoryPane = new ComponentList(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java index 79d21fbb4a..82ccd9fc3b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.util; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.game.*; import org.jackhuang.hmcl.setting.VersionSetting; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -34,6 +33,7 @@ import java.util.*; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; import static org.jackhuang.hmcl.util.logging.Logger.LOG; /** @@ -51,9 +51,7 @@ private static Map getNatives(Platform platform) { return natives.computeIfAbsent(platform, p -> { //noinspection ConstantConditions try (Reader reader = new InputStreamReader(NativePatcher.class.getResourceAsStream("/assets/natives.json"), StandardCharsets.UTF_8)) { - Map> natives = JsonUtils.GSON.fromJson(reader, new TypeToken>>() { - }.getType()); - + Map> natives = JsonUtils.GSON.fromJson(reader, mapTypeOf(String.class, mapTypeOf(String.class, Library.class))); return natives.getOrDefault(p.toString(), Collections.emptyMap()); } catch (IOException e) { LOG.warning("Failed to load native library list", e); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java index cde4fcda0d..79efb38484 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java @@ -41,10 +41,9 @@ */ package org.jackhuang.hmcl.util; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.ui.SwingUtils; +import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.ChecksumMismatchException; import org.jackhuang.hmcl.util.io.IOUtils; import org.jackhuang.hmcl.util.io.JarUtils; @@ -68,6 +67,8 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.stream.Collectors.toSet; import static org.jackhuang.hmcl.Metadata.HMCL_DIRECTORY; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -104,11 +105,11 @@ private static final class DependencyDescriptor { private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies").resolve(Platform.getPlatform().toString()).resolve("openjfx"); static List readDependencies() { - ArrayList dependencies; + List dependencies; //noinspection ConstantConditions try (Reader reader = new InputStreamReader(SelfDependencyPatcher.class.getResourceAsStream(DEPENDENCIES_LIST_FILE), UTF_8)) { - Map> allDependencies = - new Gson().fromJson(reader, new TypeToken>>(){}.getType()); + Map> allDependencies = + JsonUtils.GSON.fromJson(reader, mapTypeOf(String.class, listTypeOf(DependencyDescriptor.class))); dependencies = allDependencies.get(Platform.getPlatform().toString()); } catch (IOException e) { throw new UncheckedIOException(e); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/YggdrasilServer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/YggdrasilServer.java index f3deed3d4f..7e722fa6bb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/YggdrasilServer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/YggdrasilServer.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.auth.offline; -import com.google.gson.reflect.TypeToken; import org.glavo.png.javafx.PNGJavaFXUtils; import org.jackhuang.hmcl.auth.yggdrasil.GameProfile; import org.jackhuang.hmcl.auth.yggdrasil.TextureModel; @@ -38,6 +37,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public class YggdrasilServer extends HttpServer { @@ -81,8 +81,7 @@ private Response status(Request request) { } private Response profiles(Request request) throws IOException { - List names = JsonUtils.fromNonNullJsonFully(request.getSession().getInputStream(), new TypeToken>() { - }.getType()); + List names = JsonUtils.fromNonNullJsonFully(request.getSession().getInputStream(), listTypeOf(String.class)); return ok(names.stream().distinct() .map(this::findCharacterByName) .flatMap(Lang::toStream) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java index 9837bc6791..8440f70b79 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.download.fabric; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -25,13 +24,13 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import static org.jackhuang.hmcl.util.Lang.wrap; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class FabricVersionList extends VersionList { private final DownloadProvider downloadProvider; @@ -69,8 +68,8 @@ public CompletableFuture refreshAsync() { private List getGameVersions(String metaUrl) throws IOException { String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl)); - return JsonUtils.GSON.>fromJson(json, new TypeToken>() { - }.getType()).stream().map(GameVersion::getVersion).collect(Collectors.toList()); + return JsonUtils.GSON.fromJson(json, listTypeOf(GameVersion.class)) + .stream().map(GameVersion::getVersion).collect(Collectors.toList()); } private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java index ef37315eee..c0d0fdc8b7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download.forge; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.Lang; @@ -40,6 +39,7 @@ import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Lang.wrap; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; import static org.jackhuang.hmcl.util.logging.Logger.LOG; public final class ForgeBMCLVersionList extends VersionList { @@ -87,11 +87,9 @@ public CompletableFuture refreshAsync(String gameVersion) { String lookupVersion = toLookupVersion(gameVersion); return CompletableFuture.completedFuture(null) - .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + lookupVersion).>getJson(new TypeToken>() { - }.getType()))) + .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + lookupVersion).getJson(listTypeOf(ForgeVersion.class)))) .thenAcceptAsync(forgeVersions -> { lock.writeLock().lock(); - try { versions.clear(gameVersion); if (forgeVersions == null) return; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloads.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloads.java index e549664676..cd1cf741cd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloads.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloads.java @@ -19,7 +19,6 @@ import com.google.gson.*; import com.google.gson.annotations.JsonAdapter; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.game.DownloadInfo; import org.jackhuang.hmcl.util.Immutable; @@ -27,6 +26,9 @@ import java.util.List; import java.util.Map; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; + @JsonAdapter(MojangJavaDownloads.Adapter.class) public class MojangJavaDownloads { @@ -49,8 +51,7 @@ public JsonElement serialize(MojangJavaDownloads src, Type typeOfSrc, JsonSerial @Override public MojangJavaDownloads deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return new MojangJavaDownloads(context.deserialize(json, new TypeToken>>>() { - }.getType())); + return new MojangJavaDownloads(context.deserialize(json, mapTypeOf(String.class, mapTypeOf(String.class, listTypeOf(JavaDownload.class))).getType())); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java index d1d8c83407..a00f2eaebc 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java @@ -19,18 +19,17 @@ import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.gson.Validation; import org.jackhuang.hmcl.util.io.HttpRequest; import java.util.Collections; -import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import static org.jackhuang.hmcl.util.Lang.wrap; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class NeoForgeBMCLVersionList extends VersionList { private final String apiRoot; @@ -68,8 +67,7 @@ public Optional getVersion(String gameVersion, String rem @Override public CompletableFuture refreshAsync(String gameVersion) { return CompletableFuture.completedFuture((Void) null) - .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/neoforge/list/" + gameVersion).>getJson(new TypeToken>() { - }.getType()))) + .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/neoforge/list/" + gameVersion).getJson(listTypeOf(NeoForgeVersion.class)))) .thenAcceptAsync(neoForgeVersions -> { lock.writeLock().lock(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java index af5f8b7546..5e9c368235 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download.optifine; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.HttpRequest; @@ -26,10 +25,11 @@ import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; + /** * @author huangyuhui */ @@ -72,8 +72,7 @@ private String toLookupVersion(String version) { @Override public CompletableFuture refreshAsync() { - return HttpRequest.GET(apiRoot + "/optifine/versionlist").>getJsonAsync(new TypeToken>() { - }.getType()).thenAcceptAsync(root -> { + return HttpRequest.GET(apiRoot + "/optifine/versionlist").getJsonAsync(listTypeOf(OptiFineVersion.class)).thenAcceptAsync(root -> { lock.writeLock().lock(); try { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java index bc7bf88041..f7d6a2e6b2 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.download.quilt; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -25,13 +24,13 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import static org.jackhuang.hmcl.util.Lang.wrap; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class QuiltVersionList extends VersionList { private final DownloadProvider downloadProvider; @@ -69,8 +68,8 @@ public CompletableFuture refreshAsync() { private List getGameVersions(String metaUrl) throws IOException { String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl)); - return JsonUtils.GSON.>fromJson(json, new TypeToken>() { - }.getType()).stream().map(GameVersion::getVersion).collect(Collectors.toList()); + return JsonUtils.GSON.fromJson(json, listTypeOf(GameVersion.class)) + .stream().map(GameVersion::getVersion).collect(Collectors.toList()); } private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java index 115b79c332..21c63c60ef 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.game; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.MaintainTask; import org.jackhuang.hmcl.download.game.VersionJsonSaveTask; import org.jackhuang.hmcl.event.*; @@ -499,18 +498,16 @@ public File getModpackConfiguration(String version) { * read modpack configuration for a version. * * @param version version installed as modpack - * @param manifest type of ModpackConfiguration * @return modpack configuration object, or null if this version is not a modpack. * @throws VersionNotFoundException if version does not exist. * @throws IOException if an i/o error occurs. */ @Nullable - public ModpackConfiguration readModpackConfiguration(String version) throws IOException, VersionNotFoundException { + public ModpackConfiguration readModpackConfiguration(String version) throws IOException, VersionNotFoundException { if (!hasVersion(version)) throw new VersionNotFoundException(version); File file = getModpackConfiguration(version); if (!file.exists()) return null; - return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken>() { - }.getType()); + return JsonUtils.GSON.fromJson(FileUtils.readText(file), ModpackConfiguration.class); } public boolean isModpack(String version) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/RuledArgument.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/RuledArgument.java index d812258c02..b55937f15b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/RuledArgument.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/RuledArgument.java @@ -19,13 +19,14 @@ import com.google.gson.*; import com.google.gson.annotations.JsonAdapter; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.util.Immutable; import java.lang.reflect.Type; import java.util.*; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; + /** * * @author huangyuhui @@ -86,8 +87,7 @@ public JsonElement serialize(RuledArgument src, Type typeOfSrc, JsonSerializatio public RuledArgument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject obj = json.getAsJsonObject(); - List rules = context.deserialize(obj.get("rules"), new TypeToken>() { - }.getType()); + List rules = context.deserialize(obj.get("rules"), listTypeOf(CompatibilityRule.class).getType()); JsonElement valuesElement; if (obj.has("values")) { @@ -102,8 +102,7 @@ public RuledArgument deserialize(JsonElement json, Type typeOfT, JsonDeserializa if (valuesElement.isJsonPrimitive()) { values = Collections.singletonList(valuesElement.getAsString()); } else { - values = context.deserialize(valuesElement, new TypeToken>() { - }.getType()); + values = context.deserialize(valuesElement, listTypeOf(String.class).getType()); } return new RuledArgument(rules, values); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java index e936db80d7..743f930454 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModpackConfiguration.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.mod; import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.gson.Validation; import org.jetbrains.annotations.Nullable; @@ -29,6 +30,11 @@ @Immutable public final class ModpackConfiguration implements Validation { + @SuppressWarnings("unchecked") + public static TypeToken> typeOf(Class clazz) { + return (TypeToken>) TypeToken.getParameterized(ModpackConfiguration.class, clazz); + } + private final T manifest; private final String type; private final String name; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseForgeRemoteModRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseForgeRemoteModRepository.java index 5bda19051e..3913ef7f0e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseForgeRemoteModRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseForgeRemoteModRepository.java @@ -38,6 +38,7 @@ import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class CurseForgeRemoteModRepository implements RemoteModRepository { @@ -113,8 +114,7 @@ public SearchResult search(String gameVersion, @Nullable RemoteModRepository.Cat pair("index", Integer.toString(pageOffset * pageSize)), pair("pageSize", Integer.toString(pageSize))) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>>() { - }.getType()); + .getJson(Response.typeOf(listTypeOf(CurseAddon.class))); if (searchFilter.isEmpty()) { return new SearchResult(response.getData().stream().map(CurseAddon::toMod), calculateTotalPages(response, pageSize)); } @@ -163,8 +163,7 @@ public Optional getRemoteVersionByLocalFile(LocalModFile loca Response response = HttpRequest.POST(PREFIX + "/v1/fingerprints/432") .json(mapOf(pair("fingerprints", Collections.singletonList(hash)))) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>() { - }.getType()); + .getJson(Response.typeOf(FingerprintMatchesResult.class)); if (response.getData().getExactMatches() == null || response.getData().getExactMatches().isEmpty()) { return Optional.empty(); @@ -177,8 +176,7 @@ public Optional getRemoteVersionByLocalFile(LocalModFile loca public RemoteMod getModById(String id) throws IOException { Response response = HttpRequest.GET(PREFIX + "/v1/mods/" + id) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>() { - }.getType()); + .getJson(Response.typeOf(CurseAddon.class)); return response.data.toMod(); } @@ -186,8 +184,7 @@ public RemoteMod getModById(String id) throws IOException { public RemoteMod.File getModFile(String modId, String fileId) throws IOException { Response response = HttpRequest.GET(String.format("%s/v1/mods/%s/files/%s", PREFIX, modId, fileId)) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>() { - }.getType()); + .getJson(Response.typeOf(CurseAddon.LatestFile.class)); return response.getData().toVersion().getFile(); } @@ -196,16 +193,14 @@ public Stream getRemoteVersionsById(String id) throws IOExcep Response> response = HttpRequest.GET(PREFIX + "/v1/mods/" + id + "/files", pair("pageSize", "10000")) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>>() { - }.getType()); + .getJson(Response.typeOf(listTypeOf(CurseAddon.LatestFile.class))); return response.getData().stream().map(CurseAddon.LatestFile::toVersion); } public List getCategoriesImpl() throws IOException { Response> categories = HttpRequest.GET(PREFIX + "/v1/categories", pair("gameId", "432")) .header("X-API-KEY", apiKey) - .getJson(new TypeToken>>() { - }.getType()); + .getJson(Response.typeOf(listTypeOf(CurseAddon.Category.class))); return reorganizeCategories(categories.getData(), section); } @@ -284,6 +279,17 @@ public int getTotalCount() { } public static class Response { + + @SuppressWarnings("unchecked") + public static TypeToken> typeOf(Class responseType) { + return (TypeToken>) TypeToken.getParameterized(Response.class, responseType); + } + + @SuppressWarnings("unchecked") + public static TypeToken> typeOf(TypeToken responseType) { + return (TypeToken>) TypeToken.getParameterized(Response.class, responseType.getType()); + } + private final T data; private final Pagination pagination; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java index 6796cf3308..b40618c689 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/curse/CurseInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.curse; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -99,8 +98,7 @@ public CurseInstallTask(DefaultDependencyManager dependencyManager, File zipFile ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(CurseManifest.class)); if (!CurseModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Curse modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackCompletionTask.java index 93be7eb009..1df44c1ea7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackCompletionTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.mcbbs; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.mod.ModManager; @@ -88,8 +87,7 @@ public CompletableFuture getFuture(TaskCompletableFuture executor) { if (configuration == null) { // Load configuration from disk try { - configuration = JsonUtils.fromNonNullJson(FileUtils.readText(configurationFile), new TypeToken>() { - }.getType()); + configuration = JsonUtils.fromNonNullJson(FileUtils.readText(configurationFile), ModpackConfiguration.typeOf(McbbsModpackManifest.class)); } catch (IOException | JsonParseException e) { throw new IOException("Malformed modpack configuration"); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackLocalInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackLocalInstallTask.java index 3cee33c603..7bd81ae526 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackLocalInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackLocalInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.mcbbs; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -80,8 +79,7 @@ public McbbsModpackLocalInstallTask(DefaultDependencyManager dependencyManager, ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(McbbsModpackManifest.class)); if (!McbbsModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Mcbbs modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackProvider.java index 2deaf72333..6a7ab07281 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackProvider.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.mcbbs; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; import org.jackhuang.hmcl.download.DefaultDependencyManager; @@ -56,8 +55,7 @@ public Task createUpdateTask(DefaultDependencyManager dependencyManager, Stri @Override public void injectLaunchOptions(String modpackConfigurationJson, LaunchOptions.Builder builder) { - ModpackConfiguration config = JsonUtils.GSON.fromJson(modpackConfigurationJson, new TypeToken>() { - }.getType()); + ModpackConfiguration config = JsonUtils.GSON.fromJson(modpackConfigurationJson, ModpackConfiguration.typeOf(McbbsModpackManifest.class)); if (!getName().equals(config.getType())) { throw new IllegalArgumentException("Incorrect manifest type, actual=" + config.getType() + ", expected=" + getName()); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackRemoteInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackRemoteInstallTask.java index 3e970980e6..4550273d8e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackRemoteInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackRemoteInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.mcbbs; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -66,8 +65,7 @@ public McbbsModpackRemoteInstallTask(DefaultDependencyManager dependencyManager, ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(McbbsModpackManifest.class)); if (!MODPACK_TYPE.equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Mcbbs modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeOldModMetadata.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeOldModMetadata.java index 067c5b8c25..78b673ece9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeOldModMetadata.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeOldModMetadata.java @@ -19,7 +19,6 @@ import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.mod.LocalModFile; import org.jackhuang.hmcl.mod.ModLoaderType; import org.jackhuang.hmcl.mod.ModManager; @@ -34,6 +33,8 @@ import java.nio.file.Path; import java.util.List; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; + /** * * @author huangyuhui @@ -125,9 +126,7 @@ public static LocalModFile fromFile(ModManager modManager, Path modFile, FileSys Path mcmod = fs.getPath("mcmod.info"); if (Files.notExists(mcmod)) throw new IOException("File " + modFile + " is not a Forge mod."); - List modList = JsonUtils.GSON.fromJson(FileUtils.readText(mcmod), - new TypeToken>() { - }.getType()); + List modList = JsonUtils.GSON.fromJson(FileUtils.readText(mcmod), listTypeOf(ForgeOldModMetadata.class)); if (modList == null || modList.isEmpty()) throw new IOException("Mod " + modFile + " `mcmod.info` is malformed.."); ForgeOldModMetadata metadata = modList.get(0); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthInstallTask.java index 64ccc7c2f6..b796413d4b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthInstallTask.java @@ -18,12 +18,10 @@ package org.jackhuang.hmcl.mod.modrinth; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.mod.*; -import org.jackhuang.hmcl.mod.curse.CurseManifest; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; @@ -95,8 +93,7 @@ public ModrinthInstallTask(DefaultDependencyManager dependencyManager, File zipF ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(ModrinthManifest.class)); if (!ModrinthModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Modrinth modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java index d20a542ac9..c257a38816 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java @@ -39,6 +39,7 @@ import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Pair.pair; +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class ModrinthRemoteModRepository implements RemoteModRepository { public static final ModrinthRemoteModRepository MODS = new ModrinthRemoteModRepository("mod"); @@ -93,8 +94,7 @@ public SearchResult search(String gameVersion, @Nullable RemoteModRepository.Cat pair("index", convertSortType(sort)) ); Response response = HttpRequest.GET(NetworkUtils.withQuery(PREFIX + "/v2/search", query)) - .getJson(new TypeToken>() { - }.getType()); + .getJson(Response.typeOf(ProjectSearchResult.class)); return new SearchResult(response.getHits().stream().map(ProjectSearchResult::toMod), (int) Math.ceil((double) response.totalHits / pageSize)); } @@ -132,13 +132,12 @@ public RemoteMod.File getModFile(String modId, String fileId) throws IOException public Stream getRemoteVersionsById(String id) throws IOException { id = StringUtils.removePrefix(id, "local-"); List versions = HttpRequest.GET(PREFIX + "/v2/project/" + id + "/version") - .getJson(new TypeToken>() { - }.getType()); + .getJson(listTypeOf(ProjectVersion.class)); return versions.stream().map(ProjectVersion::toVersion).flatMap(Lang::toStream); } public List getCategoriesImpl() throws IOException { - List categories = HttpRequest.GET(PREFIX + "/v2/tag/category").getJson(new TypeToken>() {}.getType()); + List categories = HttpRequest.GET(PREFIX + "/v2/tag/category").getJson(listTypeOf(Category.class)); return categories.stream().filter(category -> category.getProjectType().equals(projectType)).collect(Collectors.toList()); } @@ -696,6 +695,12 @@ public RemoteMod toMod() { } public static class Response { + + @SuppressWarnings("unchecked") + public static TypeToken> typeOf(Class responseType) { + return (TypeToken>) TypeToken.getParameterized(Response.class, responseType); + } + private final int offset; private final int limit; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java index 017f722445..973da7726e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.multimc; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.Arguments; @@ -128,8 +127,7 @@ public void preExecute() throws Exception { ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(MultiMCInstanceConfiguration.class)); if (!MultiMCModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a MultiMC modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java index 9f7ddfb95c..3130f24e0e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackCompletionTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.server; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -66,8 +65,7 @@ public ServerModpackCompletionTask(DefaultDependencyManager dependencyManager, S try { File manifestFile = repository.getModpackConfiguration(version); if (manifestFile.exists()) { - this.manifest = JsonUtils.GSON.fromJson(FileUtils.readText(manifestFile), new TypeToken>() { - }.getType()); + this.manifest = JsonUtils.GSON.fromJson(FileUtils.readText(manifestFile), ModpackConfiguration.typeOf(ServerModpackManifest.class)); } } catch (Exception e) { LOG.warning("Unable to read Server modpack manifest.json", e); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java index b23753f304..fec92572d3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackLocalInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.server; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -72,8 +71,7 @@ public ServerModpackLocalInstallTask(DefaultDependencyManager dependencyManager, ModpackConfiguration config = null; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(ServerModpackManifest.class)); if (!ServerModpackProvider.INSTANCE.getName().equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java index eddafb81ae..e6bb9b5565 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/server/ServerModpackRemoteInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.mod.server; import com.google.gson.JsonParseException; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.DefaultGameRepository; @@ -63,11 +62,10 @@ public ServerModpackRemoteInstallTask(DefaultDependencyManager dependencyManager repository.removeVersionFromDisk(name); }); - ModpackConfiguration config = null; + ModpackConfiguration config; try { if (json.exists()) { - config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken>() { - }.getType()); + config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(ServerModpackManifest.class)); if (!MODPACK_TYPE.equals(config.getType())) throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version."); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java index 89082d4cc5..223ff4d631 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CacheRepository.java @@ -19,9 +19,7 @@ import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.util.function.ExceptionalSupplier; -import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.IOUtils; @@ -46,6 +44,7 @@ import java.util.stream.Stream; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.jackhuang.hmcl.util.gson.JsonUtils.*; import static org.jackhuang.hmcl.util.logging.Logger.LOG; public class CacheRepository { @@ -68,7 +67,7 @@ public void changeDirectory(Path commonDir) { } if (Files.isRegularFile(indexFile)) { - ETagIndex raw = JsonUtils.GSON.fromJson(FileUtils.readText(indexFile), ETagIndex.class); + ETagIndex raw = GSON.fromJson(FileUtils.readText(indexFile), ETagIndex.class); if (raw == null) index = new HashMap<>(); else @@ -289,10 +288,10 @@ public void saveETagIndex() throws IOException { try (FileChannel channel = FileChannel.open(indexFile, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)) { FileLock lock = channel.lock(); try { - ETagIndex indexOnDisk = JsonUtils.fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), ETagIndex.class); + ETagIndex indexOnDisk = fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), ETagIndex.class); Map newIndex = joinETagIndexes(indexOnDisk == null ? null : indexOnDisk.eTag, index.values()); channel.truncate(0); - ByteBuffer writeTo = ByteBuffer.wrap(JsonUtils.GSON.toJson(new ETagIndex(newIndex.values())).getBytes(UTF_8)); + ByteBuffer writeTo = ByteBuffer.wrap(GSON.toJson(new ETagIndex(newIndex.values())).getBytes(UTF_8)); while (writeTo.hasRemaining()) { if (channel.write(writeTo) == 0) { throw new IOException("No value is written"); @@ -412,8 +411,7 @@ private void changeDirectory(Path cacheDirectory) { try { indexFile = cacheDirectory.resolve(name + ".json"); if (Files.isRegularFile(indexFile)) { - joinEntries(JsonUtils.fromNonNullJson(FileUtils.readText(indexFile), new TypeToken>() { - }.getType())); + joinEntries(fromNonNullJson(FileUtils.readText(indexFile), mapTypeOf(String.class, Object.class))); } } catch (IOException | JsonParseException e) { LOG.warning("Unable to read storage {" + name + "} file"); @@ -426,12 +424,11 @@ public void saveToFile() { try (FileChannel channel = FileChannel.open(indexFile, StandardOpenOption.READ, StandardOpenOption.WRITE)) { FileLock lock = channel.lock(); try { - Map indexOnDisk = JsonUtils.fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), new TypeToken>() { - }.getType()); + Map indexOnDisk = fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), mapTypeOf(String.class, Object.class)); if (indexOnDisk == null) indexOnDisk = new HashMap<>(); indexOnDisk.putAll(storage); channel.truncate(0); - channel.write(ByteBuffer.wrap(JsonUtils.GSON.toJson(storage).getBytes(UTF_8))); + channel.write(ByteBuffer.wrap(GSON.toJson(storage).getBytes(UTF_8))); this.storage = indexOnDisk; } finally { lock.release(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonUtils.java index bddf8d3f4a..bfd07080ac 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonUtils.java @@ -27,14 +27,16 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.time.Instant; +import java.util.List; +import java.util.Map; import java.util.UUID; /** * @author yushijinhun */ +@SuppressWarnings("unchecked") public final class JsonUtils { public static final Gson GSON = defaultGsonBuilder().create(); @@ -48,13 +50,29 @@ public final class JsonUtils { private JsonUtils() { } + public static TypeToken> listTypeOf(Class elementType) { + return (TypeToken>) TypeToken.getParameterized(List.class, elementType); + } + + public static TypeToken> listTypeOf(TypeToken elementType) { + return (TypeToken>) TypeToken.getParameterized(List.class, elementType.getType()); + } + + public static TypeToken> mapTypeOf(Class keyType, Class valueType) { + return (TypeToken>) TypeToken.getParameterized(Map.class, keyType, valueType); + } + + public static TypeToken> mapTypeOf(Class keyType, TypeToken valueType) { + return (TypeToken>) TypeToken.getParameterized(Map.class, keyType, valueType.getType()); + } + public static T fromJsonFully(InputStream json, Class classOfT) throws IOException, JsonParseException { try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) { return GSON.fromJson(reader, classOfT); } } - public static T fromJsonFully(InputStream json, Type type) throws IOException, JsonParseException { + public static T fromJsonFully(InputStream json, TypeToken type) throws IOException, JsonParseException { try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) { return GSON.fromJson(reader, type); } @@ -67,13 +85,6 @@ public static T fromNonNullJson(String json, Class classOfT) throws JsonP return parsed; } - public static T fromNonNullJson(String json, Type type) throws JsonParseException { - T parsed = GSON.fromJson(json, type); - if (parsed == null) - throw new JsonParseException("Json object cannot be null."); - return parsed; - } - public static T fromNonNullJson(String json, TypeToken type) throws JsonParseException { T parsed = GSON.fromJson(json, type); if (parsed == null) @@ -90,7 +101,7 @@ public static T fromNonNullJsonFully(InputStream json, Class classOfT) th } } - public static T fromNonNullJsonFully(InputStream json, Type type) throws IOException, JsonParseException { + public static T fromNonNullJsonFully(InputStream json, TypeToken type) throws IOException, JsonParseException { try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) { T parsed = GSON.fromJson(reader, type); if (parsed == null) @@ -107,7 +118,7 @@ public static T fromMaybeMalformedJson(String json, Class classOfT) throw } } - public static T fromMaybeMalformedJson(String json, Type type) throws JsonParseException { + public static T fromMaybeMalformedJson(String json, TypeToken type) throws JsonParseException { try { return GSON.fromJson(json, type); } catch (JsonSyntaxException e) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpRequest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpRequest.java index 29dd6d5046..4fb0fead5b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpRequest.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/HttpRequest.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.util.io; import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.util.Pair; import org.jackhuang.hmcl.util.function.ExceptionalBiConsumer; @@ -26,7 +27,6 @@ import java.io.IOException; import java.io.OutputStream; -import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; @@ -101,7 +101,7 @@ public T getJson(Class typeOfT) throws IOException, JsonParseException { return JsonUtils.fromNonNullJson(getString(), typeOfT); } - public T getJson(Type type) throws IOException, JsonParseException { + public T getJson(TypeToken type) throws IOException, JsonParseException { return JsonUtils.fromNonNullJson(getString(), type); } @@ -109,7 +109,7 @@ public CompletableFuture getJsonAsync(Class typeOfT) { return getStringAsync().thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, typeOfT)); } - public CompletableFuture getJsonAsync(Type type) { + public CompletableFuture getJsonAsync(TypeToken type) { return getStringAsync().thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, type)); } diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/gson/JsonUtilsTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/gson/JsonUtilsTest.java new file mode 100644 index 0000000000..a3f0aaeed6 --- /dev/null +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/gson/JsonUtilsTest.java @@ -0,0 +1,42 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2024 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.jackhuang.hmcl.util.gson; + +import com.google.gson.reflect.TypeToken; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; +import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Glavo + */ +public class JsonUtilsTest { + + @Test + public void testGetTypeToken() { + assertEquals(new TypeToken>(){}, listTypeOf(Object.class)); + assertEquals(new TypeToken>(){}, listTypeOf(String.class)); + assertEquals(new TypeToken>>(){}, listTypeOf(mapTypeOf(String.class, Integer.class))); + assertEquals(new TypeToken>>>(){}, listTypeOf(mapTypeOf(String.class, listTypeOf(Integer.class)))); + } +} From 1c864ba072b9da1cc856d18eedd8bd794bce1725 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 13 Oct 2024 19:19:52 +0800 Subject: [PATCH 007/169] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20Jsoup=20=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=B9=B6=E6=B8=B2=E6=9F=93=20HTML=20=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=20(#3321)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 50 ---- .../org/jackhuang/hmcl/ui/HTMLRenderer.java | 266 ++++++++++++++++++ .../org/jackhuang/hmcl/ui/UpgradeDialog.java | 89 +++--- .../java/org/jackhuang/hmcl/ui/WebPage.java | 74 +++++ .../java/org/jackhuang/hmcl/ui/WebStage.java | 72 ----- .../hmcl/ui/download/LocalModpackPage.java | 6 +- .../hmcl/ui/download/RemoteModpackPage.java | 4 +- .../jackhuang/hmcl/ui/wizard/WizardPage.java | 3 +- .../hmcl/util/SelfDependencyPatcher.java | 16 +- HMCL/src/main/resources/assets/css/root.css | 34 +++ .../resources/assets/lang/I18N.properties | 4 + .../resources/assets/lang/I18N_zh.properties | 4 + .../assets/lang/I18N_zh_CN.properties | 4 + HMCLCore/build.gradle.kts | 1 + javafx.gradle.kts | 21 +- 15 files changed, 456 insertions(+), 192 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/WebStage.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index cbedf9fb40..df712fe24a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -52,7 +52,6 @@ import org.glavo.png.PNGType; import org.glavo.png.PNGWriter; import org.glavo.png.javafx.PNGJavaFXUtils; -import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.animation.AnimationUtils; import org.jackhuang.hmcl.ui.construct.JFXHyperlink; @@ -70,12 +69,9 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; -import javax.swing.*; -import javax.swing.event.HyperlinkEvent; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import java.awt.*; import java.io.*; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; @@ -527,52 +523,6 @@ public static void openLink(String link) { }); } - public static void showWebDialog(String title, String content) { - showWebDialog(title, content, 800, 480); - } - - public static void showWebDialog(String title, String content, int width, int height) { - try { - WebStage stage = new WebStage(width, height); - stage.getWebView().getEngine().loadContent(content); - stage.setTitle(title); - stage.showAndWait(); - } catch (NoClassDefFoundError | UnsatisfiedLinkError e) { - LOG.warning("WebView is missing or initialization failed, use JEditorPane replaced", e); - - SwingUtils.initLookAndFeel(); - SwingUtilities.invokeLater(() -> { - final JFrame frame = new JFrame(title); - frame.setSize(width, height); - frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - frame.setLocationByPlatform(true); - frame.setIconImage(new ImageIcon(FXUtils.class.getResource("/assets/img/icon.png")).getImage()); - frame.setLayout(new BorderLayout()); - - final JProgressBar progressBar = new JProgressBar(); - progressBar.setIndeterminate(true); - frame.add(progressBar, BorderLayout.PAGE_START); - - Schedulers.defaultScheduler().execute(() -> { - final JEditorPane pane = new JEditorPane("text/html", content); - pane.setEditable(false); - pane.addHyperlinkListener(event -> { - if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - openLink(event.getURL().toExternalForm()); - } - }); - SwingUtilities.invokeLater(() -> { - progressBar.setVisible(false); - frame.add(new JScrollPane(pane), BorderLayout.CENTER); - }); - }); - - frame.setVisible(true); - frame.toFront(); - }); - } - } - public static void bind(JFXTextField textField, Property property, StringConverter converter) { textField.setText(converter == null ? (String) property.getValue() : converter.toString(property.getValue())); TextFieldBindingListener listener = new TextFieldBindingListener<>(textField, property, converter); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java new file mode 100644 index 0000000000..d311996a9e --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java @@ -0,0 +1,266 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2024 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.jackhuang.hmcl.ui; + +import javafx.scene.Cursor; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.text.Text; +import javafx.scene.text.TextFlow; +import org.jsoup.nodes.Node; +import org.jsoup.nodes.TextNode; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import static org.jackhuang.hmcl.util.logging.Logger.LOG; + +/** + * @author Glavo + */ +public final class HTMLRenderer { + private static URI resolveLink(Node linkNode) { + String href = linkNode.absUrl("href"); + if (href.isEmpty()) + return null; + + try { + return new URI(href); + } catch (Throwable e) { + return null; + } + } + + private final List children = new ArrayList<>(); + private final List stack = new ArrayList<>(); + + private boolean bold; + private boolean italic; + private boolean underline; + private boolean strike; + private boolean highlight; + private String headerLevel; + private Node hyperlink; + + private final Consumer onClickHyperlink; + + public HTMLRenderer(Consumer onClickHyperlink) { + this.onClickHyperlink = onClickHyperlink; + } + + private void updateStyle() { + bold = false; + italic = false; + underline = false; + strike = false; + highlight = false; + headerLevel = null; + hyperlink = null; + + for (Node node : stack) { + String nodeName = node.nodeName(); + switch (nodeName) { + case "b": + case "strong": + bold = true; + break; + case "i": + case "em": + italic = true; + break; + case "ins": + underline = true; + break; + case "del": + strike = true; + break; + case "mark": + highlight = true; + break; + case "a": + hyperlink = node; + break; + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + headerLevel = nodeName; + break; + } + } + } + + private void pushNode(Node node) { + stack.add(node); + updateStyle(); + } + + private void popNode() { + stack.remove(stack.size() - 1); + updateStyle(); + } + + private void applyStyle(Text text) { + if (hyperlink != null) { + URI target = resolveLink(hyperlink); + if (target != null) { + text.setOnMouseClicked(event -> onClickHyperlink.accept(target)); + text.setCursor(Cursor.HAND); + } + text.getStyleClass().add("html-hyperlink"); + } + + if (hyperlink != null || underline) + text.setUnderline(true); + + if (strike) + text.setStrikethrough(true); + + if (bold || highlight) + text.getStyleClass().add("html-bold"); + + if (italic) + text.getStyleClass().add("html-italic"); + + if (headerLevel != null) + text.getStyleClass().add("html-" + headerLevel); + } + + private void appendText(String text) { + Text textNode = new Text(text); + applyStyle(textNode); + children.add(textNode); + } + + private void appendImage(Node node) { + String src = node.absUrl("src"); + URI imageUri = null; + try { + if (!src.isEmpty()) + imageUri = URI.create(src); + } catch (Exception ignored) { + } + + String alt = node.attr("alt"); + + if (imageUri != null) { + URI uri = URI.create(src); + + String widthAttr = node.attr("width"); + String heightAttr = node.attr("height"); + + double width = 0; + double height = 0; + + if (!widthAttr.isEmpty() && !heightAttr.isEmpty()) { + try { + width = Double.parseDouble(widthAttr); + height = Double.parseDouble(heightAttr); + } catch (NumberFormatException ignored) { + } + + if (width <= 0 || height <= 0) { + width = 0; + height = 0; + } + } + + Image image = FXUtils.newRemoteImage(uri.toString(), width, height, true, true, false); + if (image.isError()) { + LOG.warning("Failed to load image: " + uri, image.getException()); + } else { + ImageView imageView = new ImageView(image); + if (hyperlink != null) { + URI target = resolveLink(hyperlink); + if (target != null) { + imageView.setOnMouseClicked(event -> onClickHyperlink.accept(target)); + imageView.setCursor(Cursor.HAND); + } + } + children.add(imageView); + return; + } + } + + if (!alt.isEmpty()) + appendText(alt); + } + + public void appendNode(Node node) { + if (node instanceof TextNode) { + appendText(((TextNode) node).text()); + } + + String name = node.nodeName(); + switch (name) { + case "img": + appendImage(node); + break; + case "li": + appendText("\n \u2022 "); + break; + case "dt": + appendText(" "); + break; + case "p": + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + case "tr": + if (!children.isEmpty()) + appendText("\n\n"); + break; + } + + if (node.childNodeSize() > 0) { + pushNode(node); + for (Node childNode : node.childNodes()) { + appendNode(childNode); + } + popNode(); + } + + switch (name) { + case "br": + case "dd": + case "p": + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + appendText("\n"); + break; + } + } + + public TextFlow render() { + TextFlow textFlow = new TextFlow(); + textFlow.getStyleClass().add("html"); + textFlow.getChildren().setAll(children); + return textFlow; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java index e8602e394d..e6b1e99255 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java @@ -19,58 +19,73 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXDialogLayout; -import javafx.concurrent.Worker; import javafx.scene.control.Label; -import javafx.scene.web.WebEngine; -import javafx.scene.web.WebView; -import org.jackhuang.hmcl.Metadata; +import javafx.scene.control.ProgressIndicator; +import javafx.scene.control.ScrollPane; +import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.construct.DialogCloseEvent; +import org.jackhuang.hmcl.ui.construct.JFXHyperlink; import org.jackhuang.hmcl.upgrade.RemoteVersion; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Node; +import java.io.IOException; +import java.net.URL; import static org.jackhuang.hmcl.Metadata.CHANGELOG_URL; import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; -import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; +import static org.jackhuang.hmcl.util.logging.Logger.LOG; -public class UpgradeDialog extends JFXDialogLayout { +public final class UpgradeDialog extends JFXDialogLayout { public UpgradeDialog(RemoteVersion remoteVersion, Runnable updateRunnable) { - { - setHeading(new Label(i18n("update.changelog"))); - } + setHeading(new Label(i18n("update.changelog"))); + setBody(new ProgressIndicator()); + + String url = CHANGELOG_URL + remoteVersion.getChannel().channelName + ".html"; + Task.supplyAsync(Schedulers.io(), () -> { + Document document = Jsoup.parse(new URL(url), 30 * 1000); + Node node = document.selectFirst("#nowchange"); + if (node == null) + throw new IOException("Cannot find #nowchange in document"); - { - String url = CHANGELOG_URL + remoteVersion.getChannel().channelName + ".html#nowchange"; - try { - WebView webView = new WebView(); - webView.getEngine().setUserDataDirectory(Metadata.HMCL_DIRECTORY.toFile()); - WebEngine engine = webView.getEngine(); - engine.load(url); - engine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> { - if (newValue == Worker.State.FAILED) { - LOG.warning("Failed to load update log, trying to open it in browser"); - FXUtils.openLink(url); - setBody(); - } - }); - setBody(webView); - } catch (NoClassDefFoundError | UnsatisfiedLinkError e) { - LOG.warning("WebView is missing or initialization failed", e); + HTMLRenderer renderer = new HTMLRenderer(uri -> { + LOG.info("Open link: " + uri); + FXUtils.openLink(uri.toString()); + }); + + do { + renderer.appendNode(node); + node = node.nextSibling(); + } while (node != null); + + return renderer.render(); + }).whenComplete(Schedulers.javafx(), (result, exception) -> { + if (exception == null) { + ScrollPane scrollPane = new ScrollPane(result); + scrollPane.setFitToWidth(true); + setBody(scrollPane); + } else { + LOG.warning("Failed to load update log, trying to open it in browser"); FXUtils.openLink(url); + setBody(); } - } + }).start(); + + JFXHyperlink openInBrowser = new JFXHyperlink(i18n("web.view_in_browser")); + openInBrowser.setExternalLink(url); - { - JFXButton updateButton = new JFXButton(i18n("update.accept")); - updateButton.getStyleClass().add("dialog-accept"); - updateButton.setOnMouseClicked(e -> updateRunnable.run()); + JFXButton updateButton = new JFXButton(i18n("update.accept")); + updateButton.getStyleClass().add("dialog-accept"); + updateButton.setOnAction(e -> updateRunnable.run()); - JFXButton cancelButton = new JFXButton(i18n("button.cancel")); - cancelButton.getStyleClass().add("dialog-cancel"); - cancelButton.setOnMouseClicked(e -> fireEvent(new DialogCloseEvent())); + JFXButton cancelButton = new JFXButton(i18n("button.cancel")); + cancelButton.getStyleClass().add("dialog-cancel"); + cancelButton.setOnAction(e -> fireEvent(new DialogCloseEvent())); - setActions(updateButton, cancelButton); - onEscPressed(this, cancelButton::fire); - } + setActions(openInBrowser, updateButton, cancelButton); + onEscPressed(this, cancelButton::fire); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java new file mode 100644 index 0000000000..7dca291e09 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java @@ -0,0 +1,74 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2024 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.jackhuang.hmcl.ui; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.Background; +import javafx.scene.paint.Color; +import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.ui.construct.SpinnerPane; +import org.jackhuang.hmcl.ui.decorator.DecoratorPage; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; + +import static org.jackhuang.hmcl.util.i18n.I18n.i18n; +import static org.jackhuang.hmcl.util.logging.Logger.LOG; + +/** + * @author Glavo + */ +public final class WebPage extends SpinnerPane implements DecoratorPage { + + private final ObjectProperty stateProperty; + + public WebPage(String title, String content) { + this.stateProperty = new SimpleObjectProperty<>(DecoratorPage.State.fromTitle(title)); + this.setBackground(Background.fill(Color.WHITE)); + + Task.supplyAsync(() -> { + Document document = Jsoup.parseBodyFragment(content); + HTMLRenderer renderer = new HTMLRenderer(uri -> { + Controllers.confirm(i18n("web.open_in_browser", uri), i18n("message.confirm"), () -> { + FXUtils.openLink(uri.toString()); + }, null); + }); + renderer.appendNode(document); + return renderer.render(); + }).whenComplete(Schedulers.javafx(), ((result, exception) -> { + if (exception == null) { + ScrollPane scrollPane = new ScrollPane(); + scrollPane.setFitToWidth(true); + scrollPane.setContent(result); + setContent(scrollPane); + setFailedReason(null); + } else { + LOG.warning("Failed to load content", exception); + setFailedReason(i18n("web.failed")); + } + })).start(); + } + + @Override + public ReadOnlyObjectProperty stateProperty() { + return stateProperty; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebStage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebStage.java deleted file mode 100644 index 1b57ca0aa3..0000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebStage.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.jackhuang.hmcl.ui; - -import com.jfoenix.controls.JFXProgressBar; -import javafx.beans.binding.Bindings; -import javafx.scene.Scene; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.StackPane; -import javafx.scene.web.WebEngine; -import javafx.scene.web.WebView; -import javafx.stage.Stage; -import org.jackhuang.hmcl.Metadata; -import org.jackhuang.hmcl.setting.Theme; - -import static org.jackhuang.hmcl.setting.ConfigHolder.config; - -public class WebStage extends Stage { - protected final StackPane pane = new StackPane(); - protected final JFXProgressBar progressBar = new JFXProgressBar(); - protected final WebView webView = new WebView(); - protected final WebEngine webEngine = webView.getEngine(); - - public WebStage() { - this(800, 480); - } - - public WebStage(int width, int height) { - setScene(new Scene(pane, width, height)); - getScene().getStylesheets().addAll(Theme.getTheme().getStylesheets(config().getLauncherFontFamily())); - FXUtils.setIcon(this); - webView.getEngine().setUserDataDirectory(Metadata.HMCL_DIRECTORY.toFile()); - webView.setContextMenuEnabled(false); - progressBar.progressProperty().bind(webView.getEngine().getLoadWorker().progressProperty()); - - progressBar.visibleProperty().bind(Bindings.createBooleanBinding(() -> { - switch (webView.getEngine().getLoadWorker().getState()) { - case SUCCEEDED: - case FAILED: - case CANCELLED: - return false; - default: - return true; - } - }, webEngine.getLoadWorker().stateProperty())); - - BorderPane borderPane = new BorderPane(); - borderPane.setPickOnBounds(false); - borderPane.setTop(progressBar); - progressBar.prefWidthProperty().bind(borderPane.widthProperty()); - pane.getChildren().setAll(webView, borderPane); - } - - public WebView getWebView() { - return webView; - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java index 54480e5524..4c71fd6eed 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java @@ -31,6 +31,7 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; +import org.jackhuang.hmcl.ui.WebPage; import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.ui.construct.RequiredValidator; import org.jackhuang.hmcl.ui.construct.Validator; @@ -153,9 +154,8 @@ protected void onInstall() { } protected void onDescribe() { - if (manifest != null) { - FXUtils.showWebDialog(i18n("modpack.description"), manifest.getDescription()); - } + if (manifest != null) + Controllers.navigate(new WebPage(i18n("modpack.description"), manifest.getDescription())); } public static final String MODPACK_FILE = "MODPACK_FILE"; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java index b38c663462..9f396efec1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java @@ -22,7 +22,7 @@ import org.jackhuang.hmcl.mod.server.ServerModpackManifest; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.ui.Controllers; -import org.jackhuang.hmcl.ui.FXUtils; +import org.jackhuang.hmcl.ui.WebPage; import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.ui.construct.RequiredValidator; import org.jackhuang.hmcl.ui.construct.Validator; @@ -84,7 +84,7 @@ protected void onInstall() { } protected void onDescribe() { - FXUtils.showWebDialog(i18n("modpack.description"), manifest.getDescription()); + Controllers.navigate(new WebPage(i18n("modpack.description"), manifest.getDescription())); } public static final String MODPACK_SERVER_MANIFEST = "MODPACK_SERVER_MANIFEST"; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardPage.java index cf5c2438b7..b9d04ba341 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardPage.java @@ -23,7 +23,8 @@ public interface WizardPage { default void onNavigate(Map settings) { } - void cleanup(Map settings); + default void cleanup(Map settings) { + } String getTitle(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java index 79efb38484..8d88115fde 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/SelfDependencyPatcher.java @@ -105,28 +105,14 @@ private static final class DependencyDescriptor { private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies").resolve(Platform.getPlatform().toString()).resolve("openjfx"); static List readDependencies() { - List dependencies; //noinspection ConstantConditions try (Reader reader = new InputStreamReader(SelfDependencyPatcher.class.getResourceAsStream(DEPENDENCIES_LIST_FILE), UTF_8)) { Map> allDependencies = JsonUtils.GSON.fromJson(reader, mapTypeOf(String.class, listTypeOf(DependencyDescriptor.class))); - dependencies = allDependencies.get(Platform.getPlatform().toString()); + return allDependencies.get(Platform.getPlatform().toString()); } catch (IOException e) { throw new UncheckedIOException(e); } - - if (dependencies == null) return null; - - try { - ClassLoader classLoader = SelfDependencyPatcher.class.getClassLoader(); - Class.forName("netscape.javascript.JSObject", false, classLoader); - Class.forName("org.w3c.dom.html.HTMLDocument", false, classLoader); - } catch (Throwable e) { - LOG.warning("Disable javafx.web because JRE is incomplete", e); - dependencies.removeIf(it -> "javafx.web".equals(it.module) || "javafx.media".equals(it.module)); - } - - return dependencies; } public String module; diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 36c589bbe3..ddb77d8122 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -1438,3 +1438,37 @@ .fit-width { -fx-pref-width: 100%; } + +/******************************************************************************* +* * +* HTML Renderer * +* * +*******************************************************************************/ + +.html { + -fx-font-size: 16; +} + +.html-hyperlink { + -fx-fill: blue; +} + +.html-h1 { + -fx-font-size: 22; +} + +.html-h2 { + -fx-font-size: 20; +} + +.html-h3 { + -fx-font-size: 18; +} + +.html-bold { + -fx-font-weight: bold; +} + +.html-italic { + -fx-font-style: italic; +} diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index c455bbff31..7c3098022d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -978,6 +978,10 @@ datapack.choose_datapack=Select a datapack to import datapack.extension=Datapack datapack.title=World %s - Datapacks +web.failed=Page loading failed +web.open_in_browser=Do you want to open this address in a browser:\n%s +web.view_in_browser=View in browser + world=Worlds world.add=Add a World (.zip) world.datapack=Manage Datapacks diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index bfbda91368..42d71bf8cf 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -847,6 +847,10 @@ datapack.choose_datapack=選擇要匯入的資料包壓縮檔 datapack.extension=資料包 datapack.title=世界 %s - 資料包 +web.failed=加載頁面失敗 +web.open_in_browser=是否要在瀏覽器中打開此連結:\n%s +web.view_in_browser=在瀏覽器中查看 + world=世界 world.add=加入世界 world.datapack=管理資料包 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 21090c4d4d..0d8202b402 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -846,6 +846,10 @@ datapack.choose_datapack=选择要导入的数据包压缩包 datapack.extension=数据包 datapack.title=世界 %s - 数据包 +web.failed=加载页面失败 +web.open_in_browser=是否要在浏览器中打开此链接:\n%s +web.view_in_browser=在浏览器中查看 + world=世界 world.add=添加世界 world.datapack=管理数据包 diff --git a/HMCLCore/build.gradle.kts b/HMCLCore/build.gradle.kts index c94473b502..e7c4b4ab57 100644 --- a/HMCLCore/build.gradle.kts +++ b/HMCLCore/build.gradle.kts @@ -12,5 +12,6 @@ dependencies { api("com.github.steveice10:opennbt:1.5") api("org.nanohttpd:nanohttpd:2.3.1") api("org.apache.commons:commons-compress:1.25.0") + api("org.jsoup:jsoup:1.18.1") compileOnlyApi("org.jetbrains:annotations:24.1.0") } diff --git a/javafx.gradle.kts b/javafx.gradle.kts index 734639eeb3..f64e36b974 100644 --- a/javafx.gradle.kts +++ b/javafx.gradle.kts @@ -14,11 +14,8 @@ data class Platform( val name: String, val classifier: String, val groupId: String = "org.openjfx", - val version: String = jfxVersion, - val unsupportedModules: List = listOf() + val version: String = jfxVersion ) { - val modules: List = jfxModules.filter { it !in unsupportedModules } - fun fileUrl( module: String, classifier: String, ext: String, repo: String = "https://repo1.maven.org/maven2" @@ -28,22 +25,22 @@ data class Platform( ).toURL() } -val jfxModules = listOf("base", "graphics", "controls", "media", "web") +val jfxModules = listOf("base", "graphics", "controls") val jfxMirrorRepos = listOf("https://mirrors.cloud.tencent.com/nexus/repository/maven-public") val jfxDependenciesFile = project("HMCL").layout.buildDirectory.file("openjfx-dependencies.json").get().asFile val jfxPlatforms = listOf( Platform("windows-x86", "win-x86"), Platform("windows-x86_64", "win"), - Platform("windows-arm64", "win", groupId = "org.glavo.hmcl.openjfx", version = "18.0.2+1-arm64", unsupportedModules = listOf("media", "web")), + Platform("windows-arm64", "win", groupId = "org.glavo.hmcl.openjfx", version = "18.0.2+1-arm64"), Platform("osx-x86_64", "mac"), Platform("osx-arm64", "mac-aarch64"), Platform("linux-x86_64", "linux"), - Platform("linux-arm32", "linux-arm32-monocle", unsupportedModules = listOf("media", "web")), + Platform("linux-arm32", "linux-arm32-monocle"), Platform("linux-arm64", "linux-aarch64"), Platform("linux-loongarch64", "linux", groupId = "org.glavo.hmcl.openjfx", version = "17.0.8-loongarch64"), - Platform("linux-loongarch64_ow", "linux", groupId = "org.glavo.hmcl.openjfx", version = "19-ea+10-loongson64", unsupportedModules = listOf("media", "web")), - Platform("linux-riscv64", "linux", groupId = "org.glavo.hmcl.openjfx", version = "19.0.2.1-riscv64", unsupportedModules = listOf("media", "web")), - Platform("freebsd-x86_64", "freebsd", groupId = "org.glavo.hmcl.openjfx", version = "14.0.2.1-freebsd", unsupportedModules = listOf("media", "web")), + Platform("linux-loongarch64_ow", "linux", groupId = "org.glavo.hmcl.openjfx", version = "19-ea+10-loongson64"), + Platform("linux-riscv64", "linux", groupId = "org.glavo.hmcl.openjfx", version = "19.0.2.1-riscv64"), + Platform("freebsd-x86_64", "freebsd", groupId = "org.glavo.hmcl.openjfx", version = "14.0.2.1-freebsd"), ) val jfxInClasspath = @@ -93,7 +90,7 @@ rootProject.tasks.create("generateOpenJFXDependencies") { doLast { val jfxDependencies = jfxPlatforms.associate { platform -> - platform.name to platform.modules.map { module -> + platform.name to jfxModules.map { module -> mapOf( "module" to "javafx.$module", "groupId" to platform.groupId, @@ -117,7 +114,7 @@ rootProject.tasks.create("preTouchOpenJFXDependencies") { doLast { for (repo in jfxMirrorRepos) { for (platform in jfxPlatforms) { - for (module in platform.modules) { + for (module in jfxModules) { val url = platform.fileUrl(module, platform.classifier, "jar", repo = repo) logger.quiet("Getting $url") try { From 65fc3d0c4f262bd6b484366f35887bc7cd6d31b1 Mon Sep 17 00:00:00 2001 From: YLDK <116365019+YELANDAOKONG@users.noreply.github.com> Date: Sun, 13 Oct 2024 19:29:02 +0800 Subject: [PATCH 008/169] =?UTF-8?q?Support=20#3087:=20=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E6=95=B4=E5=90=88=E5=8C=85=E6=96=87=E4=BB=B6=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=20(#3088)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Support #3087: 隐藏整合包文件位置显示 * Support #3087: 移除整合包文件位置显示代码 * Support #3087: 移除整合包文件位置显示代码 --- .../jackhuang/hmcl/ui/download/LocalModpackPage.java | 3 --- .../org/jackhuang/hmcl/ui/download/ModpackPage.java | 12 +----------- .../hmcl/ui/download/RemoteModpackPage.java | 1 - HMCL/src/main/resources/assets/lang/I18N.properties | 1 - .../main/resources/assets/lang/I18N_es.properties | 3 +-- .../main/resources/assets/lang/I18N_ja.properties | 1 - .../main/resources/assets/lang/I18N_ru.properties | 1 - .../main/resources/assets/lang/I18N_zh.properties | 1 - .../main/resources/assets/lang/I18N_zh_CN.properties | 1 - 9 files changed, 2 insertions(+), 22 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java index 4c71fd6eed..3b8525b06f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java @@ -108,7 +108,6 @@ public LocalModpackPage(WizardController controller) { hideSpinner(); lblName.setText(selectedFile.getName()); installAsVersion.set(false); - lblModpackLocation.setText(selectedFile.getAbsolutePath()); if (!name.isPresent()) { // trim: https://github.com/HMCL-dev/HMCL/issues/962 @@ -131,8 +130,6 @@ public LocalModpackPage(WizardController controller) { lblVersion.setText(manifest.getVersion()); lblAuthor.setText(manifest.getAuthor()); - lblModpackLocation.setText(selectedFile.getAbsolutePath()); - if (!name.isPresent()) { // trim: https://github.com/HMCL-dev/HMCL/issues/962 txtModpackName.setText(manifest.getName().trim()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java index 2240b5d18f..c54317e412 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java @@ -22,7 +22,6 @@ public abstract class ModpackPage extends SpinnerPane implements WizardPage { protected final Label lblName; protected final Label lblVersion; protected final Label lblAuthor; - protected final Label lblModpackLocation; protected final JFXTextField txtModpackName; protected final JFXButton btnInstall; @@ -37,15 +36,6 @@ protected ModpackPage(WizardController controller) { ComponentList componentList = new ComponentList(); { - BorderPane locationPane = new BorderPane(); - { - locationPane.setLeft(new Label(i18n("modpack.task.install.will"))); - - lblModpackLocation = new Label(); - BorderPane.setAlignment(lblModpackLocation, Pos.CENTER_RIGHT); - locationPane.setCenter(lblModpackLocation); - } - BorderPane archiveNamePane = new BorderPane(); { Label label = new Label(i18n("archive.file.name")); @@ -99,7 +89,7 @@ protected ModpackPage(WizardController controller) { } componentList.getContent().setAll( - locationPane, archiveNamePane, modpackNamePane, versionPane, authorPane, descriptionPane); + archiveNamePane, modpackNamePane, versionPane, authorPane, descriptionPane); } borderPane.getChildren().setAll(componentList); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java index 9f396efec1..b29583fd39 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java @@ -43,7 +43,6 @@ public RemoteModpackPage(WizardController controller) { manifest = tryCast(controller.getSettings().get(MODPACK_SERVER_MANIFEST), ServerModpackManifest.class) .orElseThrow(() -> new IllegalStateException("MODPACK_SERVER_MANIFEST should exist")); - lblModpackLocation.setText(manifest.getFileApi()); try { controller.getSettings().put(MODPACK_MANIFEST, manifest.toModpack(null)); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 7c3098022d..5f7e8bfe57 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -822,7 +822,6 @@ modpack.origin.mcbbs.prompt=Post ID modpack.scan=Parsing Modpack Index modpack.task.install=Import Modpack modpack.task.install.error=Unable to identify this modpack. We currently only support Curse, Modrinth, MultiMC, and MCBBS modpacks. -modpack.task.install.will=The location of the modpack you are going to install: modpack.type.curse=Curse modpack.type.curse.tolerable_error=Unable to download dependencies, you can try continuing to download by launching this game instance. modpack.type.curse.error=Unable to download dependencies, please try again or use a proxy connection. diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index e3c983843f..8cb9008479 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -731,8 +731,7 @@ modpack.origin.mcbbs=MCBBS modpack.origin.mcbbs.prompt=ID de publicación modpack.scan=Análisis del índice de modpacks modpack.task.install=Instalar Modpack -modpack.task.install.error=No se ha podido identificar este modpack. Actualmente sólo soportamos los modpacks Curse, Modrinth, MultiMC y MCBBS. -modpack.task.install.will=Vas a instalar el modpack: +modpack.task.install.error=No se ha podido identificar este modpack. Actualmente sólo soportamos los modpacks Curse, Modrinth, MultiMC y MCBBS. modpack.type.curse=Curse modpack.type.curse.tolerable_error=No se han podido descargar las dependencias, puedes intentar continuar la descarga ejecutando esta instancia del juego. modpack.type.curse.error=No se han podido descargar las dependencias de CurseForge, inténtalo de nuevo o utiliza una conexión proxy. diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 5aef7a0195..8e705640a9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -573,7 +573,6 @@ modpack.origin.mcbbs.prompt=スレッドID modpack.scan=このmodpackをスキャンしています modpack.task.install=Modpackのインポート modpack.task.install.error=このmodpackファイルは認識できません。CurseおよびMultiMCmodpackのみがサポートされています。 -modpack.task.install.will=modpackをインストールします: modpack.type.curse=Curse modpack.type.curse.completion=Cursemodpackに関連するファイルをインストールします modpack.type.curse.tolerable_error=このmodpackのすべてのファイルのダウンロードを完了できません。対応するゲームバージョンを開始するときに、ダウンロードを再試行できます。ネットワークの問題により、数回再試行する場合があります。 diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 1454eeb20b..36c792bf78 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -601,7 +601,6 @@ modpack.origin.mcbbs.prompt=ID записи modpack.scan=Разбор индекса модпака modpack.task.install=Установить модпак modpack.task.install.error=Не удаётся идентифицировать этот модпак. Поддерживаются только модпаки Curse, Modrinth, MultiMC и MCBBS. -modpack.task.install.will=Вы собираетесь установить модпак\: modpack.type.curse=Curse modpack.type.curse.completion=Установите файлы, связанные с модпаком Curse modpack.type.curse.tolerable_error=Мы не можем завершить скачивание всех файлов этого модпака. Вы можете повторить скачивание при запуске соответствующей версии игры. Вы можете повторить попытку несколько раз из-за проблем с сетью. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 42d71bf8cf..8373e0da19 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -702,7 +702,6 @@ modpack.origin.mcbbs.prompt=貼子 id modpack.scan=解析模組包 modpack.task.install=匯入模組包 modpack.task.install.error=無法識別該模組包,目前僅支援匯入 Curse、Modrinth、MultiMC、MCBBS 模組包。 -modpack.task.install.will=將會安裝模組包: modpack.type.curse=Curse modpack.type.curse.tolerable_error=但未能完成該模組包檔案的下載,您可以在啟動該遊戲版本時繼續該模組包檔案的下載。由於網路問題,您可能需要重試多次…… modpack.type.curse.error=無法完成該模組包所需的依賴下載,請多次重試或設定代理…… 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 0d8202b402..2f7bf89620 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -701,7 +701,6 @@ modpack.origin.mcbbs.prompt=贴子 id modpack.scan=解析整合包 modpack.task.install=导入整合包 modpack.task.install.error=无法识别该整合包,目前仅支持导入 Curse、Modrinth、MultiMC、MCBBS 整合包。\n你可以点击右上角帮助按钮进行求助。 -modpack.task.install.will=导入的整合包文件位置: modpack.type.curse=Curse modpack.type.curse.tolerable_error=但未能完成该整合包所需的依赖下载,您可以在启动该游戏版本时继续该整合包文件的下载。由于网络问题,您可能需要重试多次。\n你可以点击右上角帮助按钮进行求助。 modpack.type.curse.error=未能完成该整合包所需的依赖下载,请多次重试或设置代理。\n你可以点击右上角帮助按钮进行求助。 From 6265580d758a4f16b547b55942c606ab2e02c339 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sun, 13 Oct 2024 19:35:24 +0800 Subject: [PATCH 009/169] Adjust the order of sidebars in instance settings (#3278) --- .../hmcl/ui/versions/VersionPage.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java index bb328b7eaf..e5ed85a480 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java @@ -56,8 +56,8 @@ public class VersionPage extends DecoratorAnimatedPage implements DecoratorPage private final ReadOnlyObjectWrapper state = new ReadOnlyObjectWrapper<>(); private final TabHeader tab; private final TabHeader.Tab versionSettingsTab = new TabHeader.Tab<>("versionSettingsTab"); - private final TabHeader.Tab modListTab = new TabHeader.Tab<>("modListTab"); private final TabHeader.Tab installerListTab = new TabHeader.Tab<>("installerListTab"); + private final TabHeader.Tab modListTab = new TabHeader.Tab<>("modListTab"); private final TabHeader.Tab worldListTab = new TabHeader.Tab<>("worldList"); private final TransitionPane transitionPane = new TransitionPane(); private final BooleanProperty currentVersionUpgradable = new SimpleBooleanProperty(); @@ -68,11 +68,11 @@ public class VersionPage extends DecoratorAnimatedPage implements DecoratorPage { versionSettingsTab.setNodeSupplier(loadVersionFor(() -> new VersionSettingsPage(false))); - modListTab.setNodeSupplier(loadVersionFor(ModListPage::new)); installerListTab.setNodeSupplier(loadVersionFor(InstallerListPage::new)); + modListTab.setNodeSupplier(loadVersionFor(ModListPage::new)); worldListTab.setNodeSupplier(loadVersionFor(WorldListPage::new)); - tab = new TabHeader(versionSettingsTab, modListTab, installerListTab, worldListTab); + tab = new TabHeader(versionSettingsTab, installerListTab, modListTab, worldListTab); addEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onNavigated); @@ -128,10 +128,10 @@ public void loadVersion(String version, Profile profile) { if (versionSettingsTab.isInitialized()) versionSettingsTab.getNode().loadVersion(profile, version); - if (modListTab.isInitialized()) - modListTab.getNode().loadVersion(profile, version); if (installerListTab.isInitialized()) installerListTab.getNode().loadVersion(profile, version); + if (modListTab.isInitialized()) + modListTab.getNode().loadVersion(profile, version); if (worldListTab.isInitialized()) worldListTab.getNode().loadVersion(profile, version); currentVersionUpgradable.set(profile.getRepository().isModpack(version)); @@ -247,15 +247,6 @@ protected Skin(VersionPage control) { runInFX(() -> FXUtils.installFastTooltip(versionSettingsItem, i18n("settings.game"))); versionSettingsItem.setOnAction(e -> control.tab.select(control.versionSettingsTab)); - AdvancedListItem modListItem = new AdvancedListItem(); - modListItem.getStyleClass().add("navigation-drawer-item"); - modListItem.setTitle(i18n("mods.manage")); - modListItem.setLeftGraphic(wrap(SVG.PUZZLE)); - modListItem.setActionButtonVisible(false); - modListItem.activeProperty().bind(control.tab.getSelectionModel().selectedItemProperty().isEqualTo(control.modListTab)); - runInFX(() -> FXUtils.installFastTooltip(modListItem, i18n("mods.manage"))); - modListItem.setOnAction(e -> control.tab.select(control.modListTab)); - AdvancedListItem installerListItem = new AdvancedListItem(); installerListItem.getStyleClass().add("navigation-drawer-item"); installerListItem.setTitle(i18n("settings.tabs.installers")); @@ -265,6 +256,15 @@ protected Skin(VersionPage control) { runInFX(() -> FXUtils.installFastTooltip(installerListItem, i18n("settings.tabs.installers"))); installerListItem.setOnAction(e -> control.tab.select(control.installerListTab)); + AdvancedListItem modListItem = new AdvancedListItem(); + modListItem.getStyleClass().add("navigation-drawer-item"); + modListItem.setTitle(i18n("mods.manage")); + modListItem.setLeftGraphic(wrap(SVG.PUZZLE)); + modListItem.setActionButtonVisible(false); + modListItem.activeProperty().bind(control.tab.getSelectionModel().selectedItemProperty().isEqualTo(control.modListTab)); + runInFX(() -> FXUtils.installFastTooltip(modListItem, i18n("mods.manage"))); + modListItem.setOnAction(e -> control.tab.select(control.modListTab)); + AdvancedListItem worldListItem = new AdvancedListItem(); worldListItem.getStyleClass().add("navigation-drawer-item"); worldListItem.setTitle(i18n("world.manage")); @@ -276,8 +276,8 @@ protected Skin(VersionPage control) { AdvancedListBox sideBar = new AdvancedListBox() .add(versionSettingsItem) - .add(modListItem) .add(installerListItem) + .add(modListItem) .add(worldListItem); VBox.setVgrow(sideBar, Priority.ALWAYS); From c3917082ee20a241a79da13ab8e603d90386c758 Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Sun, 13 Oct 2024 19:37:35 +0800 Subject: [PATCH 010/169] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=93=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E5=99=A8=E6=97=A5=E5=BF=97=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=B9=E6=8C=89=E9=92=AE=20(#3237)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加打开启动器日志文件夹 * Update HMCL/src/main/resources/assets/lang/I18N.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> * Update HMCL/src/main/resources/assets/lang/I18N_zh.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> * Update HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> * Update HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> --------- Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> --- .../org/jackhuang/hmcl/ui/main/SettingsView.java | 16 +++++++++++++++- .../main/resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../resources/assets/lang/I18N_zh_CN.properties | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java index 39bd0ae17f..8995e19498 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java @@ -30,6 +30,7 @@ import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; import javafx.scene.text.TextFlow; +import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.setting.EnumCommonDirectory; import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.FXUtils; @@ -191,10 +192,19 @@ public SettingsView() { BorderPane.setAlignment(left, Pos.CENTER_LEFT); debugPane.setLeft(left); + JFXButton openLogFolderButton = new JFXButton(i18n("settings.launcher.launcher_log.reveal")); + openLogFolderButton.setOnMouseClicked(e -> openLogFolder()); + openLogFolderButton.getStyleClass().add("jfx-button-border"); + JFXButton logButton = new JFXButton(i18n("settings.launcher.launcher_log.export")); logButton.setOnMouseClicked(e -> onExportLogs()); logButton.getStyleClass().add("jfx-button-border"); - debugPane.setRight(logButton); + + HBox buttonBox = new HBox(); + buttonBox.setSpacing(10); + buttonBox.getChildren().addAll(openLogFolderButton, logButton); + BorderPane.setAlignment(buttonBox, Pos.CENTER_RIGHT); + debugPane.setRight(buttonBox); settingsPane.getContent().add(debugPane); } @@ -205,6 +215,10 @@ public SettingsView() { } } + public void openLogFolder() { + FXUtils.openFolder(Metadata.HMCL_DIRECTORY.resolve("logs").toFile()); + } + protected abstract void onUpdate(); protected abstract void onExportLogs(); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 5f7e8bfe57..14eb8e13e3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1183,6 +1183,7 @@ settings.launcher.font=Font settings.launcher.general=General settings.launcher.language=Language (applies after restart) settings.launcher.launcher_log.export=Export launcher logs +settings.launcher.launcher_log.reveal=Reveal Logs in Explorer settings.launcher.launcher_log.export.failed=Unable to export logs settings.launcher.launcher_log.export.success=Logs have been exported to %s settings.launcher.log=Logging diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 8373e0da19..78971778f5 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1042,6 +1042,7 @@ settings.launcher.font=字體 settings.launcher.general=通用 settings.launcher.language=語言 (重啟後生效) settings.launcher.launcher_log.export=匯出啟動器日誌 +settings.launcher.launcher_log.reveal=打開日誌目錄 settings.launcher.launcher_log.export.failed=無法匯出日誌 settings.launcher.launcher_log.export.success=日誌已儲存到 %s settings.launcher.log=記錄 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 2f7bf89620..945552efaf 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1041,6 +1041,7 @@ settings.launcher.font=字体 settings.launcher.general=通用 settings.launcher.language=语言 (重启后生效) settings.launcher.launcher_log.export=导出启动器日志 +settings.launcher.launcher_log.reveal=打开日志目录 settings.launcher.launcher_log.export.failed=无法导出日志 settings.launcher.launcher_log.export.success=日志已保存到 %s settings.launcher.log=日志 From e9c3795ffc9dd7e501c6791f388101d8a4fc005e Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 13 Oct 2024 19:52:00 +0800 Subject: [PATCH 011/169] =?UTF-8?q?=E9=A2=84=E7=94=9F=E6=88=90=20openjfx-d?= =?UTF-8?q?ependencies.json=20(#3322)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/build.gradle.kts | 5 - .../assets/openjfx-dependencies.json | 314 ++++++++++++++++++ javafx.gradle.kts | 4 +- 3 files changed, 315 insertions(+), 8 deletions(-) create mode 100644 HMCL/src/main/resources/assets/openjfx-dependencies.json diff --git a/HMCL/build.gradle.kts b/HMCL/build.gradle.kts index 25b2687df0..3374bb3fe6 100644 --- a/HMCL/build.gradle.kts +++ b/HMCL/build.gradle.kts @@ -189,11 +189,6 @@ tasks.processResources { from(sourceSets["java11"].output) } dependsOn(tasks["java11Classes"]) - - into("assets") { - from(project.layout.buildDirectory.file("openjfx-dependencies.json")) - } - dependsOn(rootProject.tasks["generateOpenJFXDependencies"]) } val makeExecutables = tasks.create("makeExecutables") { diff --git a/HMCL/src/main/resources/assets/openjfx-dependencies.json b/HMCL/src/main/resources/assets/openjfx-dependencies.json new file mode 100644 index 0000000000..728d293332 --- /dev/null +++ b/HMCL/src/main/resources/assets/openjfx-dependencies.json @@ -0,0 +1,314 @@ +{ + "windows-x86": [ + { + "module": "javafx.base", + "groupId": "org.openjfx", + "artifactId": "javafx-base", + "version": "19.0.2.1", + "classifier": "win-x86", + "sha1": "6c9ebafc7f9c4544d72fa5e306f4111e56b5db58" + }, + { + "module": "javafx.graphics", + "groupId": "org.openjfx", + "artifactId": "javafx-graphics", + "version": "19.0.2.1", + "classifier": "win-x86", + "sha1": "a14a1fbe3a0dca81d99c53fd7be8e7c784a68afe" + }, + { + "module": "javafx.controls", + "groupId": "org.openjfx", + "artifactId": "javafx-controls", + "version": "19.0.2.1", + "classifier": "win-x86", + "sha1": "7df1501701f9e9fbadab8ce55ef1dde128e2e88a" + } + ], + "windows-x86_64": [ + { + "module": "javafx.base", + "groupId": "org.openjfx", + "artifactId": "javafx-base", + "version": "19.0.2.1", + "classifier": "win", + "sha1": "f33d0776b2b027c2ea9267c184f9048ef94c4deb" + }, + { + "module": "javafx.graphics", + "groupId": "org.openjfx", + "artifactId": "javafx-graphics", + "version": "19.0.2.1", + "classifier": "win", + "sha1": "951ca77bd50ef4fd44f4b7fb1e38301088fde4e2" + }, + { + "module": "javafx.controls", + "groupId": "org.openjfx", + "artifactId": "javafx-controls", + "version": "19.0.2.1", + "classifier": "win", + "sha1": "78ac7de48d0aac48e7d5282efc81bab7f337b587" + } + ], + "windows-arm64": [ + { + "module": "javafx.base", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-base", + "version": "18.0.2+1-arm64", + "classifier": "win", + "sha1": "4518a696b9d509dc09a7fe283452fce84a1686a8" + }, + { + "module": "javafx.graphics", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-graphics", + "version": "18.0.2+1-arm64", + "classifier": "win", + "sha1": "e19ba9aefc4bba8ff86dcdf416620b93b7bdea39" + }, + { + "module": "javafx.controls", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-controls", + "version": "18.0.2+1-arm64", + "classifier": "win", + "sha1": "0bf7380823bb8c420dd41837d2c71087b8953ec1" + } + ], + "osx-x86_64": [ + { + "module": "javafx.base", + "groupId": "org.openjfx", + "artifactId": "javafx-base", + "version": "19.0.2.1", + "classifier": "mac", + "sha1": "73e422d8426aaa23e8c712b9f4d9bebf70d3bfb9" + }, + { + "module": "javafx.graphics", + "groupId": "org.openjfx", + "artifactId": "javafx-graphics", + "version": "19.0.2.1", + "classifier": "mac", + "sha1": "6ab6f3e23421fcfa04e692d9d26a8f55a830c114" + }, + { + "module": "javafx.controls", + "groupId": "org.openjfx", + "artifactId": "javafx-controls", + "version": "19.0.2.1", + "classifier": "mac", + "sha1": "b7786b1b63e741c0e234829825fae5fef9d96c31" + } + ], + "osx-arm64": [ + { + "module": "javafx.base", + "groupId": "org.openjfx", + "artifactId": "javafx-base", + "version": "19.0.2.1", + "classifier": "mac-aarch64", + "sha1": "1d0d887c492330ed527b0614d115a4f32d2d05a4" + }, + { + "module": "javafx.graphics", + "groupId": "org.openjfx", + "artifactId": "javafx-graphics", + "version": "19.0.2.1", + "classifier": "mac-aarch64", + "sha1": "64db28799e61e0f8f51e471c732599b2a6961803" + }, + { + "module": "javafx.controls", + "groupId": "org.openjfx", + "artifactId": "javafx-controls", + "version": "19.0.2.1", + "classifier": "mac-aarch64", + "sha1": "3a14bd5f3ebe45d344c1f2bade0fe074e6ea2a83" + } + ], + "linux-x86_64": [ + { + "module": "javafx.base", + "groupId": "org.openjfx", + "artifactId": "javafx-base", + "version": "19.0.2.1", + "classifier": "linux", + "sha1": "9e4ca5ce2b87c479d2cc445ff411a48aeae76936" + }, + { + "module": "javafx.graphics", + "groupId": "org.openjfx", + "artifactId": "javafx-graphics", + "version": "19.0.2.1", + "classifier": "linux", + "sha1": "27c64e4e1569ddf198f28eda84cf8d014ab80693" + }, + { + "module": "javafx.controls", + "groupId": "org.openjfx", + "artifactId": "javafx-controls", + "version": "19.0.2.1", + "classifier": "linux", + "sha1": "b5b2a8ead40bd43476740aa51697bb1cac23de5c" + } + ], + "linux-arm32": [ + { + "module": "javafx.base", + "groupId": "org.openjfx", + "artifactId": "javafx-base", + "version": "19.0.2.1", + "classifier": "linux-arm32-monocle", + "sha1": "452f455d6948788c1e5350a41259eb8101d3f82a" + }, + { + "module": "javafx.graphics", + "groupId": "org.openjfx", + "artifactId": "javafx-graphics", + "version": "19.0.2.1", + "classifier": "linux-arm32-monocle", + "sha1": "b45b33252e88263fe80a462a45828b4562c3c709" + }, + { + "module": "javafx.controls", + "groupId": "org.openjfx", + "artifactId": "javafx-controls", + "version": "19.0.2.1", + "classifier": "linux-arm32-monocle", + "sha1": "e606c619fc493ecd18d281b0ded3aa38ba15a9e5" + } + ], + "linux-arm64": [ + { + "module": "javafx.base", + "groupId": "org.openjfx", + "artifactId": "javafx-base", + "version": "19.0.2.1", + "classifier": "linux-aarch64", + "sha1": "1490bfe619e148b3d58746d43f549d697640c935" + }, + { + "module": "javafx.graphics", + "groupId": "org.openjfx", + "artifactId": "javafx-graphics", + "version": "19.0.2.1", + "classifier": "linux-aarch64", + "sha1": "cad8004a87f57d9813c52985894ef15e8011baee" + }, + { + "module": "javafx.controls", + "groupId": "org.openjfx", + "artifactId": "javafx-controls", + "version": "19.0.2.1", + "classifier": "linux-aarch64", + "sha1": "ccc33fc1fcbf46130346f4330d6d70b71bdec7d0" + } + ], + "linux-loongarch64": [ + { + "module": "javafx.base", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-base", + "version": "17.0.8-loongarch64", + "classifier": "linux", + "sha1": "9d692dfc79eb334a7b4bae922aa57cb3a437345e" + }, + { + "module": "javafx.graphics", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-graphics", + "version": "17.0.8-loongarch64", + "classifier": "linux", + "sha1": "7f241dc6adc8beddb776f453a3c63a5848d7b90b" + }, + { + "module": "javafx.controls", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-controls", + "version": "17.0.8-loongarch64", + "classifier": "linux", + "sha1": "1c8b0141bec93ed21d7c0e9a2f69a1c7e3c734d2" + } + ], + "linux-loongarch64_ow": [ + { + "module": "javafx.base", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-base", + "version": "19-ea+10-loongson64", + "classifier": "linux", + "sha1": "f90663ba93aef9f818236ce19ecfa33dca0ffe10" + }, + { + "module": "javafx.graphics", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-graphics", + "version": "19-ea+10-loongson64", + "classifier": "linux", + "sha1": "6ff76304d08bba093abfe7f4d50ce6a49279c87f" + }, + { + "module": "javafx.controls", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-controls", + "version": "19-ea+10-loongson64", + "classifier": "linux", + "sha1": "8a16096d42de70f2548f18840cdcd49a07fc1654" + } + ], + "linux-riscv64": [ + { + "module": "javafx.base", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-base", + "version": "19.0.2.1-riscv64", + "classifier": "linux", + "sha1": "e33c7e0bac2931a8f7a752bb74e4e4e535eec4ad" + }, + { + "module": "javafx.graphics", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-graphics", + "version": "19.0.2.1-riscv64", + "classifier": "linux", + "sha1": "ac4e5edd55d84da80f8fc2d81a4c9994296a6c09" + }, + { + "module": "javafx.controls", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-controls", + "version": "19.0.2.1-riscv64", + "classifier": "linux", + "sha1": "efe6a87ea24972d45f1931528f87e64a53bd2232" + } + ], + "freebsd-x86_64": [ + { + "module": "javafx.base", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-base", + "version": "14.0.2.1-freebsd", + "classifier": "freebsd", + "sha1": "7bac900f0ab0d4d6dcf178252cf37ee1e0470d40" + }, + { + "module": "javafx.graphics", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-graphics", + "version": "14.0.2.1-freebsd", + "classifier": "freebsd", + "sha1": "7773ce02d1dc29160801e4e077ed2a26e93bed13" + }, + { + "module": "javafx.controls", + "groupId": "org.glavo.hmcl.openjfx", + "artifactId": "javafx-controls", + "version": "14.0.2.1-freebsd", + "classifier": "freebsd", + "sha1": "34a3dd3ccbc898bacfdcb3256cfb87ddc50621d3" + } + ] +} \ No newline at end of file diff --git a/javafx.gradle.kts b/javafx.gradle.kts index f64e36b974..ac94aca785 100644 --- a/javafx.gradle.kts +++ b/javafx.gradle.kts @@ -27,7 +27,7 @@ data class Platform( val jfxModules = listOf("base", "graphics", "controls") val jfxMirrorRepos = listOf("https://mirrors.cloud.tencent.com/nexus/repository/maven-public") -val jfxDependenciesFile = project("HMCL").layout.buildDirectory.file("openjfx-dependencies.json").get().asFile +val jfxDependenciesFile = project.file("HMCL/src/main/resources/assets/openjfx-dependencies.json") val jfxPlatforms = listOf( Platform("windows-x86", "win-x86"), Platform("windows-x86_64", "win"), @@ -86,8 +86,6 @@ if (!jfxInClasspath && JavaVersion.current() >= JavaVersion.VERSION_11) { } rootProject.tasks.create("generateOpenJFXDependencies") { - outputs.file(jfxDependenciesFile) - doLast { val jfxDependencies = jfxPlatforms.associate { platform -> platform.name to jfxModules.map { module -> From 1c05cd981f6d4bf485ac0a758126f55263d59bbf Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 13 Oct 2024 20:20:05 +0800 Subject: [PATCH 012/169] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20./gradlew=20run=20?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=20HMCL=20=E6=97=B6=E8=A7=A3=E6=9E=90=20HMCL?= =?UTF-8?q?=5FJAVA=5FOPTS=20=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F=20(#3323)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/build.gradle.kts | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/HMCL/build.gradle.kts b/HMCL/build.gradle.kts index 3374bb3fe6..5c42b7814f 100644 --- a/HMCL/build.gradle.kts +++ b/HMCL/build.gradle.kts @@ -203,6 +203,56 @@ tasks.build { dependsOn(makeExecutables) } +fun parseToolOptions(options: String?): List { + if (options == null) + return listOf() + + val builder = StringBuilder() + val result = mutableListOf() + + var offset = 0 + + loop@ while (offset < options.length) { + val ch = options[offset] + if (Character.isWhitespace(ch)) { + if (builder.isNotEmpty()) { + result += builder.toString() + builder.clear() + } + + while (offset < options.length && Character.isWhitespace(options[offset])) { + offset++ + } + + continue@loop + } + + if (ch == '\'' || ch == '"') { + offset++ + + while (offset < options.length) { + val ch2 = options[offset++] + if (ch2 != ch) { + builder.append(ch2) + } else { + continue@loop + } + } + + throw GradleException("Unmatched quote in $options") + } + + builder.append(ch) + offset++ + } + + if (builder.isNotEmpty()) { + result += builder.toString() + } + + return result +} + tasks.create("run") { dependsOn(tasks.jar) @@ -210,4 +260,11 @@ tasks.create("run") { classpath = files(jarPath) workingDir = rootProject.rootDir + + val vmOptions = parseToolOptions(System.getenv("HMCL_JAVA_OPTS")) + jvmArgs(vmOptions) + + doFirst { + logger.quiet("HMCL_JAVA_OPTS: $vmOptions") + } } From 17c1998119a87aaedf0dfa229fe0c640d62c4bbb Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 13 Oct 2024 20:39:55 +0800 Subject: [PATCH 013/169] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=A1=86=E6=A0=87=E9=A2=98=E5=92=8C=E6=8C=89=E9=92=AE=E6=9C=AA?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E8=87=AA=E5=AE=9A=E4=B9=89=E5=AD=97=E4=BD=93?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=20(#3324)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/resources/assets/css/root.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index ddb77d8122..6ee1010484 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -431,7 +431,6 @@ .jfx-layout-heading { -fx-font-size: 20.0px; - -fx-font-family: -fx-base-font-family; -fx-alignment: center-left; -fx-padding: 5.0 0.0 5.0 0.0; } @@ -449,18 +448,15 @@ .dialog-error { -fx-text-fill: #d32f2f; - -fx-font-family: -fx-base-font-family; -fx-padding: 0.7em 0.8em; } .dialog-accept { -fx-text-fill: #03A9F4; - -fx-font-family: -fx-base-font-family; -fx-padding: 0.7em 0.8em; } .dialog-cancel { - -fx-font-family: -fx-base-font-family; -fx-padding: 0.7em 0.8em; } From 00b7085370f85ca62e07b06cddbc525aa29b2583 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 13 Oct 2024 20:54:15 +0800 Subject: [PATCH 014/169] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20Linux=20LoongArch6?= =?UTF-8?q?4=20=E6=94=AF=E6=8C=81=20(#3264)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/resources/assets/natives.json | 220 ++++++++++++++++++++ PLATFORM.md | 23 +- PLATFORM_cn.md | 23 +- 3 files changed, 244 insertions(+), 22 deletions(-) diff --git a/HMCL/src/main/resources/assets/natives.json b/HMCL/src/main/resources/assets/natives.json index 558d2bd3e2..7f4f6eaaff 100644 --- a/HMCL/src/main/resources/assets/natives.json +++ b/HMCL/src/main/resources/assets/natives.json @@ -2265,6 +2265,226 @@ "org.lwjgl:lwjgl-glfw:3.3.1:natives-linux": null, "org.lwjgl:lwjgl-stb:3.3.1:natives-linux": null, "org.lwjgl:lwjgl-tinyfd:3.3.1:natives-linux": null, + "org.lwjgl:lwjgl:3.3.2": { + "name": "org.lwjgl:lwjgl:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl/3.3.4/lwjgl-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl/3.3.4/lwjgl-3.3.4.jar", + "sha1": "b86c3e4832426e8a6b466013b7cb34b40e9ce956", + "size": 800127 + } + } + }, + "org.lwjgl:lwjgl:3.3.2:natives-linux": { + "name": "org.glavo.hmcl:lwjgl3-natives:3.3.4-rc2", + "downloads": { + "classifiers": { + "linux-loongarch64": { + "path": "org/glavo/hmcl/lwjgl3-natives/3.3.4-rc2/lwjgl3-natives-3.3.4-rc2-linux-loongarch64.jar", + "url": "https://repo1.maven.org/maven2/org/glavo/hmcl/lwjgl3-natives/3.3.4-rc2-linux-loongarch64/lwjgl3-natives-3.3.4-rc2-linux-loongarch64.jar", + "sha1": "34a7f913c6750f2bede863f59c074cc4d540fb64", + "size": 12234234 + } + } + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "natives": { + "linux": "linux-loongarch64" + } + }, + "org.lwjgl:lwjgl-jemalloc:3.3.2": { + "name": "org.lwjgl:lwjgl-jemalloc:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-jemalloc/3.3.4/lwjgl-jemalloc-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-jemalloc/3.3.4/lwjgl-jemalloc-3.3.4.jar", + "sha1": "e3f5dcb8e13f3a5ed3f740fd30a114cee2a80bc4", + "size": 46430 + } + } + }, + "org.lwjgl:lwjgl-jemalloc:3.3.2:natives-linux": null, + "org.lwjgl:lwjgl-openal:3.3.2": { + "name": "org.lwjgl:lwjgl-openal:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-openal/3.3.4/lwjgl-openal-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-openal/3.3.4/lwjgl-openal-3.3.4.jar", + "sha1": "9b74d3ea380c83353d42af43ad9659e04dabe84a", + "size": 113103 + } + } + }, + "org.lwjgl:lwjgl-openal:3.3.2:natives-linux": null, + "org.lwjgl:lwjgl-opengl:3.3.2": { + "name": "org.lwjgl:lwjgl-opengl:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-opengl/3.3.4/lwjgl-opengl-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-opengl/3.3.4/lwjgl-opengl-3.3.4.jar", + "sha1": "2852ac7d9f6fc71349f1ce28e2708ff1977f18af", + "size": 931960 + } + } + }, + "org.lwjgl:lwjgl-opengl:3.3.2:natives-linux": null, + "org.lwjgl:lwjgl-glfw:3.3.2": { + "name": "org.lwjgl:lwjgl-glfw:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-glfw/3.3.4/lwjgl-glfw-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-glfw/3.3.4/lwjgl-glfw-3.3.4.jar", + "sha1": "7e46ecdec85db8738053cfde1414352cd62dab74", + "size": 147044 + } + } + }, + "org.lwjgl:lwjgl-glfw:3.3.2:natives-linux": null, + "org.lwjgl:lwjgl-stb:3.3.2": { + "name": "org.lwjgl:lwjgl-stb:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-stb/3.3.4/lwjgl-stb-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-stb/3.3.4/lwjgl-stb-3.3.4.jar", + "sha1": "5821735d5ef23f6da8542887344e57eb181b7cac", + "size": 143112 + } + } + }, + "org.lwjgl:lwjgl-stb:3.3.2:natives-linux": null, + "org.lwjgl:lwjgl-tinyfd:3.3.2": { + "name": "org.lwjgl:lwjgl-tinyfd:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-tinyfd/3.3.4/lwjgl-tinyfd-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-tinyfd/3.3.4/lwjgl-tinyfd-3.3.4.jar", + "sha1": "2d73789ffd8962b38d9d599cc38b2383ce818c7a", + "size": 15928 + } + } + }, + "org.lwjgl:lwjgl-tinyfd:3.3.2:natives-linux": null, + "org.lwjgl:lwjgl:3.3.3": { + "name": "org.lwjgl:lwjgl:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl/3.3.4/lwjgl-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl/3.3.4/lwjgl-3.3.4.jar", + "sha1": "b86c3e4832426e8a6b466013b7cb34b40e9ce956", + "size": 800127 + } + } + }, + "org.lwjgl:lwjgl:3.3.3:natives-linux": { + "name": "org.glavo.hmcl:lwjgl3-natives:3.3.4-rc2", + "downloads": { + "classifiers": { + "linux-loongarch64": { + "path": "org/glavo/hmcl/lwjgl3-natives/3.3.4-rc2/lwjgl3-natives-3.3.4-rc2-linux-loongarch64.jar", + "url": "https://repo1.maven.org/maven2/org/glavo/hmcl/lwjgl3-natives/3.3.4-rc2-linux-loongarch64/lwjgl3-natives-3.3.4-rc2-linux-loongarch64.jar", + "sha1": "34a7f913c6750f2bede863f59c074cc4d540fb64", + "size": 12234234 + } + } + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "natives": { + "linux": "linux-loongarch64" + } + }, + "org.lwjgl:lwjgl-jemalloc:3.3.3": { + "name": "org.lwjgl:lwjgl-jemalloc:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-jemalloc/3.3.4/lwjgl-jemalloc-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-jemalloc/3.3.4/lwjgl-jemalloc-3.3.4.jar", + "sha1": "e3f5dcb8e13f3a5ed3f740fd30a114cee2a80bc4", + "size": 46430 + } + } + }, + "org.lwjgl:lwjgl-jemalloc:3.3.3:natives-linux": null, + "org.lwjgl:lwjgl-openal:3.3.3": { + "name": "org.lwjgl:lwjgl-openal:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-openal/3.3.4/lwjgl-openal-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-openal/3.3.4/lwjgl-openal-3.3.4.jar", + "sha1": "9b74d3ea380c83353d42af43ad9659e04dabe84a", + "size": 113103 + } + } + }, + "org.lwjgl:lwjgl-openal:3.3.3:natives-linux": null, + "org.lwjgl:lwjgl-opengl:3.3.3": { + "name": "org.lwjgl:lwjgl-opengl:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-opengl/3.3.4/lwjgl-opengl-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-opengl/3.3.4/lwjgl-opengl-3.3.4.jar", + "sha1": "2852ac7d9f6fc71349f1ce28e2708ff1977f18af", + "size": 931960 + } + } + }, + "org.lwjgl:lwjgl-opengl:3.3.3:natives-linux": null, + "org.lwjgl:lwjgl-glfw:3.3.3": { + "name": "org.lwjgl:lwjgl-glfw:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-glfw/3.3.4/lwjgl-glfw-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-glfw/3.3.4/lwjgl-glfw-3.3.4.jar", + "sha1": "7e46ecdec85db8738053cfde1414352cd62dab74", + "size": 147044 + } + } + }, + "org.lwjgl:lwjgl-glfw:3.3.3:natives-linux": null, + "org.lwjgl:lwjgl-stb:3.3.3": { + "name": "org.lwjgl:lwjgl-stb:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-stb/3.3.4/lwjgl-stb-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-stb/3.3.4/lwjgl-stb-3.3.4.jar", + "sha1": "5821735d5ef23f6da8542887344e57eb181b7cac", + "size": 143112 + } + } + }, + "org.lwjgl:lwjgl-stb:3.3.3:natives-linux": null, + "org.lwjgl:lwjgl-tinyfd:3.3.3": { + "name": "org.lwjgl:lwjgl-tinyfd:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-tinyfd/3.3.4/lwjgl-tinyfd-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-tinyfd/3.3.4/lwjgl-tinyfd-3.3.4.jar", + "sha1": "2d73789ffd8962b38d9d599cc38b2383ce818c7a", + "size": 15928 + } + } + }, + "org.lwjgl:lwjgl-tinyfd:3.3.3:natives-linux": null, + "org.lwjgl:lwjgl-freetype:3.3.3": { + "name": "org.lwjgl:lwjgl-freetype:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-freetype/3.3.4/lwjgl-freetype-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-freetype/3.3.4/lwjgl-freetype-3.3.4.jar", + "sha1": "23f7bf165068ef2ca80ae1b79fd905af20498600", + "size": 453489 + } + } + }, + "org.lwjgl:lwjgl-freetype:3.3.3:natives-linux": null, "net.java.dev.jna:jna:5.8.0": { "name": "net.java.dev.jna:jna:5.13.0", "downloads": { diff --git a/PLATFORM.md b/PLATFORM.md index 3826696f8e..85aa1cbcf8 100644 --- a/PLATFORM.md +++ b/PLATFORM.md @@ -2,17 +2,18 @@ English | [简体中文](PLATFORM_cn.md) -| | Windows | Linux | Mac OS | FreeBSD | -|----------------------------|:--------------------------------------------------|:--------------------------|:------------------------------------------------------------------------|:-------------------------| -| x86-64 | ✅️ | ✅️ | ✅️ | 👌 (Minecraft 1.13~1.21) | -| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | -| ARM64 | 👌 (Minecraft 1.8~1.18.2)
✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.20.6) | 👌 (Minecraft 1.6~1.18.2)
✅ (Minecraft 1.19+)
✅ (use Rosetta 2) | ❔ | -| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | -| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | -| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21) | / | / | -| LoongArch64 | / | 👌 (Minecraft 1.6~1.20.1) | / | / | -| PowerPC-64 (Little-Endian) | / | ❔ | / | / | -| S390x | / | ❔ | / | / | +| | Windows | Linux | Mac OS | FreeBSD | +|----------------------------|:--------------------------------------------------|:---------------------------|:------------------------------------------------------------------------|:---------------------------| +| x86-64 | ✅️ | ✅️ | ✅️ | 👌 (Minecraft 1.13~1.21.1) | +| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | +| ARM64 | 👌 (Minecraft 1.8~1.18.2)
✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.20.6) | 👌 (Minecraft 1.6~1.18.2)
✅ (Minecraft 1.19+)
✅ (use Rosetta 2) | ❔ | +| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | +| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | +| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.1) | / | / | +| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | +| LoongArch64 (Old World) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | +| PowerPC-64 (Little-Endian) | / | ❔ | / | / | +| S390x | / | ❔ | / | / | Legend: diff --git a/PLATFORM_cn.md b/PLATFORM_cn.md index 0fe094933f..a952493ce5 100644 --- a/PLATFORM_cn.md +++ b/PLATFORM_cn.md @@ -2,17 +2,18 @@ [English](PLATFORM.md) | 简体中文 -| | Windows | Linux | Mac OS | FreeBSD | -|----------------------------|:--------------------------------------------------|:---------------------------|:-----------------------------------------------------------------------|:------------------------| -| x86-64 | ✅️ | ✅️ | ✅️ | 👌(Minecraft 1.13~1.21) | -| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | -| ARM64 | 👌 (Minecraft 1.8~1.18.2)
✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21) | 👌 (Minecraft 1.6~1.18.2)
✅ (Minecraft 1.19+)
✅ (使用 Rosetta 2) | ❔ | -| ARM32 | /️ | 👌 (Minecraft 1.6~1.20.1) | / | / | -| MIPS64el | / | 👌 (Minecraft 1.6~1.20.1) | / | / | -| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21) | / | / | -| LoongArch64 | / | 👌 (Minecraft 1.6~1.20.1) | / | / | -| PowerPC-64 (Little-Endian) | / | ❔ | / | / | -| S390x | / | ❔ | / | / | +| | Windows | Linux | Mac OS | FreeBSD | +|----------------------------|:--------------------------------------------------|:---------------------------|:-----------------------------------------------------------------------|:--------------------------| +| x86-64 | ✅️ | ✅️ | ✅️ | 👌(Minecraft 1.13~1.21.1) | +| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | +| ARM64 | 👌 (Minecraft 1.8~1.18.2)
✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21) | 👌 (Minecraft 1.6~1.18.2)
✅ (Minecraft 1.19+)
✅ (使用 Rosetta 2) | ❔ | +| ARM32 | /️ | 👌 (Minecraft 1.6~1.20.1) | / | / | +| MIPS64el | / | 👌 (Minecraft 1.6~1.20.1) | / | / | +| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21) | / | / | +| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | +| LoongArch64 (旧世界) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | +| PowerPC-64 (Little-Endian) | / | ❔ | / | / | +| S390x | / | ❔ | / | / | 图例: From dec307b5313300a01850f46d9443217493ee61a7 Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Sun, 13 Oct 2024 21:46:48 +0800 Subject: [PATCH 015/169] =?UTF-8?q?=E5=AE=89=E8=A3=85=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E7=9A=84=E7=89=88=E6=9C=AC=E5=90=8D=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E6=A1=86=E6=98=BE=E7=A4=BA=E5=B7=B2=E9=80=89=E6=8B=A9=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E5=99=A8=E5=90=8D=E7=A7=B0=20(#3234)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update InstallersPage.java * 优化代码 * Update InstallersPage.java * Update InstallersPage.java * fix: checkstyle * 给 LibraryAnalyzer.LibraryType.fromPatchId 稍微优化一下,把她里面的实现改为一个预先生成的 map, 相信你知道怎么把这个函数改成一个 lookupMap.get(patchId) 的形式 * Update InstallersPage.java * Update InstallersPage.java * Fix * update --------- Co-authored-by: Glavo --- .../hmcl/ui/download/InstallersPage.java | 51 ++++++++++++++++++- .../hmcl/download/LibraryAnalyzer.java | 12 +++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index b9c8e0c338..1e0bc2d8dc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -52,6 +52,8 @@ public class InstallersPage extends Control implements WizardPage { protected JFXTextField txtName = new JFXTextField(); protected BooleanProperty installable = new SimpleBooleanProperty(); + private boolean isNameModifiedByUser = false; + public InstallersPage(WizardController controller, HMCLGameRepository repository, String gameVersion, DownloadProvider downloadProvider) { this.controller = controller; this.group = new InstallerItem.InstallerItemGroup(gameVersion, getInstallerItemStyle()); @@ -61,7 +63,8 @@ public InstallersPage(WizardController controller, HMCLGameRepository repository new Validator(i18n("install.new_game.already_exists"), str -> !repository.versionIdConflicts(str)), new Validator(i18n("install.new_game.malformed"), HMCLGameRepository::isValidVersionId)); installable.bind(createBooleanBinding(txtName::validate, txtName.textProperty())); - txtName.setText(gameVersion); + + txtName.textProperty().addListener((obs, oldText, newText) -> isNameModifiedByUser = true); for (InstallerItem library : group.getLibraries()) { String libraryId = library.getLibraryId(); @@ -103,6 +106,9 @@ protected void reload() { library.versionProperty().set(null); } } + if (!isNameModifiedByUser) { + setTxtNameWithLoaders(); + } } @Override @@ -124,6 +130,49 @@ protected Skin createDefaultSkin() { return new InstallersPageSkin(this); } + private void setTxtNameWithLoaders() { + StringBuilder nameBuilder = new StringBuilder(group.getGame().versionProperty().get().getVersion()); + + for (InstallerItem library : group.getLibraries()) { + String libraryId = library.getLibraryId().replace(LibraryAnalyzer.LibraryType.MINECRAFT.getPatchId(), ""); + if (!controller.getSettings().containsKey(libraryId)) { + continue; + } + + LibraryAnalyzer.LibraryType libraryType = LibraryAnalyzer.LibraryType.fromPatchId(libraryId); + if (libraryType != null) { + String loaderName; + switch (libraryType) { + case FORGE: + loaderName = i18n("install.installer.forge"); + break; + case NEO_FORGE: + loaderName = i18n("install.installer.neoforge"); + break; + case FABRIC: + loaderName = i18n("install.installer.fabric"); + break; + case LITELOADER: + loaderName = i18n("install.installer.liteloader"); + break; + case QUILT: + loaderName = i18n("install.installer.quilt"); + break; + case OPTIFINE: + loaderName = i18n("install.installer.optifine"); + break; + default: + continue; + } + + nameBuilder.append("-").append(loaderName); + } + } + + txtName.setText(nameBuilder.toString()); + isNameModifiedByUser = false; + } + protected static class InstallersPageSkin extends SkinBase { /** diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java index 71f963cfb9..d7ac46571e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java @@ -270,6 +270,13 @@ private String scanVersion(Version version) { private final Pattern group, artifact; private final ModLoaderType modLoaderType; + private static final Map PATCH_ID_MAP = new HashMap<>(); + static { + for (LibraryType type : values()) { + PATCH_ID_MAP.put(type.getPatchId(), type); + } + } + LibraryType(boolean modLoader, String patchId, Pattern group, Pattern artifact, ModLoaderType modLoaderType) { this.modLoader = modLoader; this.patchId = patchId; @@ -291,10 +298,7 @@ public ModLoaderType getModLoaderType() { } public static LibraryType fromPatchId(String patchId) { - for (LibraryType type : values()) - if (type.getPatchId().equals(patchId)) - return type; - return null; + return PATCH_ID_MAP.get(patchId); } protected boolean matchLibrary(Library library, List libraries) { From edd95ad626a1a6992d04a1d87806ff91f25f4d0e Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Sun, 13 Oct 2024 21:57:32 +0800 Subject: [PATCH 016/169] =?UTF-8?q?=E6=A8=A1=E7=BB=84=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E6=93=8D=E4=BD=9C=E6=9B=B4=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E6=96=87=E6=9C=AC=E6=9B=B4=E6=96=B0=E5=90=8E=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=20(#3221)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 更改为文本更新后触发 * 添加防抖 --- .../org/jackhuang/hmcl/ui/versions/ModListPageSkin.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index 4c35fe6308..5cfaa1f1e6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -19,6 +19,7 @@ import com.jfoenix.controls.*; import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject; +import javafx.animation.PauseTransition; import javafx.beans.binding.Bindings; import javafx.beans.property.BooleanProperty; import javafx.collections.ListChangeListener; @@ -33,6 +34,7 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.StackPane; +import javafx.util.Duration; import org.jackhuang.hmcl.mod.LocalModFile; import org.jackhuang.hmcl.mod.ModLoaderType; import org.jackhuang.hmcl.mod.RemoteMod; @@ -113,7 +115,12 @@ class ModListPageSkin extends SkinBase { searchField = new JFXTextField(); searchField.setPromptText(i18n("search")); HBox.setHgrow(searchField, Priority.ALWAYS); - searchField.setOnAction(e -> search()); + PauseTransition pause = new PauseTransition(Duration.millis(100)); + pause.setOnFinished(e -> search()); + searchField.textProperty().addListener((observable, oldValue, newValue) -> { + pause.setRate(1); + pause.playFromStart(); + }); JFXButton closeSearchBar = createToolbarButton2(null, SVG.CLOSE, () -> { From d4579852bb6dafa3f1b49341dd6175db55f2bdc2 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 14 Oct 2024 01:08:06 +0800 Subject: [PATCH 017/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20AboutPage=20(#3325?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 优化关于页面 * update --- .../org/jackhuang/hmcl/ui/main/AboutPage.java | 187 ++++++------------ .../src/main/resources/assets/about/deps.json | 62 ++++++ .../main/resources/assets/about/thanks.json | 78 ++++++++ 3 files changed, 201 insertions(+), 126 deletions(-) create mode 100644 HMCL/src/main/resources/assets/about/deps.json create mode 100644 HMCL/src/main/resources/assets/about/thanks.json diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java index 0c3e8c78ff..9d84d53996 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java @@ -17,18 +17,30 @@ */ package org.jackhuang.hmcl.ui.main; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import javafx.geometry.Insets; import javafx.scene.control.ScrollPane; +import javafx.scene.image.Image; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.construct.ComponentList; import org.jackhuang.hmcl.ui.construct.IconedTwoLineListItem; +import org.jackhuang.hmcl.util.gson.JsonUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; +import static org.jackhuang.hmcl.util.logging.Logger.LOG; -public class AboutPage extends StackPane { +public final class AboutPage extends StackPane { public AboutPage() { ComponentList about = new ComponentList(); @@ -48,131 +60,9 @@ public AboutPage() { about.getContent().setAll(launcher, author); } - ComponentList thanks = new ComponentList(); - { - IconedTwoLineListItem yushijinhun = new IconedTwoLineListItem(); - yushijinhun.setImage(FXUtils.newBuiltinImage("/assets/img/yushijinhun.png")); - yushijinhun.setTitle("yushijinhun"); - yushijinhun.setSubtitle(i18n("about.thanks_to.yushijinhun.statement")); - yushijinhun.setExternalLink("https://yushi.moe/"); - - IconedTwoLineListItem bangbang93 = new IconedTwoLineListItem(); - bangbang93.setImage(FXUtils.newBuiltinImage("/assets/img/bangbang93.png")); - bangbang93.setTitle("bangbang93"); - bangbang93.setSubtitle(i18n("about.thanks_to.bangbang93.statement")); - bangbang93.setExternalLink("https://bmclapi2.bangbang93.com/"); - - IconedTwoLineListItem glavo = new IconedTwoLineListItem(); - glavo.setImage(FXUtils.newBuiltinImage("/assets/img/glavo.png")); - glavo.setTitle("Glavo"); - glavo.setSubtitle(i18n("about.thanks_to.glavo.statement")); - glavo.setExternalLink("https://github.com/Glavo"); - - IconedTwoLineListItem zekerzhayard = new IconedTwoLineListItem(); - zekerzhayard.setImage(FXUtils.newBuiltinImage("/assets/img/zekerzhayard.png")); - zekerzhayard.setTitle("ZekerZhayard"); - zekerzhayard.setSubtitle(i18n("about.thanks_to.zekerzhayard.statement")); - zekerzhayard.setExternalLink("https://github.com/ZekerZhayard"); - - IconedTwoLineListItem zkitefly = new IconedTwoLineListItem(); - zkitefly.setImage(FXUtils.newBuiltinImage("/assets/img/zkitefly.png")); - zkitefly.setTitle("Zkitefly"); - zkitefly.setSubtitle(i18n("about.thanks_to.zkitefly.statement")); - zkitefly.setExternalLink("https://github.com/zkitefly"); - - IconedTwoLineListItem burningtnt = new IconedTwoLineListItem(); - burningtnt.setImage(FXUtils.newBuiltinImage("/assets/img/burningtnt.png")); - burningtnt.setTitle("Burning_TNT"); - burningtnt.setSubtitle(i18n("about.thanks_to.burningtnt.statement")); - burningtnt.setExternalLink("https://github.com/burningtnt"); - - IconedTwoLineListItem shulkerSakura = new IconedTwoLineListItem(); - shulkerSakura.setTitle("ShulkerSakura"); - shulkerSakura.setImage(FXUtils.newBuiltinImage("/assets/img/ShulkerSakura.png")); - shulkerSakura.setSubtitle(i18n("about.thanks_to.shulkersakura.statement")); - shulkerSakura.setExternalLink("https://github.com/ShulkerSakura"); - - IconedTwoLineListItem gamerteam = new IconedTwoLineListItem(); - gamerteam.setTitle("gamerteam"); - gamerteam.setImage(FXUtils.newBuiltinImage("/assets/img/gamerteam.png")); - gamerteam.setSubtitle(i18n("about.thanks_to.gamerteam.statement")); - gamerteam.setExternalLink("http://www.zhaisoul.com/"); - - IconedTwoLineListItem redLnn = new IconedTwoLineListItem(); - redLnn.setTitle("Red_lnn"); - redLnn.setImage(FXUtils.newBuiltinImage("/assets/img/red_lnn.png")); - redLnn.setSubtitle(i18n("about.thanks_to.red_lnn.statement")); - - IconedTwoLineListItem mcmod = new IconedTwoLineListItem(); - mcmod.setImage(FXUtils.newBuiltinImage("/assets/img/mcmod.png")); - mcmod.setTitle(i18n("about.thanks_to.mcmod")); - mcmod.setSubtitle(i18n("about.thanks_to.mcmod.statement")); - mcmod.setExternalLink("https://www.mcmod.cn/"); - - IconedTwoLineListItem mcbbs = new IconedTwoLineListItem(); - mcbbs.setImage(FXUtils.newBuiltinImage("/assets/img/chest.png")); - mcbbs.setTitle(i18n("about.thanks_to.mcbbs")); - mcbbs.setSubtitle(i18n("about.thanks_to.mcbbs.statement")); - - IconedTwoLineListItem contributors = new IconedTwoLineListItem(); - contributors.setImage(FXUtils.newBuiltinImage("/assets/img/github.png")); - contributors.setTitle(i18n("about.thanks_to.contributors")); - contributors.setSubtitle(i18n("about.thanks_to.contributors.statement")); - contributors.setExternalLink("https://github.com/HMCL-dev/HMCL/graphs/contributors"); - - IconedTwoLineListItem users = new IconedTwoLineListItem(); - users.setImage(FXUtils.newBuiltinImage("/assets/img/icon.png")); - users.setTitle(i18n("about.thanks_to.users")); - users.setSubtitle(i18n("about.thanks_to.users.statement")); - users.setExternalLink("https://docs.hmcl.net/groups.html"); - - thanks.getContent().setAll(yushijinhun, bangbang93, glavo, zekerzhayard, zkitefly, burningtnt, mcmod, mcbbs, shulkerSakura, gamerteam, redLnn, contributors, users); - } + ComponentList thanks = loadIconedTwoLineList("/assets/about/thanks.json"); - ComponentList dep = new ComponentList(); - { - IconedTwoLineListItem javafx = new IconedTwoLineListItem(); - javafx.setTitle("JavaFX"); - javafx.setSubtitle("Copyright © 2013, 2024, Oracle and/or its affiliates.\nLicensed under the GPL 2 with Classpath Exception."); - javafx.setExternalLink("https://openjfx.io/"); - - IconedTwoLineListItem jfoenix = new IconedTwoLineListItem(); - jfoenix.setTitle("JFoenix"); - jfoenix.setSubtitle("Copyright © 2016 JFoenix.\nLicensed under the MIT License."); - jfoenix.setExternalLink("https://github.com/sshahine/JFoenix"); - - IconedTwoLineListItem gson = new IconedTwoLineListItem(); - gson.setTitle("Gson"); - gson.setSubtitle("Copyright © 2008 Google Inc.\nLicensed under the Apache 2.0 License."); - gson.setExternalLink("https://github.com/google/gson"); - - IconedTwoLineListItem xz = new IconedTwoLineListItem(); - xz.setTitle("XZ for Java"); - xz.setSubtitle("Lasse Collin, Igor Pavlov, and/or Brett Okken.\nPublic Domain."); - xz.setExternalLink("https://tukaani.org/xz/java.html"); - - IconedTwoLineListItem fxgson = new IconedTwoLineListItem(); - fxgson.setTitle("fx-gson"); - fxgson.setSubtitle("Copyright © 2016 Joffrey Bion.\nLicensed under the MIT License."); - fxgson.setExternalLink("https://github.com/joffrey-bion/fx-gson"); - - IconedTwoLineListItem constantPoolScanner = new IconedTwoLineListItem(); - constantPoolScanner.setTitle("Constant Pool Scanner"); - constantPoolScanner.setSubtitle("Copyright © 1997-2010 Oracle and/or its affiliates.\nLicensed under the GPL 2 or the CDDL."); - constantPoolScanner.setExternalLink("https://github.com/jenkinsci/constant-pool-scanner"); - - IconedTwoLineListItem openNBT = new IconedTwoLineListItem(); - openNBT.setTitle("OpenNBT"); - openNBT.setSubtitle("Copyright © 2013-2021 Steveice10.\nLicensed under the MIT License."); - openNBT.setExternalLink("https://github.com/GeyserMC/OpenNBT"); - - IconedTwoLineListItem minecraftJFXSkin = new IconedTwoLineListItem(); - minecraftJFXSkin.setTitle("minecraft-jfx-skin"); - minecraftJFXSkin.setSubtitle("Copyright © 2016 InfinityStudio.\nLicensed under the GPL 3."); - minecraftJFXSkin.setExternalLink("https://github.com/InfinityStudio/minecraft-jfx-skin"); - - dep.getContent().setAll(javafx, jfoenix, gson, xz, fxgson, constantPoolScanner, openNBT, minecraftJFXSkin); - } + ComponentList deps = loadIconedTwoLineList("/assets/about/deps.json"); ComponentList legal = new ComponentList(); { @@ -204,7 +94,7 @@ public AboutPage() { thanks, ComponentList.createComponentListTitle(i18n("about.dependency")), - dep, + deps, ComponentList.createComponentListTitle(i18n("about.legal")), legal @@ -216,4 +106,49 @@ public AboutPage() { FXUtils.smoothScrolling(scrollPane); getChildren().setAll(scrollPane); } + + private static ComponentList loadIconedTwoLineList(String path) { + ComponentList componentList = new ComponentList(); + + InputStream input = FXUtils.class.getResourceAsStream(path); + if (input == null) { + LOG.warning("Resources not found: " + path); + return componentList; + } + + try (Reader reader = new InputStreamReader(input)) { + JsonArray array = JsonUtils.GSON.fromJson(reader, JsonArray.class); + + for (JsonElement element : array) { + JsonObject obj = element.getAsJsonObject(); + IconedTwoLineListItem item = new IconedTwoLineListItem(); + + if (obj.has("image")) { + String image = obj.get("image").getAsString(); + item.setImage(image.startsWith("/") + ? FXUtils.newBuiltinImage(image) + : new Image(image)); + } + + if (obj.has("title")) + item.setTitle(obj.get("title").getAsString()); + else if (obj.has("titleLocalized")) + item.setTitle(i18n(obj.get("titleLocalized").getAsString())); + + if (obj.has("subtitle")) + item.setSubtitle(obj.get("subtitle").getAsString()); + else if (obj.has("subtitleLocalized")) + item.setSubtitle(i18n(obj.get("subtitleLocalized").getAsString())); + + if (obj.has("externalLink")) + item.setExternalLink(obj.get("externalLink").getAsString()); + + componentList.getContent().add(item); + } + } catch (IOException | JsonParseException e) { + LOG.warning("Failed to load list: " + path, e); + } + + return componentList; + } } diff --git a/HMCL/src/main/resources/assets/about/deps.json b/HMCL/src/main/resources/assets/about/deps.json new file mode 100644 index 0000000000..5b0cf68475 --- /dev/null +++ b/HMCL/src/main/resources/assets/about/deps.json @@ -0,0 +1,62 @@ +[ + { + "title" : "OpenJFX", + "subtitle" : "Copyright © 2013, 2024, Oracle and/or its affiliates.\nLicensed under the GPL 2 with Classpath Exception.", + "externalLink" : "https://openjfx.io" + }, + { + "title" : "JFoenix", + "subtitle" : "Copyright © 2016 JFoenix.\nLicensed under the MIT License.", + "externalLink" : "https://github.com/sshahine/JFoenix" + }, + { + "title" : "Gson", + "subtitle" : "Copyright © 2008 Google Inc.\nLicensed under the Apache 2.0 License.", + "externalLink" : "https://github.com/google/gson" + }, + { + "title" : "Apache Commons Compress", + "subtitle" : "Licensed under the Apache 2.0 License.", + "externalLink" : "https://commons.apache.org/proper/commons-compress/" + }, + { + "title" : "XZ for Java", + "subtitle" : "Lasse Collin, Igor Pavlov, and/or Brett Okken.\nPublic Domain.", + "externalLink" : "https://tukaani.org/xz/java.html" + }, + { + "title" : "FX Gson", + "subtitle" : "Copyright © 2016 Joffrey Bion.\nLicensed under the MIT License.", + "externalLink" : "https://github.com/joffrey-bion/fx-gson" + }, + { + "title" : "jsoup", + "subtitle" : "Copyright © 2009 - 2024 Jonathan Hedley (https://jsoup.org/)\nLicensed under the MIT License.", + "externalLink" : "https://jsoup.org/" + }, + { + "title" : "NanoHTTPD", + "subtitle" : "Copyright © 2012 - 2015 nanohttpd.\nLicensed under the BSD 3-clause License.", + "externalLink" : "https://github.com/NanoHttpd/nanohttpd" + }, + { + "title" : "Constant Pool Scanner", + "subtitle" : "Copyright © 1997-2010 Oracle and/or its affiliates.\nLicensed under the GPL 2 or the CDDL.", + "externalLink" : "https://github.com/jenkinsci/constant-pool-scanner" + }, + { + "title" : "OpenNBT", + "subtitle" : "Copyright © 2013-2021 Steveice10.\nLicensed under the MIT License.", + "externalLink" : "https://github.com/GeyserMC/OpenNBT" + }, + { + "title" : "minecraft-jfx-skin", + "subtitle" : "Copyright © 2016 InfinityStudio.\nLicensed under the GPL 3.", + "externalLink" : "https://github.com/InfinityStudio/minecraft-jfx-skin" + }, + { + "title" : "SimplePNG", + "subtitle" : "Copyright © 2023 Glavo.\nLicensed under the Apache 2.0 License.", + "externalLink" : "https://github.com/Glavo/SimplePNG" + } +] \ No newline at end of file diff --git a/HMCL/src/main/resources/assets/about/thanks.json b/HMCL/src/main/resources/assets/about/thanks.json new file mode 100644 index 0000000000..189ff30129 --- /dev/null +++ b/HMCL/src/main/resources/assets/about/thanks.json @@ -0,0 +1,78 @@ +[ + { + "image" : "/assets/img/yushijinhun.png", + "title" : "yushijinhun", + "subtitleLocalized" : "about.thanks_to.yushijinhun.statement", + "externalLink" : "https://github.com/yushijinhun" + }, + { + "image" : "/assets/img/bangbang93.png", + "title" : "bangbang93", + "subtitleLocalized" : "about.thanks_to.bangbang93.statement", + "externalLink" : "https://www.bangbang93.com" + }, + { + "image" : "/assets/img/glavo.png", + "title" : "Glavo", + "subtitleLocalized" : "about.thanks_to.glavo.statement", + "externalLink" : "https://github.com/Glavo" + }, + { + "image" : "/assets/img/zekerzhayard.png", + "title" : "ZekerZhayard", + "subtitleLocalized" : "about.thanks_to.zekerzhayard.statement", + "externalLink" : "https://github.com/ZekerZhayard" + }, + { + "image" : "/assets/img/zkitefly.png", + "title" : "Zkitefly", + "subtitleLocalized" : "about.thanks_to.zkitefly.statement", + "externalLink" : "https://github.com/zkitefly" + }, + { + "image" : "/assets/img/burningtnt.png", + "title" : "Burning_TNT", + "subtitleLocalized" : "about.thanks_to.burningtnt.statement", + "externalLink" : "https://github.com/burningtnt" + }, + { + "image" : "/assets/img/ShulkerSakura.png", + "title" : "ShulkerSakura", + "subtitleLocalized" : "about.thanks_to.shulkersakura.statement", + "externalLink" : "https://github.com/ShulkerSakura" + }, + { + "image" : "/assets/img/gamerteam.png", + "title" : "gamerteam", + "subtitleLocalized" : "about.thanks_to.gamerteam.statement", + "externalLink" : "https://github.com/ZhaiSoul" + }, + { + "image" : "/assets/img/red_lnn.png", + "title" : "Red_lnn", + "subtitleLocalized" : "about.thanks_to.red_lnn.statement" + }, + { + "image" : "/assets/img/mcmod.png", + "titleLocalized" : "about.thanks_to.mcmod", + "subtitleLocalized" : "about.thanks_to.mcmod.statement", + "externalLink" : "https://www.mcmod.cn" + }, + { + "image" : "/assets/img/chest.png", + "titleLocalized" : "about.thanks_to.mcbbs", + "subtitleLocalized" : "about.thanks_to.mcbbs.statement" + }, + { + "image" : "/assets/img/github.png", + "titleLocalized" : "about.thanks_to.contributors", + "subtitleLocalized" : "about.thanks_to.contributors.statement", + "externalLink" : "https://github.com/HMCL-dev/HMCL/graphs/contributors" + }, + { + "image" : "/assets/img/icon.png", + "titleLocalized" : "about.thanks_to.users", + "subtitleLocalized" : "about.thanks_to.users.statement", + "externalLink" : "https://docs.hmcl.net/groups.html" + } +] \ No newline at end of file From a4f5e013cbcb0f5a32ee390b122ddaf037c2978c Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 14 Oct 2024 01:24:14 +0800 Subject: [PATCH 018/169] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BD=BF=E7=94=A8=20?= =?UTF-8?q?Java=208=20=E6=9E=84=E5=BB=BA=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20(#3326)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java index 7dca291e09..96c23f51af 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/WebPage.java @@ -22,6 +22,7 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.scene.control.ScrollPane; import javafx.scene.layout.Background; +import javafx.scene.layout.BackgroundFill; import javafx.scene.paint.Color; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; @@ -42,7 +43,7 @@ public final class WebPage extends SpinnerPane implements DecoratorPage { public WebPage(String title, String content) { this.stateProperty = new SimpleObjectProperty<>(DecoratorPage.State.fromTitle(title)); - this.setBackground(Background.fill(Color.WHITE)); + this.setBackground(new Background(new BackgroundFill(Color.WHITE, null, null))); Task.supplyAsync(() -> { Document document = Jsoup.parseBodyFragment(content); From ae01a49cc46a093a81f557f2b0ecd37455bc4f5b Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Tue, 15 Oct 2024 00:57:23 +0800 Subject: [PATCH 019/169] Fix some error message wrap (#3333) * Fix some error message wrap * Fix checkstyle --- .../src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 c11bb0aa55..c5d70755fa 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -244,9 +244,9 @@ public void onStop(boolean success, TaskExecutor executor) { } else if (ex instanceof PermissionException) { message = i18n("launch.failed.executable_permission"); } else if (ex instanceof ProcessCreationException) { - message = i18n("launch.failed.creating_process") + ex.getLocalizedMessage(); + message = i18n("launch.failed.creating_process") + "\n" + ex.getLocalizedMessage(); } else if (ex instanceof NotDecompressingNativesException) { - message = i18n("launch.failed.decompressing_natives") + ex.getLocalizedMessage(); + message = i18n("launch.failed.decompressing_natives") + "\n" + ex.getLocalizedMessage(); } else if (ex instanceof LibraryDownloadException) { message = i18n("launch.failed.download_library", ((LibraryDownloadException) ex).getLibrary().getName()) + "\n"; if (ex.getCause() instanceof ResponseCodeException) { From 2109df81454067b4c9d7c67b110e327139e80ff8 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Tue, 15 Oct 2024 00:58:40 +0800 Subject: [PATCH 020/169] Fix some link (#3334) * Fix some link * Revise --- .../src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java | 4 ++-- HMCL/src/main/resources/assets/lang/I18N.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_es.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) 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 c5d70755fa..61725887c7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -881,8 +881,8 @@ public void onExit(int exitCode, ExitType exitType) { } - private static final String ORACLEJDK_DOWNLOAD_LINK = "https://www.java.com/download"; - private static final String OPENJDK_DOWNLOAD_LINK = "https://docs.microsoft.com/java/openjdk/download"; + private static final String ORACLEJDK_DOWNLOAD_LINK = "https://www.java.com/download/"; + private static final String OPENJDK_DOWNLOAD_LINK = "https://learn.microsoft.com/java/openjdk/download"; public static final Queue PROCESSES = new ConcurrentLinkedQueue<>(); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 14eb8e13e3..4f482d8820 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -578,7 +578,7 @@ There are some keywords that might contain some Mod Names. You can search them o %s game.crash.reason.too_old_java=The game crashed because you are using a historical Java VM version.\n\ \n\ -You need to switch to a newer version (%1$s) of Java in the game settings and then relaunch the game. You can download Java from here. +You need to switch to a newer version (%1$s) of Java in the game settings and then relaunch the game. You can download Java from here. game.crash.reason.unknown=We are not able to figure out why the game crashed, please refer to the game logs. game.crash.reason.unsatisfied_link_error=Unable to launch Minecraft due to missing libraries: %1$s.\n\ \n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 8cb9008479..b7ade7bd12 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -522,7 +522,7 @@ Hay algunas palabras clave que pueden contener algunos Mod IDs. Puedes buscarlas %s game.crash.reason.too_old_java=El juego se ha bloqueado porque estás utilizando una versión histórica de Java VM..\n\ \n\ -Tienes que cambiar a una versión más reciente (%1$s) de Java en la configuración del juego y luego volver a ejecutar el juego. Puedes descargar Java desde here. +Tienes que cambiar a una versión más reciente (%1$s) de Java en la configuración del juego y luego volver a ejecutar el juego. Puedes descargar Java desde here. game.crash.reason.unknown=No somos capaces de averiguar por qué el juego se estrelló, por favor refiérase a los registros del juego.\n\ \n\ Cuando pidas ayuda a otra persona, por favor, comparte con ella el registro completo del juego y el archivo de informe de fallos relacionado.\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 78971778f5..a74d8b88d2 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -471,7 +471,7 @@ game.crash.reason.out_of_memory=當前遊戲因為記憶體不足,無法繼續 game.crash.reason.processing_of_javaagent_failed=當前遊戲因為加載 -javaagent 參數失敗,無法繼續運行。\n如果你在 Java 虛擬機參數 中添加了相關參數,請檢查是否正確。\n如果你沒有添加相關參數或參數確認正確, 請嘗試:\n打開 控制面板 -- 時鐘和區域 分類(選項為類別顯示才有此選項,沒有就跳過)-- 區域 -- 上方的 管理 選項卡 -- 下方的 更改系統區域設置 按鈕 -- 在彈出的視窗中將 “使用Unicode UTF-8提供全球語言支持” 選項關閉,重啓設備後再嘗試啟動遊戲。\n可在 DiscordQQ 群尋求幫助 game.crash.reason.resolution_too_high=當前遊戲因為材質包解析度過高,無法繼續運行\n你可以更換一個解析度更低的材質,或者更換一個視訊記憶體更大的顯示卡。 game.crash.reason.stacktrace=原因未知,請點擊日誌按鈕查看詳細訊息。\n下面是一些關鍵字,其中可能包含 Mod 名稱,你可以透過搜索的方式查找有關訊息。\n%s -game.crash.reason.too_old_java=當前遊戲因為 Java 虛擬機版本過低,無法繼續運行。\n你需要在遊戲設置中更換 %1$s 或更新版本的 Java 虛擬機,並重新啟動遊戲。如果沒有下載安裝,你可以點擊 此處 下載微軟 JDK。 +game.crash.reason.too_old_java=當前遊戲因為 Java 虛擬機版本過低,無法繼續運行。\n你需要在遊戲設置中更換 %1$s 或更新版本的 Java 虛擬機,並重新啟動遊戲。如果沒有下載安裝,你可以點擊 此處 下載微軟 JDK。 game.crash.reason.unknown=原因未知,請點擊日誌按鈕查看詳細訊息。 game.crash.reason.unsatisfied_link_error=當前遊戲因為缺少本地庫,無法繼續運行。\n這些本地庫缺失:%1$s。\n如果你在全局(特定)遊戲設置中修改了本地庫路徑選項,請你修改回預設模式。\n如果已經在預設模式下,請檢查本地庫缺失是否是 Mod 引起的,或由 HMCL 引起的。如果你確定是 HMCL 引起的,建議你向我們反饋。\n或將游戲路徑中的所有非英文字符的名稱修改為英文字符(例如中文,空格等)\n如果你確實需要自定義本地庫路徑,你需要保證其中包含缺失的本地庫! game.crash.reason.failed_to_load_a_library=當前遊戲因為加載本地庫失敗,無法繼續運行。\n如果你在全局(特定)遊戲設置中修改了本地庫路徑選項,請你修改回預設模式。\n如果已經在預設模式下,請檢查本地庫缺失是否是 Mod 引起的,或由 HMCL 引起的。如果你確定是 HMCL 引起的,建議你向我們反饋。\n或將游戲路徑中的所有非英文字符的名稱修改為英文字符(例如中文,空格等)\n如果你確實需要自定義本地庫路徑,你需要保證其中包含缺失的本地庫! @@ -584,7 +584,7 @@ launch.advice.not_enough_space=你設定的記憶體大小過大,由於超過 launch.advice.require_newer_java_version=當前遊戲版本需要 Java %s,但 HMCL 未能找到該 Java 版本,你可以點擊“是”,HMCL 會自動下載他,是否下載? launch.advice.too_large_memory_for_32bit=你設定的記憶體大小過大,由於可能超過了 32 位元 Java 的記憶體分配限制,所以可能無法啟動遊戲,請將記憶體調至低於 1024MB 的值。 launch.advice.vanilla_linux_java_8=對於 Linux x86-64 平台,Minecraft 1.12.2 及以下版本與 Java 9+ 不相容,請使用 Java 8 啟動遊戲。 -launch.advice.vanilla_x86.translation=Minecraft 尚未為你的平臺提供完善支持,所以可能影響遊戲體驗或無法啟動遊戲。\n你可以在 這裡 下載 X86-64 架構的 Java 以獲得更完整的體驗。\n是否繼續啟動? +launch.advice.vanilla_x86.translation=Minecraft 尚未為你的平臺提供完善支持,所以可能影響遊戲體驗或無法啟動遊戲。\n你可以在 這裡 下載 X86-64 架構的 Java 以獲得更完整的體驗。\n是否繼續啟動? launch.advice.unknown=由於以下原因,無法繼續啟動遊戲: launch.failed=啟動失敗 launch.failed.cannot_create_jvm=偵測到無法建立 Java 虛擬機,可能是 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 945552efaf..4a2fb0073f 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -583,7 +583,7 @@ launch.advice.not_enough_space=你设置的内存大小过大,超过了系统 launch.advice.require_newer_java_version=当前游戏版本需要 Java %s,但 HMCL 未能找到该 Java 版本,你可以点击“是”,HMCL 会自动下载他,是否下载?\n如遇到问题,你可以点击右上角帮助按钮进行求助。 launch.advice.too_large_memory_for_32bit=您设置的内存大小过大,由于可能超过了 32 位 Java 的内存分配限制,所以可能无法启动游戏,请将内存调至 1024MB 或更小。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 launch.advice.vanilla_linux_java_8=对于 Linux x86-64 平台,Minecraft 1.12.2 及以下版本与 Java 9+ 不兼容,请使用 Java 8 启动游戏。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 -launch.advice.vanilla_x86.translation=Minecraft 尚未为您的平台提供完善支持,所以可能影响游戏体验或无法启动游戏。\n你可以在 这里 下载 X86-64 架构的 Java 以获得更完整的体验。 +launch.advice.vanilla_x86.translation=Minecraft 尚未为您的平台提供完善支持,所以可能影响游戏体验或无法启动游戏。\n你可以在 这里 下载 X86-64 架构的 Java 以获得更完整的体验。 launch.advice.unknown=由于以下原因,无法继续启动游戏: launch.failed=启动失败 launch.failed.cannot_create_jvm=截获到无法创建 Java 虚拟机,可能是 Java 参数有问题,可以在设置中开启无参数模式启动。 From 25c76a748fcbaa3639fab42efa7fa4e8a51b57a8 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Tue, 15 Oct 2024 01:06:21 +0800 Subject: [PATCH 021/169] Fix alignment of host and port in proxy settings (#3332) --- .../java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java index 23abc00563..3a4737afa7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.ui.main; import com.jfoenix.controls.*; -import javafx.geometry.HPos; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.Label; @@ -204,7 +203,6 @@ public DownloadSettingsPage() { Label host = new Label(i18n("settings.launcher.proxy.host")); GridPane.setRowIndex(host, 1); GridPane.setColumnIndex(host, 0); - GridPane.setHalignment(host, HPos.RIGHT); gridPane.getChildren().add(host); } @@ -220,7 +218,6 @@ public DownloadSettingsPage() { Label port = new Label(i18n("settings.launcher.proxy.port")); GridPane.setRowIndex(port, 2); GridPane.setColumnIndex(port, 0); - GridPane.setHalignment(port, HPos.RIGHT); gridPane.getChildren().add(port); } From deeef8f67a35b01617886b253b95c7a8163ece6c Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Tue, 15 Oct 2024 01:19:11 +0800 Subject: [PATCH 022/169] Download source and thread setting titles i18n key (#3338) * Change the download source and thread setting titles to the appropriate i18n key * update --------- Co-authored-by: Glavo --- .../java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java index 3a4737afa7..695c89ddfa 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java @@ -99,7 +99,7 @@ public DownloadSettingsPage() { downloadSource.getChildren().setAll(chooseWrapper, versionListSourcePane, downloadSourcePane); } - content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.version_list_source")), downloadSource); + content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.download_source")), downloadSource); } { From cce17edaa6adb12942150f80d5187abc538339c2 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Tue, 15 Oct 2024 01:24:44 +0800 Subject: [PATCH 023/169] Capitalize text above the sidebar line (#3336) --- .../java/org/jackhuang/hmcl/ui/account/AccountListPage.java | 3 ++- .../java/org/jackhuang/hmcl/ui/download/DownloadPage.java | 5 +++-- .../org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java | 6 ++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListPage.java index 253ca699b3..ae970c8643 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListPage.java @@ -44,6 +44,7 @@ import org.jackhuang.hmcl.util.javafx.MappedObservableList; import java.net.URI; +import java.util.Locale; import static org.jackhuang.hmcl.ui.versions.VersionPage.wrap; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -95,7 +96,7 @@ public AccountListPageSkin(AccountListPage skinnable) { VBox boxMethods = new VBox(); { boxMethods.getStyleClass().add("advanced-list-box-content"); - boxMethods.getChildren().add(new ClassTitle(i18n("account.create"))); + boxMethods.getChildren().add(new ClassTitle(i18n("account.create").toUpperCase(Locale.ROOT))); FXUtils.setLimitWidth(boxMethods, 200); AdvancedListItem offlineItem = new AdvancedListItem(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java index 20a0692bd1..7b8e894860 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java @@ -55,6 +55,7 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; +import java.util.Locale; import java.util.concurrent.CancellationException; import java.util.function.Supplier; @@ -101,7 +102,7 @@ public DownloadPage() { { AdvancedListBox sideBar = new AdvancedListBox() - .startCategory(i18n("download.game")) + .startCategory(i18n("download.game").toUpperCase(Locale.ROOT)) .addNavigationDrawerItem(item -> { item.setTitle(i18n("game")); item.setLeftGraphic(wrap(SVG.GAMEPAD)); @@ -114,7 +115,7 @@ public DownloadPage() { settingsItem.activeProperty().bind(tab.getSelectionModel().selectedItemProperty().isEqualTo(modpackTab)); settingsItem.setOnAction(e -> tab.select(modpackTab)); }) - .startCategory(i18n("download.content")) + .startCategory(i18n("download.content").toUpperCase(Locale.ROOT)) .addNavigationDrawerItem(item -> { item.setTitle(i18n("mods")); item.setLeftGraphic(wrap(SVG.PUZZLE)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java index 155459d376..b9395c07dd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java @@ -33,6 +33,8 @@ import org.jackhuang.hmcl.ui.decorator.DecoratorPage; import org.jackhuang.hmcl.ui.versions.VersionSettingsPage; +import java.util.Locale; + import static org.jackhuang.hmcl.ui.versions.VersionPage.wrap; import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -83,7 +85,7 @@ public LauncherSettingsPage() { javaItem.activeProperty().bind(tab.getSelectionModel().selectedItemProperty().isEqualTo(javaManagementTab)); javaItem.setOnAction(e -> tab.select(javaManagementTab)); }) - .startCategory(i18n("launcher")) + .startCategory(i18n("launcher").toUpperCase(Locale.ROOT)) .addNavigationDrawerItem(settingsItem -> { settingsItem.setTitle(i18n("settings.launcher.general")); settingsItem.setLeftGraphic(wrap(SVG.APPLICATION_OUTLINE)); @@ -102,7 +104,7 @@ public LauncherSettingsPage() { downloadItem.activeProperty().bind(tab.getSelectionModel().selectedItemProperty().isEqualTo(downloadTab)); downloadItem.setOnAction(e -> tab.select(downloadTab)); }) - .startCategory(i18n("help")) + .startCategory(i18n("help").toUpperCase(Locale.ROOT)) .addNavigationDrawerItem(helpItem -> { helpItem.setTitle(i18n("help")); helpItem.setLeftGraphic(wrap(SVG.HELP_CIRCLE_OUTLINE)); From 71c9632d615bcbe58c4004a6ad3e1d1e97d8d8be Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 15 Oct 2024 03:13:35 +0800 Subject: [PATCH 024/169] =?UTF-8?q?GitHub=20Action=20=E4=BD=BF=E7=94=A8=20?= =?UTF-8?q?Java=208=20=E6=9E=84=E5=BB=BA=20HMCL=20(#3340)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update --- .github/workflows/gradle.yml | 4 ++-- HMCLCore/build.gradle.kts | 6 ++++++ .../java/org/jackhuang/hmcl/game/CrashReportAnalyzer.java | 2 +- .../org/jackhuang/hmcl/game/CrashReportAnalyzerTest.java | 3 ++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index fe45a94b22..acc107f824 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -14,11 +14,11 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up JDK 11 + - name: Set up JDK 8 uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: '11' + java-version: 8 java-package: 'jdk+fx' - name: Build with Gradle run: ./gradlew build --no-daemon diff --git a/HMCLCore/build.gradle.kts b/HMCLCore/build.gradle.kts index e7c4b4ab57..f5cc2f8fbe 100644 --- a/HMCLCore/build.gradle.kts +++ b/HMCLCore/build.gradle.kts @@ -14,4 +14,10 @@ dependencies { api("org.apache.commons:commons-compress:1.25.0") api("org.jsoup:jsoup:1.18.1") compileOnlyApi("org.jetbrains:annotations:24.1.0") + + if (JavaVersion.current().isJava8) { + org.gradle.internal.jvm.Jvm.current().toolsJar?.let { + compileOnly(files(it)) + } + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/CrashReportAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/CrashReportAnalyzer.java index 42e96367ed..22cce5a2aa 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/CrashReportAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/CrashReportAnalyzer.java @@ -113,7 +113,7 @@ public enum Rule { //https://github.com/HMCL-dev/HMCL/pull/2038 MODMIXIN_FAILURE(Pattern.compile("(MixinApplyError|Mixin prepare failed |Mixin apply failed |mixin\\.injection\\.throwables\\.|\\.mixins\\.json\\] FAILED during \\))")),//ModMixin失败 MIXIN_APPLY_MOD_FAILED(Pattern.compile("Mixin apply for mod (?.*) failed"), "id"),//Mixin应用失败 - FORGE_ERROR(Pattern.compile("An exception was thrown, the game will display an error screen and halt\\.(?(.*)[\\n\\r]*((.*)[\\n\\r]*)+)at "), "reason"),//Forge报错,Forge可能已经提供了错误信息 + FORGE_ERROR(Pattern.compile("An exception was thrown, the game will display an error screen and halt\\.\\R*(?.*\\R*(\\s*at .*\\R)+)"), "reason"),//Forge报错,Forge可能已经提供了错误信息 MOD_RESOLUTION0(Pattern.compile("(\tMod File:|-- MOD |\tFailure message:)")), FORGE_REPEAT_INSTALLATION(Pattern.compile("MultipleArgumentsForOptionException: Found multiple arguments for option (.*?), but you asked for only one")),//https://github.com/HMCL-dev/HMCL/issues/1880 OPTIFINE_REPEAT_INSTALLATION(Pattern.compile("ResolutionException: Module optifine reads another module named optifine")),//Optifine 重复安装(及Mod文件夹有,自动安装也有) diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/game/CrashReportAnalyzerTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/game/CrashReportAnalyzerTest.java index 289573c969..a47f263050 100644 --- a/HMCLCore/src/test/java/org/jackhuang/hmcl/game/CrashReportAnalyzerTest.java +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/game/CrashReportAnalyzerTest.java @@ -140,7 +140,8 @@ public void forgeEroor() throws IOException { "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_131]\n" + "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_131]\n" + "\tat java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_131]\n" + - "\tat oolloo.jlw.Wrapper.invokeMain(Wrapper.java:58) [JavaWrapper.jar:?]\n").replaceAll("\\s+", ""), + "\tat oolloo.jlw.Wrapper.invokeMain(Wrapper.java:58) [JavaWrapper.jar:?]\n" + + "\tat oolloo.jlw.Wrapper.main(Wrapper.java:51) [JavaWrapper.jar:?]").replaceAll("\\s+", ""), result.getMatcher().group("reason").replaceAll("\\s+", "")); } From 1ce98588938745bdf116051645895b5ddc97d822 Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Tue, 15 Oct 2024 04:06:40 +0800 Subject: [PATCH 025/169] =?UTF-8?q?Support=20#2992:=20=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E6=A8=A1=E7=BB=84=E6=9B=B4=E6=96=B0=E7=95=8C=E9=9D=A2=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=E5=85=A8=E9=80=89/=E5=8F=96=E6=B6=88=E5=85=A8?= =?UTF-8?q?=E9=80=89=E5=A4=8D=E9=80=89=E6=A1=86=20(#3032)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support #2992 --------- Co-authored-by: Glavo --- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 63 +++++++++++++++++-- .../hmcl/ui/versions/ModUpdatesPage.java | 6 +- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index df712fe24a..41e5d1cd6b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -23,11 +23,9 @@ import javafx.beans.InvalidationListener; import javafx.beans.Observable; import javafx.beans.WeakInvalidationListener; +import javafx.beans.property.BooleanProperty; import javafx.beans.property.Property; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.beans.value.WeakChangeListener; -import javafx.beans.value.WritableValue; +import javafx.beans.value.*; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; @@ -657,6 +655,61 @@ public static void unbindEnum(JFXComboBox> comboBox) { comboBox.getSelectionModel().selectedIndexProperty().removeListener(listener); } + public static void bindAllEnabled(BooleanProperty allEnabled, BooleanProperty... children) { + int itemCount = children.length; + int childSelectedCount = 0; + for (BooleanProperty child : children) { + if (child.get()) + childSelectedCount++; + } + + allEnabled.set(childSelectedCount == itemCount); + + class Listener implements InvalidationListener { + private int childSelectedCount; + private boolean updating = false; + + public Listener(int childSelectedCount) { + this.childSelectedCount = childSelectedCount; + } + + @Override + public void invalidated(Observable observable) { + if (updating) + return; + + updating = true; + try { + boolean value = ((BooleanProperty) observable).get(); + + if (observable == allEnabled) { + for (BooleanProperty child : children) { + child.setValue(value); + } + childSelectedCount = value ? itemCount : 0; + } else { + if (value) + childSelectedCount++; + else + childSelectedCount--; + + allEnabled.set(childSelectedCount == itemCount); + } + } finally { + updating = false; + } + } + } + + InvalidationListener listener = new Listener(childSelectedCount); + + WeakInvalidationListener weakListener = new WeakInvalidationListener(listener); + allEnabled.addListener(listener); + for (BooleanProperty child : children) { + child.addListener(weakListener); + } + } + public static void setIcon(Stage stage) { String icon; if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) { @@ -925,7 +978,7 @@ public static List parseSegment(String segment, Consumer hyperlink Element r = doc.getDocumentElement(); NodeList children = r.getChildNodes(); - List texts = new ArrayList<>(); + List texts = new ArrayList<>(); for (int i = 0; i < children.getLength(); i++) { org.w3c.dom.Node node = children.item(i); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java index 0d080f731f..791ba21c4d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java @@ -24,6 +24,7 @@ import javafx.collections.ObservableList; import javafx.geometry.Insets; import javafx.geometry.Pos; +import javafx.scene.control.CheckBox; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.CheckBoxTableCell; @@ -73,6 +74,8 @@ public ModUpdatesPage(ModManager modManager, List update getStyleClass().add("gray-background"); TableColumn enabledColumn = new TableColumn<>(); + CheckBox allEnabledBox = new CheckBox(); + enabledColumn.setGraphic(allEnabledBox); enabledColumn.setCellFactory(CheckBoxTableCell.forTableColumn(enabledColumn)); setupCellValueFactory(enabledColumn, ModUpdateObject::enabledProperty); enabledColumn.setEditable(true); @@ -95,6 +98,7 @@ public ModUpdatesPage(ModManager modManager, List update setupCellValueFactory(sourceColumn, ModUpdateObject::sourceProperty); objects = FXCollections.observableList(updates.stream().map(ModUpdateObject::new).collect(Collectors.toList())); + FXUtils.bindAllEnabled(allEnabledBox.selectedProperty(), objects.stream().map(o -> o.enabled).toArray(BooleanProperty[]::new)); TableView table = new TableView<>(objects); table.setEditable(true); @@ -170,7 +174,7 @@ private void exportList() { csvTable.write(Files.newOutputStream(path)); FXUtils.showFileInExplorer(path); - }).whenComplete(Schedulers.javafx() ,exception -> { + }).whenComplete(Schedulers.javafx(), exception -> { if (exception == null) { Controllers.dialog(path.toString(), i18n("message.success")); } else { From 4dce13855a91530e3bf3e84947fb4d752b054104 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Tue, 15 Oct 2024 18:26:12 +0800 Subject: [PATCH 026/169] Fix some i18n key mistake for es, ja & ru (#3341) --- HMCL/src/main/resources/assets/lang/I18N_es.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_ja.properties | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index b7ade7bd12..126a653c0a 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -153,7 +153,7 @@ button.edit=Editar button.install=Instalar button.export=Exportar button.no=No -botón.ok=Aceptar +button.ok=Aceptar button.refresh=Refrescar button.remove=Eliminar button.remove.confirm=¿Está seguro de querer eliminarlo definitivamente? Esta acción no se puede deshacer. @@ -517,7 +517,7 @@ game.crash.reason.shaders_mod=El juego actual no puede seguir ejecutándose porq game.crash.reason.rtss_forest_sodium=El juego actual se bloquea debido a una incompatibilidad entre RivaTuner Statistics Server (RTSS) y Sodium, lo que provoca el fallo del juego. Haz clic aquí para obtener más detalles. game.crash.reason.stacktrace=El motivo del fallo es desconocido. Puede ver los detalles haciendo clic en el botón "Registros".\n\ \n\ -Hay algunas palabras clave que pueden contener algunos Mod IDs. Puedes buscarlas en Internet para averiguar el problema por ti mismo..\n\ +Hay algunas palabras clave que pueden contener algunos Mod IDs. Puedes buscarlas en Internet para averiguar el problema por ti mismo.\n\ \n\ %s game.crash.reason.too_old_java=El juego se ha bloqueado porque estás utilizando una versión histórica de Java VM..\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 8e705640a9..8476fc6b96 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -128,9 +128,9 @@ archive.date=公開日 archive.file.name=名前 archive.version=バージョン -Assets.download=アセットのダウンロード -Assets.download_all=アセットの整合性チェック -Assets.index.malformed=アセットインデックスの形式が正しくありません。バージョン設定の[ゲームアセットファイルの更新]で再試行できます。 +assets.download=アセットのダウンロード +assets.download_all=アセットの整合性チェック +assets.index.malformed=アセットインデックスの形式が正しくありません。バージョン設定の[ゲームアセットファイルの更新]で再試行できます。 button.cancel=キャンセル button.change_source=ダウンロードソースの変更 @@ -152,8 +152,8 @@ button.yes=はい color.recent=推奨 color.custom=カスタムカラー -crack.NoClassDefFound=「HelloMinecraft!Launcher」ソフトウェアが破損していないことを確認してください。 -crack.user_fault=OSまたはJava環境が正しくインストールされていない可能性があり、クラッシュする可能性があります。Javaランタイム環境またはコンピュータを確認してください。 +crash.NoClassDefFound=「HelloMinecraft!Launcher」ソフトウェアが破損していないことを確認してください。 +crash.user_fault=OSまたはJava環境が正しくインストールされていない可能性があり、クラッシュする可能性があります。Javaランタイム環境またはコンピュータを確認してください。 curse.category.0=すべて From 32c3b694b38fa5f96ebefc6651cb7d4d162da4da Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Tue, 15 Oct 2024 18:47:38 +0800 Subject: [PATCH 027/169] Revise readme and platform docs [skip ci] (#3054) * Revise [skip ci] Squash previous commits. * Revise [skip ci] Unify badge style. * Revise [skip ci] Change the badge style of QQ group * Revise [skip ci] - Add Chinese variants (Traditional, Taiwan) - Compilation requirements for Java bump to 11+ - Various revisions * Revise [skip ci] Fix a link * Revise [skip ci] Revert a change * Revise [skip ci] * Revise [skip ci] * Revise [skip ci] --- PLATFORM.md | 40 ++++++++++++++-------------- PLATFORM_cn.md | 54 ++++++++++++++++++-------------------- PLATFORM_tw.md | 38 +++++++++++++++++++++++++++ README.md | 43 ++++++++++++++---------------- README_cn.md | 65 +++++++++++++++++++++++---------------------- README_tw.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 206 insertions(+), 105 deletions(-) create mode 100644 PLATFORM_tw.md create mode 100644 README_tw.md diff --git a/PLATFORM.md b/PLATFORM.md index 85aa1cbcf8..b60d0a9002 100644 --- a/PLATFORM.md +++ b/PLATFORM.md @@ -1,19 +1,19 @@ # Platform Support Status -English | [简体中文](PLATFORM_cn.md) +**English** | [简体中文](PLATFORM_cn.md) | [繁體中文](PLATFORM_tw.md) -| | Windows | Linux | Mac OS | FreeBSD | -|----------------------------|:--------------------------------------------------|:---------------------------|:------------------------------------------------------------------------|:---------------------------| +| | Windows | Linux | macOS | FreeBSD | +| -------------------------- | :----------------------------------------------- | :------------------------ | :--------------------------------------------------------------------- | :------------------------ | | x86-64 | ✅️ | ✅️ | ✅️ | 👌 (Minecraft 1.13~1.21.1) | -| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | -| ARM64 | 👌 (Minecraft 1.8~1.18.2)
✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.20.6) | 👌 (Minecraft 1.6~1.18.2)
✅ (Minecraft 1.19+)
✅ (use Rosetta 2) | ❔ | -| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | -| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | -| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.1) | / | / | -| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | -| LoongArch64 (Old World) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | -| PowerPC-64 (Little-Endian) | / | ❔ | / | / | -| S390x | / | ❔ | / | / | +| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | +| ARM64 | 👌 (Minecraft 1.8~1.18.2)
✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21) | 👌 (Minecraft 1.6~1.18.2)
✅ (Minecraft 1.19+)
✅ (use Rosetta 2) | ❔ | +| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | +| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | +| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.1) | / | / | +| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | +| LoongArch64 (Old World) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | +| PowerPC-64 (Little-Endian) | / | ❔ | / | / | +| S390x | / | ❔ | / | / | Legend: @@ -23,18 +23,16 @@ Legend: * 👌: Supported platforms. - Support is provided by HMCL, tested to work, but may have more issues than a fully supported platform. - Support for versions below Minecraft 1.6 is not guaranteed. + Support is provided by HMCL, tested to work, but may have more issues than a fully supported platform. + Support for versions below Minecraft 1.6 is not guaranteed. If you encounter a problem that does not exist on fully supported platforms, you can report it to HMCL. * ❔: Low level supported platforms. - HMCL can run on this platform and has some basic support. - However, launching the game directly is not yet available. - If you want to start the game, - you'll need to get the native libraries needed by Minecraft in other way and specify the native path in the instance settings. + HMCL can run on this platform and has some basic support. However, launching the game directly is not yet available. + If you want to start the game, you will need to get the native libraries needed by Minecraft in other way and specify the native path in the instance settings. -* /: Not applicable. +* `/`: Not applicable. - We have no plans to support these platforms at this time, mainly because we don't have the equipment to test them. - If you can help us adapt, please file a support request via issue. + We have no plans to support these platforms at this time, mainly because we do not have the equipment to test them. + If you can help us adapt, please file a support request via GitHub Issue. \ No newline at end of file diff --git a/PLATFORM_cn.md b/PLATFORM_cn.md index a952493ce5..660f5a319e 100644 --- a/PLATFORM_cn.md +++ b/PLATFORM_cn.md @@ -1,40 +1,38 @@ # 平台支持状态 -[English](PLATFORM.md) | 简体中文 +[English](PLATFORM.md) | **简体中文** | [繁體中文](PLATFORM_tw.md) -| | Windows | Linux | Mac OS | FreeBSD | -|----------------------------|:--------------------------------------------------|:---------------------------|:-----------------------------------------------------------------------|:--------------------------| -| x86-64 | ✅️ | ✅️ | ✅️ | 👌(Minecraft 1.13~1.21.1) | -| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | -| ARM64 | 👌 (Minecraft 1.8~1.18.2)
✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21) | 👌 (Minecraft 1.6~1.18.2)
✅ (Minecraft 1.19+)
✅ (使用 Rosetta 2) | ❔ | -| ARM32 | /️ | 👌 (Minecraft 1.6~1.20.1) | / | / | -| MIPS64el | / | 👌 (Minecraft 1.6~1.20.1) | / | / | -| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21) | / | / | -| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | -| LoongArch64 (旧世界) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | -| PowerPC-64 (Little-Endian) | / | ❔ | / | / | -| S390x | / | ❔ | / | / | +| | Windows | Linux | macOS | FreeBSD | +| -------------------------- | :----------------------------------------------- | :------------------------ | :---------------------------------------------------------------------- | :----------------------- | +| x86-64 | ✅️ | ✅️ | ✅️ | 👌(Minecraft 1.13~1.21.1) | +| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | +| ARM64 | 👌 (Minecraft 1.8~1.18.2)
✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21) | 👌 (Minecraft 1.6~1.18.2)
✅ (Minecraft 1.19+)
✅ (使用 Rosetta 2) | ❔ | +| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | +| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | +| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.1) | / | / | +| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | +| LoongArch64 (旧世界) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | +| PowerPC-64 (Little-Endian) | / | ❔ | / | / | +| S390x | / | ❔ | / | / | -图例: +图例: -* ✅: 官方支持的平台. +* ✅: 官方支持的平台 - 受 Mojang 官方支持. 在游戏中遇到的问题应该直接向 Mojang 反馈. + 受 Mojang 官方支持。在游戏中遇到的问题应该直接向 Mojang 反馈。 -* 👌: 支持的平台. +* 👌: 支持的平台 - 由 HMCL 提供支持, 经过测试可以正常运行, 但可能比得到全面支持的平台有更多问题. - 不保证支持 Minecraft 1.6 以下的版本. - 如果你遇到在得到全面支持的平台上不存在的问题, 可以向 HMCL 反馈. + 由 HMCL 提供支持,经过测试可以正常运行,但可能比得到全面支持的平台有更多问题。 + 不保证支持 Minecraft 1.6 以下的版本。 + 如果你遇到在得到全面支持的平台上不存在的问题,可以向 HMCL 反馈。 -* ❔: 低级别支持的平台. +* ❔: 低级别支持的平台 - HMCL 可以在这个平台上运行, 并且有一些基本的支持. - 但是, 还不能正常地启动游戏. - 如果你想正常启动游戏, - 则需要通过其他方式获得游戏所需的本地库(LWJGL), 并在版本设置中指定本地库路径. + HMCL 可以在这个平台上运行,并且有一些基本的支持。但是,还不能正常地启动游戏。 + 如果你想正常启动游戏,则需要通过其他方式获得游戏所需的本地库 (LWJGL),并在(全局)游戏设置中指定本地库路径。 -* /: 不支持的平台. +* `/`: 不支持的平台 - 我们目前还没有打算支持这些平台, 主要是因为我们没有测试这些平台的设备. - 如果你能帮助我们进行测试, 请通过提交 Issue 提出支持请求. + 我们目前还没有打算支持这些平台,主要是因为我们没有测试这些平台的设备。 + 如果你能帮助我们进行测试,请通过提交 Issue 提出支持请求。 \ No newline at end of file diff --git a/PLATFORM_tw.md b/PLATFORM_tw.md new file mode 100644 index 0000000000..58f20451d5 --- /dev/null +++ b/PLATFORM_tw.md @@ -0,0 +1,38 @@ +# 平臺支援狀態 + +[English](PLATFORM.md) | [简体中文](PLATFORM_cn.md) | **繁體中文** + +| | Windows | Linux | macOS | FreeBSD | +| -------------------------- | :----------------------------------------------- | :------------------------ | :---------------------------------------------------------------------- | :----------------------- | +| x86-64 | ✅️ | ✅️ | ✅️ | 👌(Minecraft 1.13~1.21.1) | +| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | +| ARM64 | 👌 (Minecraft 1.8~1.18.2)
✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21) | 👌 (Minecraft 1.6~1.18.2)
✅ (Minecraft 1.19+)
✅ (使用 Rosetta 2) | ❔ | +| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | +| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | +| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.1) | / | / | +| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | +| LoongArch64 (舊世界) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | +| PowerPC-64 (Little-Endian) | / | ❔ | / | / | +| S390x | / | ❔ | / | / | + +圖例: + +* ✅: 官方支援的平臺 + + 受 Mojang 官方支援。在遊戲中遇到的問題應該直接向 Mojang 回報。 + +* 👌: 支援的平臺 + + 由 HMCL 提供支援,經過測試可以正常執行,但可能比得到全面支援的平臺有更多問題。 + 不保證支援 Minecraft 1.6 以下的版本。 + 如果你遇到在得到全面支援的平臺上不存在的問題,可以向 HMCL 回報。 + +* ❔: 低級別支援的平臺 + + HMCL 可以在這個平臺上執行,並且有一些基本的支援。但是,還不能正常地啟動遊戲。 + 如果你想正常啟動遊戲,則需要透過其他方式獲得遊戲所需的本機庫 (LWJGL),並在(全域)遊戲設定中指定本機庫路徑。 + +* `/`: 不支援的平臺 + + 我們目前還沒有打算支援這些平臺,主要是因為我們沒有測試這些平臺的裝置。 + 如果你能幫助我們進行測試,請透過提交 Issue 提出支援請求。 \ No newline at end of file diff --git a/README.md b/README.md index d46d9a0d27..0afa0119df 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,18 @@ # ⛏ Hello Minecraft! Launcher 💎 [![Build Status](https://ci.huangyuhui.net/job/HMCL/badge/icon?.svg)](https://ci.huangyuhui.net/job/HMCL) -![Downloads](https://img.shields.io/github/downloads/huanghongxun/HMCL/total) -![Stars](https://img.shields.io/github/stars/huanghongxun/HMCL) +![Downloads](https://img.shields.io/github/downloads/huanghongxun/HMCL/total?style=flat) +![Stars](https://img.shields.io/github/stars/huanghongxun/HMCL?style=flat) [![Discord](https://img.shields.io/discord/995291757799538688.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/jVvC7HfM6U) -[![QQ Group](https://img.shields.io/badge/QQ-HMCL-brightgreen)](https://docs.hmcl.net/groups.html) +[![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=tencentqq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) -English | [中文](README_cn.md) +**English** | [简体中文](README_cn.md) | [繁體中文](README_tw.md) ## Introduction -HMCL is a cross-platform Minecraft launcher which supports Mod Management, Game Customizing, Auto Installing (Forge, NeoForge, Fabric, Quilt, LiteLoader and OptiFine), Modpack Creating, UI Customization, and more. +HMCL is a cross-platform Minecraft launcher which supports Mod Management, Game Customizing, ModLoader Installing (Forge, NeoForge, Fabric, Quilt, LiteLoader and OptiFine), Modpack Creating, UI Customization, and more. -HMCL has amazing cross-platform capabilities. -It can not only run on different operating systems such as Windows, Linux, and macOS, -but also supports multiple CPU architectures such as x86, arm, mips, and loongarch. -You can easily play Minecraft on different platforms through HMCL. +HMCL has amazing cross-platform capabilities. It can not only run on different operating systems such as Windows, Linux, and macOS, but also supports multiple CPU architectures such as x86, ARM, MIPS, and LoongArch. You can easily play Minecraft on different platforms through HMCL. For systems and CPU architectures supported by HMCL, see [this table](PLATFORM.md). @@ -43,7 +40,7 @@ The software is distributed under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.h If you want to submit a pull request, there are some requirements: -* IDE: Intellij IDEA +* IDE: IntelliJ IDEA * Compiler: Java 1.8 or Java 11+ * Do NOT modify `gradle` files @@ -59,16 +56,16 @@ Make sure you have Java installed with JavaFX 8 at least. Liberica Full JDK 8 or ## JVM Options (for debugging) -| Parameter | Description | -|----------------------------------------------|------------------------------------------------------------------------------------------------| -| `-Dhmcl.home=` | Override HMCL directory. | -| `-Dhmcl.self_integrity_check.disable=true` | Bypass the self integrity check when checking for update. | -| `-Dhmcl.bmclapi.override=` | Override API Root of BMCLAPI download provider, defaults to `https://bmclapi2.bangbang93.com`. | -| `-Dhmcl.font.override=` | Override font family. | -| `-Dhmcl.version.override=` | Override the version number. | -| `-Dhmcl.update_source.override=` | Override the update source for HMCL itself. | -| `-Dhmcl.authlibinjector.location=` | Use specified authlib-injector (instead of downloading one). | -| `-Dhmcl.openjfx.repo=` | Add custom Maven repository for download OpenJFX. | -| `-Dhmcl.native.encoding=` | Override the native encoding. | -| `-Dhmcl.microsoft.auth.id=` | Override Microsoft OAuth App ID. | -| `-Dhmcl.microsoft.auth.secret=` | Override Microsoft OAuth App secret. | +| Parameter | Description | +| -------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `-Dhmcl.home=` | Override HMCL directory | +| `-Dhmcl.self_integrity_check.disable=true` | Bypass the self integrity check when checking for update | +| `-Dhmcl.bmclapi.override=` | Override API Root of BMCLAPI download provider, defaults to `https://bmclapi2.bangbang93.com` | +| `-Dhmcl.font.override=` | Override font family | +| `-Dhmcl.version.override=` | Override the version number | +| `-Dhmcl.update_source.override=` | Override the update source for HMCL itself | +| `-Dhmcl.authlibinjector.location=` | Use specified authlib-injector (instead of downloading one) | +| `-Dhmcl.openjfx.repo=` | Add custom Maven repository for download OpenJFX | +| `-Dhmcl.native.encoding=` | Override the native encoding | +| `-Dhmcl.microsoft.auth.id=` | Override Microsoft OAuth App ID | +| `-Dhmcl.microsoft.auth.secret=` | Override Microsoft OAuth App secret | \ No newline at end of file diff --git a/README_cn.md b/README_cn.md index bd9e1a9718..c94c7e5b62 100644 --- a/README_cn.md +++ b/README_cn.md @@ -1,72 +1,71 @@ # ⛏ Hello Minecraft! Launcher 💎 [![Build Status](https://ci.huangyuhui.net/job/HMCL/badge/icon?.svg)](https://ci.huangyuhui.net/job/HMCL) -![Downloads](https://img.shields.io/github/downloads/huanghongxun/HMCL/total) -![Stars](https://img.shields.io/github/stars/huanghongxun/HMCL) +![Downloads](https://img.shields.io/github/downloads/huanghongxun/HMCL/total?style=flat) +![Stars](https://img.shields.io/github/stars/huanghongxun/HMCL?style=flat) [![Discord](https://img.shields.io/discord/995291757799538688.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/jVvC7HfM6U) -[![QQ Group](https://img.shields.io/badge/QQ-HMCL-brightgreen)](https://docs.hmcl.net/groups.html) +[![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=tencentqq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) -[English](README.md) | 中文 +[English](README.md) | **简体中文** | [繁體中文](README_tw.md) ## 简介 -HMCL 是一款跨平台 Minecraft 启动器, 支持 Mod 管理, 游戏自定义, 游戏自动安装 (Forge, NeoForge, Fabric, Quilt, LiteLoader 与 OptiFine), 整合包创建, 界面自定义等功能. +HMCL 是一款跨平台 Minecraft 启动器,支持模组管理、游戏自定义、游戏自动安装 (Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine)、整合包创建、界面自定义等功能。 -HMCL 有着强大的跨平台能力. 它不仅支持 Windows、Linux、macOS 等常见的操作系统,同时也支持 x86、ARM、MIPS 和 LoongArch 等不同的 CPU 架构. -您可以使用 HMCL 在不同平台上轻松的游玩 Minecraft. +HMCL 有着强大的跨平台能力。它不仅支持 Windows、Linux、macOS 等常见的操作系统,同时也支持 x86、ARM、MIPS 和 LoongArch 等不同的 CPU 架构。你可以使用 HMCL 在不同平台上轻松地游玩 Minecraft。 -如果您想要了解 HMCL 对不同平台的支持程度,请参见[此表格](PLATFORM_cn.md). +如果你想要了解 HMCL 对不同平台的支持程度,请参见 [此表格](PLATFORM_cn.md)。 ## 下载 -请从 [HMCL 官网](https://hmcl.huangyuhui.net/download) 下载最新版本的 HMCL. +请从 [HMCL 官网](https://hmcl.huangyuhui.net/download) 下载最新版本的 HMCL。 -你也可以在 [GitHub Releases](https://github.com/HMCL-dev/HMCL/releases) 中下载最新版本的 HMCL. +你也可以在 [GitHub Releases](https://github.com/HMCL-dev/HMCL/releases) 中下载最新版本的 HMCL。 -虽然并不强制, 但仍建议通过 HMCL 官网下载启动器. +虽然并不强制,但仍建议通过 HMCL 官网下载启动器。 ## 开源协议 -该程序在 [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) 开源协议下发布, 同时附有附加条款. +该程序在 [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) 开源协议下发布,同时附有附加条款。 ### 附加条款 (依据 GPLv3 开源协议第七条) -1. 当您分发该程序的修改版本时, 您必须以一种合理的方式修改该程序的名称或版本号, 以示其与原始版本不同. (依据 [GPLv3, 7(c)](https://github.com/HMCL-dev/HMCL/blob/11820e31a85d8989e41d97476712b07e7094b190/LICENSE#L372-L374)) +1. 当你分发该程序的修改版本时,你必须以一种合理的方式修改该程序的名称或版本号,以示其与原始版本不同。(依据 [GPLv3, 7(c)](https://github.com/HMCL-dev/HMCL/blob/11820e31a85d8989e41d97476712b07e7094b190/LICENSE#L372-L374)) - 该程序的名称及版本号可在[此处](https://github.com/HMCL-dev/HMCL/blob/javafx/HMCL/src/main/java/org/jackhuang/hmcl/Metadata.java#L33-L35)修改. + 该程序的名称及版本号可在 [此处](https://github.com/HMCL-dev/HMCL/blob/javafx/HMCL/src/main/java/org/jackhuang/hmcl/Metadata.java#L33-L35) 修改。 -2. 您不得移除该程序所显示的版权声明. (依据 [GPLv3, 7(b)](https://github.com/HMCL-dev/HMCL/blob/11820e31a85d8989e41d97476712b07e7094b190/LICENSE#L368-L370)) +2. 你不得移除该程序所显示的版权声明。(依据 [GPLv3, 7(b)](https://github.com/HMCL-dev/HMCL/blob/11820e31a85d8989e41d97476712b07e7094b190/LICENSE#L368-L370)) ## 贡献 -如果您想提交一个 Pull Request, 必须遵守如下要求: +如果你想提交一个 Pull Request,必须遵守如下要求: -* IDE: Intellij IDEA -* 编译器: Java 1.8 或 Java 11+ +* IDE:IntelliJ IDEA +* 编译器:Java 1.8 或 Java 11+ * **不要**修改 `gradle` 相关文件 ### 编译 -于项目根目录执行以下命令: +于项目根目录执行以下命令: ```bash ./gradlew clean build ``` -请确保您至少安装了含有 JavaFX 8 的 Java. 建议使用 Liberica Full JDK 8 或更高版本. +请确保你至少安装了含有 JavaFX 8 的 Java。建议使用 Liberica Full JDK 8 或更高版本。 ## JVM 选项 (用于调试) -| 参数 | 简介 | -|----------------------------------------------|----------------------------------------------------------------| -| `-Dhmcl.home=` | 覆盖 HMCL 数据文件夹. | -| `-Dhmcl.self_integrity_check.disable=true` | 检查更新时绕过本体完整性检查. | -| `-Dhmcl.bmclapi.override=` | 覆盖 BMCLAPI 的 API Root, 默认值为 `https://bmclapi2.bangbang93.com`. | -| `-Dhmcl.font.override=` | 覆盖字族. | -| `-Dhmcl.version.override=` | 覆盖版本号. | -| `-Dhmcl.update_source.override=` | 覆盖 HMCL 更新源. | -| `-Dhmcl.authlibinjector.location=` | 使用指定的 authlib-injector (而非下载一个). | -| `-Dhmcl.openjfx.repo=` | 添加用于下载 OpenJFX 的自定义 Maven 仓库 | -| `-Dhmcl.native.encoding=` | 覆盖原生编码. | -| `-Dhmcl.microsoft.auth.id=` | 覆盖 Microsoft OAuth App ID. | -| `-Dhmcl.microsoft.auth.secret=` | 覆盖 Microsoft OAuth App 密钥. | +| 参数 | 简介 | +| -------------------------------------------- | -------------------------------------------------------------------- | +| `-Dhmcl.home=` | 覆盖 HMCL 数据文件夹 | +| `-Dhmcl.self_integrity_check.disable=true` | 检查更新时绕过本体完整性检查 | +| `-Dhmcl.bmclapi.override=` | 覆盖 BMCLAPI 的 API Root,默认值为 `https://bmclapi2.bangbang93.com` | +| `-Dhmcl.font.override=` | 覆盖字族 | +| `-Dhmcl.version.override=` | 覆盖版本号 | +| `-Dhmcl.update_source.override=` | 覆盖 HMCL 更新源 | +| `-Dhmcl.authlibinjector.location=` | 使用指定的 authlib-injector (而非下载一个) | +| `-Dhmcl.openjfx.repo=` | 添加用于下载 OpenJFX 的自定义 Maven 仓库 | +| `-Dhmcl.native.encoding=` | 覆盖原生编码 | +| `-Dhmcl.microsoft.auth.id=` | 覆盖 Microsoft OAuth App ID | +| `-Dhmcl.microsoft.auth.secret=` | 覆盖 Microsoft OAuth App 密钥 | \ No newline at end of file diff --git a/README_tw.md b/README_tw.md new file mode 100644 index 0000000000..3441b4ccb2 --- /dev/null +++ b/README_tw.md @@ -0,0 +1,71 @@ +# ⛏ Hello Minecraft! Launcher 💎 + +[![Build Status](https://ci.huangyuhui.net/job/HMCL/badge/icon?.svg)](https://ci.huangyuhui.net/job/HMCL) +![Downloads](https://img.shields.io/github/downloads/huanghongxun/HMCL/total?style=flat) +![Stars](https://img.shields.io/github/stars/huanghongxun/HMCL?style=flat) +[![Discord](https://img.shields.io/discord/995291757799538688.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/jVvC7HfM6U) +[![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=tencentqq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) + +[English](README.md) | [简体中文](README_cn.md) | **繁體中文** + +## 簡介 + +HMCL 是一款跨平臺 Minecraft 啟動器,支援模組管理、遊戲自訂、遊戲自動安裝 (Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine)、模組包建立、介面自訂等功能。 + +HMCL 有著強大的跨平臺能力。它不僅支援 Windows、Linux、macOS 等常見的作業系統,同時也支援 x86、ARM、MIPS 和 LoongArch 等不同的 CPU 架構。你可以使用 HMCL 在不同平臺上輕鬆地遊玩 Minecraft。 + +如果你想要了解 HMCL 對不同平臺的支援程度,請參見 [此表格](PLATFORM_tw.md)。 + +## 下載 + +請從 [HMCL 官網](https://hmcl.huangyuhui.net/download) 下載最新版本的 HMCL。 + +你也可以在 [GitHub Releases](https://github.com/HMCL-dev/HMCL/releases) 中下載最新版本的 HMCL。 + +雖然並不強制,但仍建議透過 HMCL 官網下載啟動器。 + +## 開源協議 + +該程式在 [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) 開源協議下發布,同時附有附加條款。 + +### 附加條款 (依據 GPLv3 開源協議第七條) + +1. 當你分發該程式的修改版本時,你必須以一種合理的方式修改該程式的名稱或版本號,以示其與原始版本不同。(依據 [GPLv3, 7(c)](https://github.com/HMCL-dev/HMCL/blob/11820e31a85d8989e41d97476712b07e7094b190/LICENSE#L372-L374)) + + 該程式的名稱及版本號可在 [此處](https://github.com/HMCL-dev/HMCL/blob/javafx/HMCL/src/main/java/org/jackhuang/hmcl/Metadata.java#L33-L35) 修改。 + +2. 你不得移除該程式所顯示的版權宣告。(依據 [GPLv3, 7(b)](https://github.com/HMCL-dev/HMCL/blob/11820e31a85d8989e41d97476712b07e7094b190/LICENSE#L368-L370)) + +## 貢獻 + +如果你想提交一個 Pull Request,必須遵守如下要求: + +* IDE:IntelliJ IDEA +* 編譯器:Java 1.8 或 Java 11+ +* **不要**修改 `gradle` 相關文件 + +### 編譯 + +於項目根目錄執行以下指令: + +```bash +./gradlew clean build +``` + +請確保你至少安裝了含有 JavaFX 8 的 Java。建議使用 Liberica Full JDK 8 或更高版本。 + +## JVM 選項 (用於除錯) + +| 參數 | 簡介 | +| -------------------------------------------- | -------------------------------------------------------------------- | +| `-Dhmcl.home=` | 覆蓋 HMCL 使用者資料夾 | +| `-Dhmcl.self_integrity_check.disable=true` | 檢查更新時繞過本體完整性檢查 | +| `-Dhmcl.bmclapi.override=` | 覆蓋 BMCLAPI 的 API Root,預設值為 `https://bmclapi2.bangbang93.com` | +| `-Dhmcl.font.override=` | 覆蓋字族 | +| `-Dhmcl.version.override=` | 覆蓋版本號 | +| `-Dhmcl.update_source.override=` | 覆蓋 HMCL 更新源 | +| `-Dhmcl.authlibinjector.location=` | 使用指定的 authlib-injector (而非下載一個) | +| `-Dhmcl.openjfx.repo=` | 添加用於下載 OpenJFX 的自訂 Maven 倉庫 | +| `-Dhmcl.native.encoding=` | 覆蓋原生編碼 | +| `-Dhmcl.microsoft.auth.id=` | 覆蓋 Microsoft OAuth App ID | +| `-Dhmcl.microsoft.auth.secret=` | 覆蓋 Microsoft OAuth App 金鑰 | \ No newline at end of file From 5b345affec1c9e38853adf41e92f89ccc7c1b065 Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 15 Oct 2024 18:47:57 +0800 Subject: [PATCH 028/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20Java=20=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E5=8A=9F=E8=83=BD=20(#3342)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update --- .../java/disco/DiscoFetchJavaListTask.java | 2 +- .../java/disco/DiscoJavaDistribution.java | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java index 036822ce57..d4f333b34e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java @@ -79,7 +79,7 @@ public void execute() throws Exception { TreeMap map = new TreeMap<>(); for (DiscoJavaRemoteVersion version : result) { - if (!distribution.getApiParameter().equals(version.getDistribution())) + if (!distribution.testVersion(version)) continue; int jdkVersion = version.getJdkVersion(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java index 80611d674b..7cc6c3e20a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java @@ -46,7 +46,16 @@ public enum DiscoJavaDistribution implements JavaDistribution> getFetchJavaVersionsTask(DownloadProvider provider, Platform platform, JavaPackageType packageType) { return new DiscoFetchJavaListTask(provider, this, platform, packageType); } + + public boolean testVersion(DiscoJavaRemoteVersion version) { + return this.getApiParameter().equals(version.getDistribution()); + } } From fab32a6d51389a0d004f2d94f682b6b2d9efe071 Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 15 Oct 2024 19:05:22 +0800 Subject: [PATCH 029/169] Bump commons-compress to 1.27.1 (#3344) --- HMCLCore/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/build.gradle.kts b/HMCLCore/build.gradle.kts index f5cc2f8fbe..09b4f190ca 100644 --- a/HMCLCore/build.gradle.kts +++ b/HMCLCore/build.gradle.kts @@ -11,7 +11,7 @@ dependencies { api("org.jenkins-ci:constant-pool-scanner:1.2") api("com.github.steveice10:opennbt:1.5") api("org.nanohttpd:nanohttpd:2.3.1") - api("org.apache.commons:commons-compress:1.25.0") + api("org.apache.commons:commons-compress:1.27.1") api("org.jsoup:jsoup:1.18.1") compileOnlyApi("org.jetbrains:annotations:24.1.0") From 936285847c2269f2013f4c1a36a8c3bcb7f0344e Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 15 Oct 2024 19:10:02 +0800 Subject: [PATCH 030/169] Bump Gson to 2.11.0 (#3345) --- HMCLCore/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/build.gradle.kts b/HMCLCore/build.gradle.kts index 09b4f190ca..abe7e5a211 100644 --- a/HMCLCore/build.gradle.kts +++ b/HMCLCore/build.gradle.kts @@ -4,7 +4,7 @@ plugins { dependencies { api("org.glavo:simple-png-javafx:0.3.0") - api("com.google.code.gson:gson:2.10.1") + api("com.google.code.gson:gson:2.11.0") api("com.moandjiezana.toml:toml4j:0.7.2") api("org.tukaani:xz:1.9") api("org.hildan.fxgson:fx-gson:5.0.0") From 58e32c44595cdda7d81662868e361a8a5d75b4ab Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 15 Oct 2024 19:56:32 +0800 Subject: [PATCH 031/169] =?UTF-8?q?=E5=BD=93=E6=95=B4=E5=90=88=E5=8C=85?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E6=8F=8F=E8=BF=B0=E6=97=B6=EF=BC=8C=E9=9A=90?= =?UTF-8?q?=E8=97=8F=E6=9F=A5=E7=9C=8B=E6=95=B4=E5=90=88=E5=8C=85=E6=8F=8F?= =?UTF-8?q?=E8=BF=B0=E6=8C=89=E9=92=AE=20(#3347)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/ui/download/LocalModpackPage.java | 5 +++++ .../java/org/jackhuang/hmcl/ui/download/ModpackPage.java | 3 ++- .../org/jackhuang/hmcl/ui/download/RemoteModpackPage.java | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java index 3b8525b06f..eb9e3f441a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java @@ -36,6 +36,7 @@ import org.jackhuang.hmcl.ui.construct.RequiredValidator; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.WizardController; +import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.io.FileUtils; @@ -79,6 +80,8 @@ public LocalModpackPage(WizardController controller) { }); } + btnDescription.setVisible(false); + File selectedFile; Optional filePath = tryCast(controller.getSettings().get(MODPACK_FILE), File.class); if (filePath.isPresent()) { @@ -134,6 +137,8 @@ public LocalModpackPage(WizardController controller) { // trim: https://github.com/HMCL-dev/HMCL/issues/962 txtModpackName.setText(manifest.getName().trim()); } + + btnDescription.setVisible(StringUtils.isNotBlank(manifest.getDescription())); } }).start(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java index c54317e412..107429813b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java @@ -24,6 +24,7 @@ public abstract class ModpackPage extends SpinnerPane implements WizardPage { protected final Label lblAuthor; protected final JFXTextField txtModpackName; protected final JFXButton btnInstall; + protected final JFXButton btnDescription; protected ModpackPage(WizardController controller) { this.controller = controller; @@ -77,7 +78,7 @@ protected ModpackPage(WizardController controller) { BorderPane descriptionPane = new BorderPane(); { - JFXButton btnDescription = new JFXButton(i18n("modpack.description")); + btnDescription = new JFXButton(i18n("modpack.description")); btnDescription.getStyleClass().add("jfx-button-border"); btnDescription.setOnAction(e -> onDescribe()); descriptionPane.setLeft(btnDescription); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java index b29583fd39..1123f3fd8a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java @@ -27,6 +27,7 @@ import org.jackhuang.hmcl.ui.construct.RequiredValidator; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.WizardController; +import org.jackhuang.hmcl.util.StringUtils; import java.io.IOException; import java.util.Map; @@ -69,6 +70,8 @@ public RemoteModpackPage(WizardController controller) { new Validator(i18n("install.new_game.already_exists"), str -> !profile.getRepository().versionIdConflicts(str)), new Validator(i18n("install.new_game.malformed"), HMCLGameRepository::isValidVersionId)); } + + btnDescription.setVisible(StringUtils.isNotBlank(manifest.getDescription())); } @Override From 1033389c385a4cbb82733081d589123c2917d7d2 Mon Sep 17 00:00:00 2001 From: Glavo Date: Wed, 16 Oct 2024 22:15:13 +0800 Subject: [PATCH 032/169] Revert "Bump commons-compress to 1.27.1 (#3344)" (#3351) This reverts commit fab32a6d51389a0d004f2d94f682b6b2d9efe071. --- HMCLCore/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/build.gradle.kts b/HMCLCore/build.gradle.kts index abe7e5a211..53ae7fcb0b 100644 --- a/HMCLCore/build.gradle.kts +++ b/HMCLCore/build.gradle.kts @@ -11,7 +11,7 @@ dependencies { api("org.jenkins-ci:constant-pool-scanner:1.2") api("com.github.steveice10:opennbt:1.5") api("org.nanohttpd:nanohttpd:2.3.1") - api("org.apache.commons:commons-compress:1.27.1") + api("org.apache.commons:commons-compress:1.25.0") api("org.jsoup:jsoup:1.18.1") compileOnlyApi("org.jetbrains:annotations:24.1.0") From 9f3fb7aff647ff18c5ec4987dbb8169d96fe9c60 Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 17 Oct 2024 04:20:09 +0800 Subject: [PATCH 033/169] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E5=AE=89=E8=A3=85=20zip=20=E6=A0=BC=E5=BC=8F=E7=9A=84=20Java?= =?UTF-8?q?=20=E5=8E=8B=E7=BC=A9=E5=8C=85=E7=9A=84=E9=97=AE=E9=A2=98=20(#3?= =?UTF-8?q?352)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java index 86d3a0c2ea..a338b3c3f4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java @@ -151,7 +151,7 @@ private void onAddJavaHome(Path file) { private void onInstallArchive(Path file) { Task.supplyAsync(() -> { - try (ArchiveFileTree tree = TarFileTree.open(file)) { + try (ArchiveFileTree tree = ArchiveFileTree.open(file)) { JavaInfo info = JavaInfo.fromArchive(tree); if (!JavaManager.isCompatible(info.getPlatform())) From 49ea9e5da059275d64e4225d1646805b8c748b6d Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 17 Oct 2024 12:48:17 +0800 Subject: [PATCH 034/169] fix checkstyle (#3353) --- .../main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java index a338b3c3f4..6eb9c2d450 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java @@ -50,7 +50,6 @@ 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.tree.TarFileTree; import java.io.*; import java.nio.file.Files; From 457490276cf4d4db06113de0880d136d6bb0dfce Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Fri, 18 Oct 2024 02:17:47 +0800 Subject: [PATCH 035/169] Update CallerFinder (#3350) * Update CallerFinder * Revert "Fix #2687 (#2688)" This reverts commit 207b4d003384b048abe069e4888e980741d7bbf6. * update --------- Co-authored-by: Glavo --- .../java11/org/jackhuang/hmcl/util/logging/CallerFinder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java11/org/jackhuang/hmcl/util/logging/CallerFinder.java b/HMCL/src/main/java11/org/jackhuang/hmcl/util/logging/CallerFinder.java index 89547137f8..8c934cdaab 100644 --- a/HMCL/src/main/java11/org/jackhuang/hmcl/util/logging/CallerFinder.java +++ b/HMCL/src/main/java11/org/jackhuang/hmcl/util/logging/CallerFinder.java @@ -9,13 +9,13 @@ * @author Glavo */ final class CallerFinder { - private static final StackWalker WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); private static final String PACKAGE_PREFIX = CallerFinder.class.getPackageName() + "."; private static final Predicate PREDICATE = stackFrame -> !stackFrame.getClassName().startsWith(PACKAGE_PREFIX); private static final Function, Optional> FUNCTION = stream -> stream.filter(PREDICATE).findFirst(); + private static final Function FRAME_MAPPING = frame -> frame.getClassName() + "." + frame.getMethodName(); static String getCaller() { - return WALKER.walk(FUNCTION).map(it -> it.getClassName() + "." + it.getMethodName()).orElse(null); + return StackWalker.getInstance().walk(FUNCTION).map(FRAME_MAPPING).orElse(null); } private CallerFinder() { From f68e056e47d96f83a7f1ee7237cb6c5c68ebd71f Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 19 Oct 2024 21:28:03 +0800 Subject: [PATCH 036/169] Revise zh_CN part 1 (#3343) * Revise zh_CN part 1 * Update Co-authored-by: Burning_TNT --------- Co-authored-by: Burning_TNT --- .../assets/lang/I18N_zh_CN.properties | 166 +++++++++--------- 1 file changed, 83 insertions(+), 83 deletions(-) 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 4a2fb0073f..2321f05bc3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -19,9 +19,9 @@ # Contributors: huangyuhui about=关于 about.copyright=版权 -about.copyright.statement=版权所有 © 2024 huangyuhui. +about.copyright.statement=版权所有 © 2024 huangyuhui about.author=作者 -about.author.statement=bilibili ID: @huanghongxun +about.author.statement=bilibili @huanghongxun about.claim=用户协议 about.claim.statement=点击链接以查看全文 about.dependency=依赖 @@ -29,21 +29,21 @@ about.legal=法律声明 about.thanks_to=鸣谢 about.thanks_to.bangbang93.statement=提供 BMCLAPI 下载源。请赞助支持 BMCLAPI! about.thanks_to.burningtnt.statement=为 HMCL 贡献许多技术支持 -about.thanks_to.contributors=所有通过 Issues、Pull Requests 等方式参与本项目的贡献者 -about.thanks_to.contributors.statement=没有开源社区的支持,Hello Minecraft! Launcher 就无法走到今天 +about.thanks_to.contributors=所有通过 Issue、Pull Request 等方式参与本项目的贡献者 +about.thanks_to.contributors.statement=没有开源社区的支持,HMCL 就无法走到今天 about.thanks_to.gamerteam.statement=提供默认背景图 about.thanks_to.glavo.statement=负责 HMCL 的日常维护 about.thanks_to.zekerzhayard.statement=为 HMCL 贡献许多技术支持 about.thanks_to.zkitefly.statement=负责维护 HMCL 的文档 -about.thanks_to.mcbbs=MCBBS 我的世界中文论坛 +about.thanks_to.mcbbs=MCBBS (我的世界中文论坛) about.thanks_to.mcbbs.statement=提供 MCBBS 下载源 (现已停止服务) -about.thanks_to.mcmod=MC 百科 -about.thanks_to.mcmod.statement=提供模组中文名映射表与 Mod 百科 +about.thanks_to.mcmod=MC 百科 (mcmod.cn) +about.thanks_to.mcmod.statement=提供模组简体中文名映射表与模组百科 about.thanks_to.red_lnn.statement=提供默认背景图 -about.thanks_to.shulkersakura.statement=提供 HMCL 的图标 +about.thanks_to.shulkersakura.statement=提供 HMCL 的徽标 about.thanks_to.users=HMCL 用户群成员 about.thanks_to.users.statement=感谢用户群成员赞助充电、积极催更、反馈问题、出谋划策 -about.thanks_to.yushijinhun.statement=authlib-injector 相关支持 +about.thanks_to.yushijinhun.statement=提供 authlib-injector 相关支持 about.open_source=开源 about.open_source.statement=GPL v3 (https://github.com/HMCL-dev/HMCL) @@ -58,28 +58,28 @@ account.create.authlibInjector=添加外置登录账户 (authlib-injector) account.email=邮箱 account.failed=账户刷新失败 account.failed.character_deleted=此角色已被删除 -account.failed.connect_authentication_server=无法连接认证服务器,可能是网络问题,请检查设备能否正常上网或使用代理服务\n你可以点击右上角帮助按钮进行求助。 -account.failed.connect_injector_server=无法连接认证服务器,可能是网络问题,请检查设备是否能正常上网,检查 URL 是否输入错误,或使用代理服务\n你可以点击右上角帮助按钮进行求助。 -account.failed.injector_download_failure=无法下载 authlib-injector,可能是网络问题,请检查设备是否能正常上网、尝试切换下载源或使用代理服务\n你可以点击右上角帮助按钮进行求助。 -account.failed.invalid_credentials=你的用户名或密码错误,或登录次数过多被暂时禁止登录,请稍后再试 +account.failed.connect_authentication_server=无法连接认证服务器,可能是网络问题,请检查设备能否正常上网或使用代理服务。\n你可以点击右上角帮助按钮进行求助。 +account.failed.connect_injector_server=无法连接认证服务器,可能是网络问题,请检查设备是否能正常上网、URL 是否输入错误,或使用代理服务。\n你可以点击右上角帮助按钮进行求助。 +account.failed.injector_download_failure=无法下载 authlib-injector,可能是网络问题,请检查设备是否能正常上网、尝试切换下载源或使用代理服务。\n你可以点击右上角帮助按钮进行求助。 +account.failed.invalid_credentials=你的用户名或密码错误,或登录次数过多被暂时禁止登录,请稍后再试。 account.failed.invalid_password=无效的密码 account.failed.invalid_token=请尝试登出并重新输入密码登录 -account.failed.migration=你的账户需要被迁移至微软账户。如果你已经迁移,你需要使用微软登录方式登录迁移后的微软账户 +account.failed.migration=你的账户需要迁移至微软账户。如果你已经迁移,你需要使用微软账户登录迁移后的账户。 account.failed.no_character=该账户没有角色 account.failed.server_disconnected=无法访问登录服务器,账户信息刷新失败。\n\ 你可以选择“再次刷新账户”重新尝试。\n\ - 你也可以选择“跳过账户刷新”继续启动游戏,但可能会使账户信息不是最新的。\n\ - 若最近没有刷新账户信息,则可能导致账户信息过期失效,\n\ - 若为 微软账户 启动游戏,账户信息过期失效可能将无法进入需账户验证的服务器。\n\ - 若尝试多次无法成功刷新,可尝试重新添加该账户尝试解决该问题。\n\ + 你也可以选择“跳过账户刷新”继续启动游戏,但可能会导致账户信息未同步更新。\n\ + 若最近没有刷新账户信息,则可能导致账户信息过期失效。\n\ + 若使用微软账户或外置登录账户启动游戏,账户信息过期失效可能将无法进入需在线验证的服务器。\n\ + 若尝试多次无法成功刷新,可尝试重新添加该账户,或许会解决该问题。\n\ 你可以点击右上角帮助按钮进行求助。 -account.failed.server_response_malformed=无法解析认证服务器响应,可能是服务器故障 +account.failed.server_response_malformed=无法解析认证服务器响应,可能是服务器故障。 account.failed.ssl=连接服务器时发生了 SSL 错误,可能网站证书已过期或你使用的 Java 版本过低,请尝试更新 Java,或关闭网络代理后再试。\n你可以点击右上角帮助按钮进行求助。 account.failed.wrong_account=登录了错误的账户 -account.hmcl.hint=你需要点击“登录”按钮,并在打开的网页中完成登录 +account.hmcl.hint=你需要点击“登录”按钮,并在打开的网页中完成登录。 account.injector.add=添加认证服务器 -account.injector.empty=无(点击右侧加号添加) -account.injector.http=警告:此服务器使用不安全的 HTTP 协议,您的密码在登录时会被明文传输。 +account.injector.empty=无 (点击右侧加号添加) +account.injector.http=警告:此服务器使用不安全的 HTTP 协议,你的密码在登录时会被明文传输。 account.injector.link.homepage=主页 account.injector.link.register=注册 account.injector.server=认证服务器 @@ -90,26 +90,26 @@ account.login.hint=我们不会保存你的密码 account.login.skip=跳过账户刷新 account.login.retry=再次刷新账户 account.login.refresh=重新登录 -account.login.refresh.microsoft.hint=因为账户授权失效,你需要重新添加微软账户 +account.login.refresh.microsoft.hint=由于账户授权失效,你需要重新添加微软账户。 account.logout=登出 account.register=注册 account.manage=账户列表 -account.copy_uuid=复制该账户的 UUID。 +account.copy_uuid=复制该账户的 UUID account.methods=登录方式 account.methods.authlib_injector=外置登录 (authlib-injector) account.methods.microsoft=微软账户 account.methods.microsoft.birth=如何修改账户出生日期 -account.methods.microsoft.close_page=已完成微软账户授权,接下来启动器还需要完成剩余登录步骤。你已经可以关闭本页面了。 +account.methods.microsoft.close_page=已完成微软账户授权,接下来启动器还需要完成其余登录步骤。你现在可以关闭本页面了。 account.methods.microsoft.deauthorize=解除账户授权 -account.methods.microsoft.error.add_family=请点击上方【账户设置页】更改你的账户的出生日期,使年龄满 18 岁以上。或将账户加入到家庭中。\n你可以点击右上角帮助按钮进行求助。 -account.methods.microsoft.error.add_family_probably=请点击上方【账户设置页】更改你的账户的出生日期,使年龄满 18 岁以上。或将账户加入到家庭中。\n你可以点击右上角帮助按钮进行求助。 -account.methods.microsoft.error.country_unavailable=你所在的国家或地区不受 XBox Live 的支持。 -account.methods.microsoft.error.missing_xbox_account=请点击上方【创建档案】关联 XBox 账户。\n你可以点击右上角帮助按钮进行求助。 -account.methods.microsoft.error.no_character=请确认你购买了 Minecraft: Java 版。若已购买,该账户未包含 Minecraft Java 版购买记录\n请点击【创建档案】创建游戏档案。\n你可以点击右上角帮助按钮进行求助。 +account.methods.microsoft.error.add_family=请点击上方“账户设置页”更改你的账户出生日期,使年龄满 18 岁以上,或将账户加入到家庭中。\n你可以点击右上角帮助按钮进行求助。 +account.methods.microsoft.error.add_family_probably=请点击上方“账户设置页”更改你的账户出生日期,使年龄满 18 岁以上,或将账户加入到家庭中。\n你可以点击右上角帮助按钮进行求助。 +account.methods.microsoft.error.country_unavailable=你所在的国家或地区不受 Xbox Live 的支持。 +account.methods.microsoft.error.missing_xbox_account=请点击上方“创建档案”关联 Xbox 账户。\n你可以点击右上角帮助按钮进行求助。 +account.methods.microsoft.error.no_character=请确认你已经购买了 Minecraft: Java 版。\n若已购买,则可能未创建游戏档案,请点击上方“创建档案”以创建游戏档案。\n你可以点击右上角帮助按钮进行求助。 account.methods.microsoft.error.unknown=未知问题。错误码:%d。\n你可以点击右上角帮助按钮进行求助。 -account.methods.microsoft.error.wrong_verify_method=请在 Microsoft 账户登陆页面使用账户 + 密码登录。请不要使用验证码登录。\n你可以点击右上角帮助按钮进行求助。 +account.methods.microsoft.error.wrong_verify_method=请在微软账户登录页面使用密码登录,不要使用验证码登录。\n你可以点击右上角帮助按钮进行求助。 account.methods.microsoft.logging_in=登录中…… -account.methods.microsoft.makegameidsettings=创建档案/编辑档案名称 +account.methods.microsoft.makegameidsettings=创建档案 / 编辑档案名称 account.methods.microsoft.hint=你需要按照以下步骤添加账户:\n\ 1.点击“登录”按钮\n\ 2.在网页浏览器显示的网站中输入 HMCL 显示的代码(自动拷贝,直接粘贴即可),并点击“下一步”\n\ @@ -132,37 +132,37 @@ account.methods.microsoft.manual=你需要按照以下步骤添加:\n\ account.methods.microsoft.profile=账户设置页 account.methods.microsoft.purchase=购买 Minecraft account.methods.forgot_password=忘记密码 -account.methods.microsoft.snapshot=你正在使用非官方构建的 HMCL,请下载官方构建进行微软登录。 +account.methods.microsoft.snapshot=你正在使用第三方提供的 HMCL,请下载官方版本来登录微软账户。 account.methods.microsoft.snapshot.website=官方网站 account.methods.offline=离线模式 account.methods.offline.name.special_characters=建议使用英文字符、数字以及下划线命名 -account.methods.offline.name.invalid=正常情况下,游戏用户名只能包括英文字符、数字以及下划线,且长度不能超过 16 个字符。\n\ - 一些合法的用户名:HuangYu,huang_Yu,Huang_Yu_123;\n\ - 一些不合法的用户名:黄鱼,Huang Yu,Huang-Yu_%%%,Huang_Yu_hello_world_hello_world。\n\ - 如果你相信服务器端有相应的模组或插件来解除此限制,你可以忽略本警告。\n\ +account.methods.offline.name.invalid=游戏用户名通常仅允许使用英文字母、数字及下划线,且长度不能超过 16 个字符。\n\ + \ · 一些合法用户名:HuangYu、huang_Yu、Huang_Yu_123;\n\ + \ · 一些非法用户名:黄鱼、Huang Yu、Huang-Yu_%%%、Huang_Yu_hello_world_hello_world。\n\ + 如果你相信服务端有相应模组或插件解除此限制,可以忽略本警告。\n\ 如遇到问题,你可以点击右上角帮助按钮进行求助。 account.methods.offline.uuid=UUID -account.methods.offline.uuid.hint=UUID 是 Minecraft 对玩家角色的唯一标识符,每个启动器生成 UUID 的方式可能不同。通过修改 UUID 选项至原启动器所生成的 UUID,你可以保证在切换启动器后,游戏还能将你的游戏角色识别为给定 UUID 所对应的角色,从而保留原来角色的背包物品。UUID 选项为高级选项,除非你知道你在做什么,否则你不需要调整该选项。 +account.methods.offline.uuid.hint=UUID 是 Minecraft 玩家的唯一标识符,每个启动器生成 UUID 的方式可能不同。通过将 UUID 修改为原启动器所生成的 UUID,你可以保证在切换启动器后,游戏还能将你的游戏角色识别为给定 UUID 所对应的角色,从而保留原角色的背包物品。UUID 选项为高级选项,除非你知道你在做什么,否则你不需要调整该选项。 account.methods.offline.uuid.malformed=格式错误 account.missing=没有游戏账户 account.missing.add=点击此处添加账户 -account.move_to_global=转换为全局账户\n该账户的信息会保存至用户目录的配置文件中 -account.move_to_portable=转换为便携账户\n该账户的信息会保存至 HMCL 同目录的配置文件中 +account.move_to_global=转换为全局账户\n该账户的信息会保存至系统当前用户文件夹的配置文件中 +account.move_to_portable=转换为便携账户\n该账户的信息会保存至与 HMCL 同文件夹的配置文件中 account.not_logged_in=未登录 account.password=密码 account.portable=便携账户 account.skin=皮肤 account.skin.file=皮肤图片文件 account.skin.model=模型 -account.skin.model.default=经典 -account.skin.model.slim=苗条 +account.skin.model.default=宽型 +account.skin.model.slim=纤细 account.skin.type.csl_api=Blessing Skin 服务器 account.skin.type.csl_api.location=服务器地址 account.skin.type.csl_api.location.hint=CustomSkinAPI 地址 account.skin.type.little_skin=LittleSkin 皮肤站 -account.skin.type.little_skin.hint=你需要在皮肤站中创建并使用和该离线账户角色同名角色,此时离线账户皮肤将为皮肤站上角色所设定的皮肤。\n你可以点击右上角帮助按钮进行求助。 +account.skin.type.little_skin.hint=你需要在皮肤站中创建并使用和该离线账户同名的角色,此时离线账户皮肤将显示为皮肤站上对应角色所设置的皮肤。\n你可以点击右上角帮助按钮进行求助。 account.skin.type.local_file=本地皮肤图片文件 -account.skin.upload=上传皮肤 +account.skin.upload=上传/编辑皮肤 account.skin.upload.failed=皮肤上传失败 account.skin.invalid_skin=无法识别的皮肤文件 account.username=用户名 @@ -174,7 +174,7 @@ archive.version=版本 assets.download=下载资源 assets.download_all=检查资源文件完整性 -assets.index.malformed=资源文件的索引文件损坏,您可以在相应的游戏管理,点击左下角的管理按钮选择【更新游戏资源文件】以修复该问题\n你可以点击右上角帮助按钮进行求助。 +assets.index.malformed=资源文件的索引文件损坏,你可以在相应版本的“版本设置”页面中,点击左下角的“管理”按钮,点击“更新游戏资源文件”以修复该问题。\n你可以点击右上角帮助按钮进行求助。 button.cancel=取消 button.change_source=切换下载源 @@ -188,7 +188,7 @@ button.no=否 button.ok=确定 button.refresh=刷新 button.remove=删除 -button.remove.confirm=您确定要删除吗?此操作无法撤销! +button.remove.confirm=你确定要删除吗?此操作无法撤销! button.retry=重试 button.save=保存 button.save_as=另存为 @@ -201,15 +201,15 @@ chat=官方群组 color.recent=推荐 color.custom=自定义颜色 -crash.NoClassDefFound=请确认 Hello Minecraft! Launcher 本体是否完整,\n或更新您的 Java。\n你可以访问\n https://docs.hmcl.net/help.html\n页面寻求帮助。 -crash.user_fault=您的系统或 Java 环境可能安装不当导致本软件崩溃,\n请检查您的 Java 环境或您的电脑。\n你可以访问\n https://docs.hmcl.net/help.html\n页面寻求帮助。 +crash.NoClassDefFound=请确认 Hello Minecraft! Launcher 本体是否完整,或更新你的 Java。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 +crash.user_fault=你的系统或 Java 环境可能安装不当导致本软件崩溃,请检查你的 Java 环境或你的电脑。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 curse.category.0=全部 # https://addons-ecs.forgesvc.net/api/v2/category/section/4471 curse.category.4474=科幻 curse.category.4481=轻量整合包 -curse.category.4483=战斗 PVP +curse.category.4483=战斗 PvP curse.category.4477=小游戏 curse.category.4478=任务 curse.category.4484=多人 @@ -229,9 +229,9 @@ curse.category.7418=恐怖 curse.category.5299=教育 curse.category.5232=额外行星 curse.category.5129=原版增强 -curse.category.5189=实用与QOL -curse.category.5190=QoL -curse.category.5191=实用与QoL +curse.category.5189=实用与 QOL +curse.category.5190=QOL +curse.category.5191=实用与 QOL curse.category.5192=梦幻菜单 curse.category.6145=空岛 curse.category.6814=性能 @@ -329,34 +329,34 @@ curse.sort.total_downloads=下载量 download=下载 download.hint=安装游戏和整合包或下载模组、资源包和地图 -download.code.404=远程服务器不包含需要下载的文件: %s +download.code.404=远程服务器不包含需要下载的文件: %s\n你可以点击右上角帮助按钮进行求助。 download.content=游戏内容 download.curseforge.unavailable=HMCL 预览版暂不支持访问 CurseForge,请使用稳定版或测试版进行下载。 -download.existing=文件已存在,无法保存。你可以在模组选择栏中的右侧按钮另存为将文件保存至其他地方。 +download.existing=文件已存在,无法保存。你可以将文件保存至其他地方。 download.external_link=打开下载网站 -download.failed=下载失败: %1$s,错误码:%2$d -download.failed.empty=[没有可供安装的版本,点击此处返回] +download.failed=下载失败: %1$s,\n错误码:%2$d\n你可以点击右上角帮助按钮进行求助。 +download.failed.empty=[没有可供安装的版本,点击此处返回]\n(你可以点击右上角帮助按钮进行求助) download.failed.no_code=下载失败: %s -download.failed.refresh=[加载版本列表失败,点击此处重试] +download.failed.refresh=[加载版本列表失败,点击此处重试]\n(你可以点击右上角帮助按钮进行求助) download.game=新游戏 -download.provider.bmclapi=BMCLAPI(bangbang93,https://bmclapi2.bangbang93.com) -download.provider.mojang=官方(OptiFine 自动安装使用 BMCLAPI 下载源) -download.provider.official=尽量使用官方源(最新,但可能加载慢) -download.provider.balanced=选择加载速度快的下载源(平衡,但可能不是最新) -download.provider.mirror=尽量使用镜像源(加载快,但可能不是最新) +download.provider.bmclapi=BMCLAPI (bangbang93,https://bmclapi2.bangbang93.com) +download.provider.mojang=官方 (OptiFine 自动安装使用 BMCLAPI 下载源) +download.provider.official=尽量使用官方源 (最新,但可能加载慢) +download.provider.balanced=选择加载速度快的下载源 (平衡,但可能不是最新) +download.provider.mirror=尽量使用镜像源 (加载快,但可能不是最新) download.java=下载 Java download.java.override=此 Java 版本已经存在,是否卸载并重新安装? download.javafx=正在下载必要的运行时组件…… -download.javafx.notes=正在通过网络下载 HMCL 必要的运行时组件。\n点击“切换下载源”按钮查看详情以及选择下载源,点击“取消”按钮停止并退出。\n注意:若下载速度过慢,请尝试切换下载源 -download.javafx.component=正在下载模块 %s +download.javafx.notes=正在通过网络下载 HMCL 必要的运行时组件。\n点击“切换下载源”按钮查看详情以及选择下载源,点击“取消”按钮停止并退出。\n注意:若下载速度过慢,请尝试切换下载源。 +download.javafx.component=正在下载模块“%s” download.javafx.prepare=准备开始下载 -exception.access_denied=因为无法访问文件 %s,HMCL 没有对该文件的访问权限,或者该文件被其他程序打开。\n\ - 请你检查当前操作系统账户是否能访问该文件,比如非管理员用户可能不能访问其他账户的个人文件夹内的文件。\n\ - 对于 Windows 用户,你还可以尝试通过资源监视器查看是否有程序占用了该文件,如果是,请关闭占用此文件相关程序,或者重启电脑再试。\n\ +exception.access_denied=无法访问文件“%s”,因为 HMCL 没有对该文件的访问权限,或者该文件已被其他程序打开。\n\ + 请你检查当前操作系统账户是否能访问该文件,比如非管理员用户可能无法访问其他账户的个人文件夹内的文件。\n\ + 对于 Windows 用户,你还可以尝试通过资源监视器查看是否有程序占用了该文件,如果是,请关闭占用该文件的程序,或者重启电脑再试。\n\ 如遇到问题,你可以点击右上角帮助按钮进行求助。 exception.artifact_malformed=下载的文件无法通过校验。\n你可以点击右上角帮助按钮进行求助。 -exception.ssl_handshake=无法建立 SSL 连接,因为当前 Java 虚拟机缺少相关的 SSL 证书。你可以尝试使用其他的 Java 虚拟机启动 HMCL 再试。\n你可以点击右上角帮助按钮进行求助。 +exception.ssl_handshake=无法建立 SSL 连接,因为当前 Java 虚拟机缺少相关的 SSL 证书。你可以尝试使用其他 Java 虚拟机启动 HMCL 再试。\n你可以点击右上角帮助按钮进行求助。 extension.bat=Windows 脚本 extension.mod=模组文件 @@ -367,29 +367,29 @@ extension.sh=Bash 脚本 fatal.javafx.incompatible=缺少 JavaFX 运行环境。\nHello Minecraft! Launcher 无法在低于 Java 11 的 Java 环境上自行补全 JavaFX 运行环境,请更新到 Java 11 或更高版本。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 fatal.javafx.incomplete=JavaFX 运行环境不完整,请尝试更换你的 Java 或者重新安装 OpenJFX。 fatal.javafx.missing=缺少 JavaFX 运行环境,请使用包含 OpenJFX 的 Java 运行环境启动 Hello Minecraft! Launcher。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 -fatal.config_change_owner_root=你正在使用 root 账户启动 Hello Minecraft! Launcher, 这可能导致你未来无法正常使用其他账户正常启动 Hello Minecraft! Launcher。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。\n是否继续启动? +fatal.config_change_owner_root=你正在使用 root 账户启动 Hello Minecraft! Launcher, 这可能导致你未来无法正常使用其他账户正常启动 HMCL。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。\n是否继续启动? fatal.config_in_temp_dir=你正在临时文件夹中启动 Hello Minecraft! Launcher, 你的设置和游戏数据可能会丢失,建议将 HMCL 移动至其他位置再启动。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。\n是否继续启动? -fatal.config_loading_failure=Hello Minecraft! Launcher 无法加载配置文件\n请确保 Hello Minecraft! Launcher 对 "%s" 目录及该目录下的文件拥有读写权限。\n对于 macOS,尝试将 HMCL 放在除「桌面」「下载」「文稿」之外的有权限的地方再试。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 -fatal.config_loading_failure.unix=Hello Minecraft! Launcher 无法加载配置文件,因为配置文件是由用户 %1$s 创建的。\n请使用 root 账户启动 HMCL (不推荐),或在终端中执行以下命令将配置文件的所有权变更为当前用户:\n%2$s\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 -fatal.mac_app_translocation=由于 macOS 的安全机制,Hello Minecraft! Launcher 被系统隔离至临时文件夹中。\n请将 Hello Minecraft! Launcher 移动到其他文件夹后再尝试启动,否则你的设置和游戏数据可能会在重启后丢失。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。\n是否继续启动? -fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher 即将完成升级,请重新打开 Hello Minecraft! Launcher。\n如遇到问题,你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 -fatal.apply_update_failure=我们很抱歉 Hello Minecraft! Launcher 无法自动完成升级,因为出现了一些问题。\n但你依可以从 %s 处手动下载 Hello Minecraft! Launcher 来完成升级\n你可以访问 https://docs.hmcl.net/help.html 网页进行反馈。 -fatal.apply_update_need_win7=Hello Minecraft! Launcher 无法在 Windows XP/Vista 上进行自动更新,请从 %s 处手动下载 Hello Minecraft! Launcher 来完成升级。 -fatal.samba=如果你正在通过 Samba 共享的文件夹中运行 Hello Minecraft! Launcher,启动器可能无法正常工作。请尝试更新你的 Java 或在本地文件夹内运行 Hello Minecraft! Launcher。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 -fatal.illegal_char=由于你的用户文件夹路径中存在非法字符‘=’,你将无法使用外置登录账户以及离线登录更换皮肤功能。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 -fatal.unsupported_platform=Minecraft 尚未为您的平台提供完善支持,所以可能影响游戏体验或无法启动游戏。\n若无法启动 Minecraft 1.17 及以上版本,可以尝试在版本设置中打开“使用 OpenGL 软渲染器”选项,使用 CPU 渲染以获得更好的兼容性。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +fatal.config_loading_failure=Hello Minecraft! Launcher 无法加载配置文件。\n请确保 HMCL 对“%s”文件夹及该文件夹下的文件拥有读写权限。\n对于 macOS,尝试将 HMCL 放在除“桌面”“下载”“文稿”之外的有权限的地方再试。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 +fatal.config_loading_failure.unix=Hello Minecraft! Launcher 无法加载配置文件,因为配置文件是由用户“%1$s”创建的。\n请使用 root 账户启动 HMCL (不推荐),或在终端中执行以下命令将配置文件的所有权变更为当前用户:\n%2$s\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 +fatal.mac_app_translocation=由于 macOS 的安全机制,Hello Minecraft! Launcher 被系统隔离至临时文件夹中。\n请将 HMCL 移动到其他文件夹后再尝试启动,否则你的设置和游戏数据可能会在重启后丢失。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。\n是否继续启动? +fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher 即将完成升级,请重新打开 HMCL。\n如遇到问题,你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 +fatal.apply_update_failure=我们很抱歉 Hello Minecraft! Launcher 无法自动完成升级,因为出现了一些问题。\n但你依可以从 %s 手动下载 HMCL 来完成升级。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 +fatal.apply_update_need_win7=Hello Minecraft! Launcher 无法在 Windows XP/Vista 上进行自动更新,请从 %s 手动下载 HMCL 来完成升级。 +fatal.samba=如果你正在通过 Samba 共享的文件夹中运行 Hello Minecraft! Launcher,启动器可能无法正常工作。请尝试更新你的 Java 或在本地文件夹内运行 HMCL。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 +fatal.illegal_char=由于你的用户文件夹路径中存在非法字符“=”,你将无法使用外置登录账户以及离线登录更换皮肤功能。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 +fatal.unsupported_platform=Minecraft 尚未对你的平台提供完善支持,所以可能影响游戏体验或无法启动游戏。\n若无法启动 Minecraft 1.17 及更高版本,可以尝试在“(全局/版本特定) 游戏设置 → 高级设置 → 调试选项”中将“渲染器”切换为“软渲染器”,以获得更好的兼容性。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher 已为龙芯提供支持。\n如果遇到问题,你可以点击右上角帮助按钮进行求助。 -fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher 已为 Apple Silicon 平台提供支持,使用 ARM 原生 Java 启动游戏以获得更流畅的游戏体验。\n如果你在游戏中遭遇问题,使用 x86-64 架构的 Java 启动游戏可能有更好的兼容性。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 -fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已为 Windows on Arm 平台提供原生支持。如果你在游戏中遭遇问题,请尝试使用 x86 架构的 Java 启动游戏。\n\n如果你正在使用高通平台,你可能需要安装 OpenGL 兼容包后才能进行游戏。点击链接前往 Microsoft Store 安装兼容包。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher 已为 Apple Silicon 平台提供支持,使用 ARM 原生 Java 启动游戏以获得更流畅的游戏体验。\n如果你在游戏中遇到问题,使用 x86-64 架构的 Java 启动游戏可能有更好的兼容性。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已为 Windows on ARM 平台提供原生支持。如果你在游戏中遇到问题,请尝试使用 x86 架构的 Java 启动游戏。\n如果你正在使用 高通 平台,你可能需要安装 OpenGL 兼容包 后才能进行游戏。点击链接前往 Microsoft Store 安装兼容包。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 feedback=反馈 feedback.channel=反馈渠道 feedback.discord=Discord -feedback.discord.statement=欢迎加入 Discord 讨论区,加入后请遵守讨论区规定。 +feedback.discord.statement=欢迎加入 Discord 讨论区,加入后请遵守讨论区规定 feedback.github=GitHub Issue -feedback.github.statement=打开一个 GitHub Issue。 +feedback.github.statement=提交一个 GitHub Issue feedback.qq_group=HMCL 用户群 -feedback.qq_group.statement=欢迎加入 HMCL 用户群,加入后请遵守群规。 +feedback.qq_group.statement=欢迎加入 HMCL 用户群,加入后请遵守群规 file=文件 From 05620519895715134ba3cd202fc6106e6713a858 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 19 Oct 2024 21:34:11 +0800 Subject: [PATCH 037/169] Fix mod update channel i18n (#3331) * Fix mod update channel i18n * Update Co-authored-by: Burning_TNT * update --------- Co-authored-by: Burning_TNT Co-authored-by: Glavo --- .../java/org/jackhuang/hmcl/ui/versions/DownloadPage.java | 6 +++--- HMCL/src/main/resources/assets/lang/I18N.properties | 3 +++ HMCL/src/main/resources/assets/lang/I18N_zh.properties | 3 +++ HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 3 +++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java index d16124206f..f7fbc807c8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java @@ -388,15 +388,15 @@ private static final class ModItem extends StackPane { switch (dataItem.getVersionType()) { case Alpha: - content.getTags().add(i18n("version.game.snapshot")); + content.getTags().add(i18n("mods.channel.alpha")); graphicPane.getChildren().setAll(SVG.ALPHA_CIRCLE_OUTLINE.createIcon(Theme.blackFill(), 24, 24)); break; case Beta: - content.getTags().add(i18n("version.game.snapshot")); + content.getTags().add(i18n("mods.channel.beta")); graphicPane.getChildren().setAll(SVG.BETA_CIRCLE_OUTLINE.createIcon(Theme.blackFill(), 24, 24)); break; case Release: - content.getTags().add(i18n("version.game.release")); + content.getTags().add(i18n("mods.channel.release")); graphicPane.getChildren().setAll(SVG.RELEASE_CIRCLE_OUTLINE.createIcon(Theme.blackFill(), 24, 24)); break; } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 4f482d8820..90fd793e5c 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -930,6 +930,9 @@ mods.add.success=%s was added successfully. mods.broken_dependency.title=Broken dependency mods.broken_dependency.desc=This dependency existed before. However, it doesn't exist now. Try using another download source. mods.category=Category +mods.channel.alpha=Alpha +mods.channel.beta=Beta +mods.channel.release=Release mods.check_updates=Check for Updates mods.check_updates.current_version=Current Version mods.check_updates.empty=All mods are up-to-date diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index a74d8b88d2..8b279a9bc4 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -799,6 +799,9 @@ mods.add.success=成功新增模組 %s。 mods.broken_dependency.title=損壞的前置模組 mods.broken_dependency.desc=該前置模組曾經在該模組倉庫上存在過,但現在被刪除了,換個下載源試試吧。 mods.category=類別 +mods.channel.alpha=Alpha +mods.channel.beta=Beta +mods.channel.release=Release mods.check_updates=檢查模組更新 mods.check_updates.current_version=當前版本 mods.check_updates.empty=沒有需要更新的模組 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 2321f05bc3..3940cc517d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -798,6 +798,9 @@ mods.add.success=成功添加模组 %s。 mods.broken_dependency.title=损坏的前置模组 mods.broken_dependency.desc=该前置模组曾经在该模组仓库上存在过,但现在被删除了。换个下载源试试吧。 mods.category=类别 +mods.channel.alpha=快照版本 +mods.channel.beta=测试版本 +mods.channel.release=稳定版本 mods.check_updates=检查模组更新 mods.check_updates.current_version=当前版本 mods.check_updates.empty=没有需要更新的模组 From c6ed42d3e6e7d78c235ff26ce830ae3363ecc0b9 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 19 Oct 2024 21:35:22 +0800 Subject: [PATCH 038/169] Revise zh_CN part 2 (#3346) * Revise zh_CN part 2 * Update * Oops... --- .../assets/lang/I18N_zh_CN.properties | 121 +++++++++--------- 1 file changed, 59 insertions(+), 62 deletions(-) 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 3940cc517d..1d385ff7d6 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -403,79 +403,76 @@ folder.saves=存档文件夹 folder.screenshots=截图文件夹 game=游戏 -game.crash.feedback=请不要将本界面截图给他人!如果你要求助他人,请你点击左下角 导出游戏崩溃信息 后将导出的文件发送给他人以供分析。\n你可以点击下方的 帮助 前往交流群寻求帮助。 +game.crash.feedback=请不要将本界面截图给他人!如果你要向他人求助,请你点击左下角“导出游戏崩溃信息”后将导出的文件发送给他人以供分析。\n你可以点击下方的“帮助”前往交流群寻求帮助。 game.crash.info=游戏信息 game.crash.reason=崩溃原因 game.crash.reason.analyzing=分析中…… -game.crash.reason.block=当前游戏因为某个方块不能正常工作,无法继续运行。\n你可以尝试通过 MCEdit 工具编辑存档删除该方块,或者直接删除相应的模组。\n方块类型:%1$s\n方块坐标:%2$s -game.crash.reason.bootstrap_failed=当前游戏因为模组 %1$s 错误,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 -game.crash.reason.mixin_apply_mod_failed=当前游戏因为 Mixin 无法应用 %1$s 模组,无法继续运行。\n你可以尝试删除或更新该 Mod 以解决问题。 -game.crash.reason.config=当前游戏因为无法解析模组配置文件,无法继续运行\n模组 %1$s 的配置文件 %2$s 无法被解析。 +game.crash.reason.block=当前游戏由于某个方块不能正常工作,无法继续运行。\n你可以尝试通过 MCEdit 工具编辑存档删除该方块,或者直接删除相应的模组。\n方块类型:%1$s\n方块坐标:%2$s +game.crash.reason.bootstrap_failed=当前游戏由于模组“%1$s”出现问题,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 +game.crash.reason.mixin_apply_mod_failed=当前游戏由于 Mixin 无法应用于“%1$s”模组,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 +game.crash.reason.config=当前游戏由于无法解析模组配置文件,无法继续运行。\n无法解析模组“%1$s”的配置文件“%2$s”。 game.crash.reason.multiple=检测到多个原因:\n\n -game.crash.reason.debug_crash=当前游戏因为手动触发崩溃,无法继续运行。\n事实上游戏并没有问题,问题都是你造成的! -game.crash.reason.duplicated_mod=当前游戏因为模组 %1$s 重复安装,无法继续运行。\n%2$s\n每种模组只能安装一个,请你删除多余的模组再试。 -game.crash.reason.entity=当前游戏因为某个实体不能正常工作,无法继续运行。\n你可以尝试通过 MCEdit 工具编辑存档删除该实体,或者直接删除相应的模组。\n实体类型:%1$s\n实体坐标:%2$s -game.crash.reason.fabric_version_0_12=Fabric 0.12 及以上版本与当前已经安装的模组可能不兼容,你需要将 Fabric 降级至 0.11.7。 +game.crash.reason.debug_crash=当前游戏由于手动触发崩溃,无法继续运行。\n事实上游戏并没有问题,问题都是你造成的! +game.crash.reason.duplicated_mod=当前游戏由于模组“%1$s”重复安装,无法继续运行。\n%2$s\n每种模组只能安装一个,请你删除多余的模组再试。 +game.crash.reason.entity=当前游戏由于某个实体不能正常工作,无法继续运行。\n你可以尝试通过 MCEdit 工具编辑存档删除该实体,或者直接删除相应的模组。\n实体类型:%1$s\n实体坐标:%2$s +game.crash.reason.fabric_version_0_12=Fabric Loader 0.12 及更高版本与当前已经安装的模组可能不兼容,你需要将 Fabric Loader 降级至 0.11.7。 game.crash.reason.fabric_warnings=Fabric 提供了一些警告信息:\n%1$s -game.crash.reason.file_already_exists=当前游戏因为文件 %1$s 已经存在,无法继续运行。\n如果你认为这个文件可以删除,你可以在备份这个文件后尝试删除它,并重新启动游戏。 -game.crash.reason.file_changed=当前游戏因为文件校验失败,无法继续运行。\n如果你手动修改了 Minecraft.jar 文件,你需要回退修改,或者重新下载游戏。 -game.crash.reason.gl_operation_failure=当前游戏因为你使用的某些模组、光影包、材质包,无法继续运行。\n请先尝试禁用你所使用的模组/光影包/材质包再试。 -game.crash.reason.graphics_driver=当前游戏因为显卡驱动问题而崩溃,请尝试以下操作:\n\ - - 如果你的电脑存在独立显卡,请尝试使用 独立显卡 而非 Intel 核显启动 HMCL 与游戏 详情 ;\n\ - - 尝试升级你的 显卡驱动 到最新版本,或回退到出厂版本;\n\ - - 如果你确实需要使用核芯显卡,请检查你的电脑的 CPU 是否是 Intel(R) Core(TM) 3000 系列或更旧的处理器,如果是,对于 Minecraft 1.16.5 及更旧版本,请你将游戏所使用的 Java 版本降级至 1.8.0_51 及以下版本 Java 1.8.0 历史版本 ,否则请跳过;\n\ - - 在全局(特定)游戏设置,高级设置中打开“使用 OpenGL 软渲染器”(开启此选项后帧数会显著降低,仅推荐在以调试为目的或应急时开启)。\n\ +game.crash.reason.file_already_exists=当前游戏由于文件“%1$s”已经存在,无法继续运行。\n如果你认为这个文件可以删除,你可以在备份这个文件后尝试删除它,并重新启动游戏。 +game.crash.reason.file_changed=当前游戏由于文件校验失败,无法继续运行。\n如果你手动修改了 Minecraft.jar 文件,你需要回退修改,或者重新下载游戏。 +game.crash.reason.gl_operation_failure=当前游戏由于你使用的某些模组/光影包/资源包有问题,导致无法继续运行。\n请先尝试禁用你所使用的模组/光影包/资源包再试。 +game.crash.reason.graphics_driver=当前游戏由于显卡驱动问题而崩溃,请尝试以下操作:\n\ + \ · 如果你的电脑存在独立显卡,请尝试使用独立显卡而非 Intel 核显启动 HMCL 与游戏;详情\n\ + \ · 尝试升级你的显卡驱动到最新版本,或回退到出厂版本;\n\ + \ · 如果你确实需要使用核芯显卡,请检查你电脑的 CPU 是否为 Intel(R) Core(TM) 3000 系列或更旧的处理器。如果是,对于 Minecraft 1.16.5 及更旧版本,请你将游戏所使用的 Java 降级至 1.8.0_51 及更低版本,否则请跳过;Java 1.8.0 历史版本\n\ 如果仍有问题,你可能需要考虑换一张新显卡或一台新电脑。 -game.crash.reason.macos_failed_to_find_service_port_for_display=当前游戏因为 Apple silicon 平台下初始化 OpenGL 窗口失败,无法继续运行。\n对于该问题,HMCL 暂无直接性的解决方案。请您尝试任意打开一个浏览器并全屏,然后再回到 HMCL 启动游戏,在弹出游戏窗口前迅速切回浏览器页面,等待游戏窗口出现后再切回游戏窗口。 -game.crash.reason.illegal_access_error=当前游戏因为某些模组的问题,无法继续运行。\n如果你认识:%1$s,你可以更新或删除对应模组再试。 -game.crash.reason.install_mixinbootstrap=当前游戏因为缺失 MixinBootstrap,无法继续运行。\n你可以尝试安装 MixinBootstrap 解决该问题。若安装后崩溃,尝试在该模组的文件名前加入英文“!”尝试解决。 -game.crash.reason.need_jdk11=当前游戏因为 Java 虚拟机版本不合适,无法继续运行。\n你需要下载安装 Java 11,并在全局(特定)游戏设置中将 Java 设置为 11 开头的版本。 -game.crash.reason.jdk_9=当前游戏因为 Java 版本过高,无法继续运行。\n你需要下载安装 Java 8,并在全局(特定)游戏设置中将 Java 设置为 1.8 的版本。 -game.crash.reason.jvm_32bit=当前游戏因为内存分配过大,超过了 32 位 Java 内存限制,无法继续运行。\n如果你的电脑是 64 位系统,请下载安装并更换 64 位 Java。下载 Java\n如果你的电脑是 32 位系统,你或许可以重新安装 64 位系统,或换一台新电脑。\n或者,你可以关闭游戏内存的自动分配,并且把内存限制调节为 1024 MB 或以下。 -game.crash.reason.loading_crashed_forge=当前游戏因为模组 %1$s (%2$s) 错误,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 -game.crash.reason.loading_crashed_fabric=当前游戏因为模组 %1$s 错误,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 -game.crash.reason.memory_exceeded=当前游戏因为分配的内存过大,无法继续运行。\n该问题是由于系统页面文件太小导致的。\n你需要在全局(特定)游戏设置中关闭游戏内存的自动分配,并将游戏内存调低至游戏能正常启动为止。\n你还可以尝试将 虚拟内存 设置调整至「自动管理所有驱动器分页文件大小」,详情。 -game.crash.reason.mac_jdk_8u261=当前游戏因为你所使用的 Forge 或 OptiFine 与 Java 冲突崩溃。\n请尝试更新 Forge 和 OptiFine,或使用 Java 8u251 及更早版本启动。 -game.crash.reason.mod=当前游戏因为 %1$s 的问题,无法继续运行。\n你可以更新或删除已经安装的 %1$s 再试。 -game.crash.reason.mod_resolution=当前游戏因为 Mod 依赖问题,无法继续运行。Fabric 提供了如下信息:\n%1$s -game.crash.reason.mod_resolution_collection=当前游戏因为前置 Mod 版本不匹配,无法继续运行。\n%1$s 需要前置 Mod:%2$s 才能继续运行。\n这表示你需要更新或降级前置。你可以到下载页的模组下载,或到网上下载 %3$s。 -game.crash.reason.mod_resolution_conflict=当前游戏因为 Mod 冲突,无法继续运行。\n%1$s 与 %2$s 不能兼容。 -game.crash.reason.mod_resolution_missing=当前游戏因为缺少 Mod 前置,无法继续运行。\n%1$s 需要前置 Mod:%2$s 才能继续运行。\n这表示你少安装了 Mod,或该 Mod 版本不够。你可以到下载页的模组下载,或到网上下载 %3$s。 -game.crash.reason.mod_resolution_missing_minecraft=当前游戏因为 Mod 和 Minecraft 游戏版本不匹配,无法继续运行。\n%1$s 需要 Minecraft %2$s 才能运行。\n如果你要继续使用你已经安装的 Mod,你可以选择安装对应的 Minecraft 版本;如果你要继续使用当前 Minecraft 版本,你需要安装对应版本的 Mod。 +game.crash.reason.macos_failed_to_find_service_port_for_display=当前游戏由于 Apple Silicon 平台下初始化 OpenGL 窗口失败,无法继续运行。\n对于该问题,HMCL 暂无直接性的解决方案。请你尝试任意打开一个浏览器并全屏,然后再回到 HMCL 启动游戏,在弹出游戏窗口前迅速切回浏览器页面,等待游戏窗口出现后再切回游戏窗口。 +game.crash.reason.illegal_access_error=当前游戏由于某些模组的问题,无法继续运行。\n如果你认识“%1$s”,你可以更新或删除对应模组再试。 +game.crash.reason.install_mixinbootstrap=当前游戏由于缺失 MixinBootstrap,无法继续运行。\n你可以尝试安装 MixinBootstrap 解决该问题。若安装后崩溃,尝试在该模组的文件名前加入半角感叹号 (!) 尝试解决。 +game.crash.reason.need_jdk11=当前游戏由于 Java 虚拟机版本不合适,无法继续运行。\n你需要下载安装 Java 11,并在“(全局/版本特定) 游戏设置 → 游戏 Java”中将 Java 设置为 11 开头的版本。 +game.crash.reason.jdk_9=当前游戏由于 Java 版本过高,无法继续运行。\n你需要下载安装 Java 8,并在“(全局/版本特定) 游戏设置 → 游戏 Java”中将 Java 设置为 1.8 的版本。 +game.crash.reason.jvm_32bit=当前游戏由于内存分配过大,超过了 32 位 Java 内存限制,无法继续运行。\n如果你的电脑是 64 位系统,请下载安装并更换 64 位 Java。下载 Java\n如果你的电脑是 32 位系统,你或许可以重新安装 64 位系统,或换一台新电脑。\n或者,你可以在“(全局/版本特定) 游戏设置 → 游戏内存”中关闭“自动分配内存”,并且把内存限制调节为 1024 MB 或以下。 +game.crash.reason.loading_crashed_forge=当前游戏由于模组“%1$s (%2$s)”错误,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 +game.crash.reason.loading_crashed_fabric=当前游戏由于模组“%1$s”错误,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 +game.crash.reason.memory_exceeded=当前游戏由于分配的内存过大,无法继续运行。\n该问题是由于系统页面文件太小导致的。\n你需要在全局(特定)游戏设置中关闭游戏内存的自动分配,并将游戏内存调低至游戏能正常启动为止。\n你还可以尝试将 虚拟内存 设置调整至「自动管理所有驱动器分页文件大小」,详情。 +game.crash.reason.mac_jdk_8u261=当前游戏由于你所使用的 Forge/OptiFine 与 Java 冲突而崩溃。\n请尝试更新 Forge/OptiFine,或使用 Java 8u251 及更早版本启动。 +game.crash.reason.mod=当前游戏由于“%1$s”的问题,无法继续运行。\n你可以更新或删除已经安装的“%1$s”再试。 +game.crash.reason.mod_resolution=当前游戏由于模组依赖问题,无法继续运行。Fabric 提供了如下信息:\n%1$s +game.crash.reason.mod_resolution_collection=当前游戏由于前置模组版本不匹配,无法继续运行。\n“%1$s”需要前置模组“%2$s”才能继续运行。\n这表示你需要更新或降级前置。你可以前往“下载 → 模组”页面下载,或到网上下载“%3$s”。 +game.crash.reason.mod_resolution_conflict=当前游戏由于模组冲突,无法继续运行。\n“%1$s”与“%2$s”不兼容。 +game.crash.reason.mod_resolution_missing=当前游戏由于缺少前置模组,无法继续运行。\n“%1$s”需要前置模组“%2$s”才能继续运行。\n这表示你少安装了模组,或该模组版本不够。你可以前往“下载 → 模组”页面下载,或到网上下载“%3$s”。 +game.crash.reason.mod_resolution_missing_minecraft=当前游戏由于模组和 Minecraft 游戏版本不匹配,无法继续运行。\n“%1$s”需要 Minecraft %2$s 才能运行。\n如果你要继续使用你已经安装的模组,你可以选择安装对应的 Minecraft 版本;如果你要继续使用当前 Minecraft 版本,你需要安装对应版本的模组。 game.crash.reason.mod_resolution_mod_version=%1$s (版本号 %2$s) game.crash.reason.mod_resolution_mod_version.any=%1$s (任意版本) -game.crash.reason.forge_repeat_installation=当前游戏因为 Forge 重复安装,无法继续运行。此为已知问题\n建议将日志上传反馈至 GitHub ,以便我们找到更多线索并修复此问题。\n目前你可以到 自动安装 里头卸载 Forge 并重新安装。 -game.crash.reason.optifine_repeat_installation=当前游戏因为 Optifine 重复安装,无法继续运行。\n请删除 Mod 文件夹下的 Optifine 或前往 游戏管理-自动安装 卸载自动安装的 Optifine。 -game.crash.reason.forgemod_resolution=当前游戏因为模组依赖问题,无法继续运行。Forge 提供了如下信息:\n%1$s -game.crash.reason.forge_found_duplicate_mods=当前游戏因为模组重复问题,无法继续运行。Forge 提供了如下信息:\n%1$s -game.crash.reason.modmixin_failure=当前游戏因为某些 Mod 注入失败,无法继续运行。\n这一般代表着该 Mod 存在 Bug,或与当前环境不兼容。\n你可以查看日志寻找出错模组。 -game.crash.reason.night_config_fixes=当前游戏因为 Night Config 库的一些问题,无法继续运行。\n你可以尝试安装 Night Config Fixes 模组,这或许能帮助你解决这个问题。\n了解更多,可访问该模组的 GitHub 仓库。 -game.crash.reason.forge_error=Forge 可能已经提供了错误信息。\n你可以查看日志,并根据错误报告中的日志信息进行对应处。\n如果没有看到报错信息,可以查看错误报告了解错误具体是如何发生的。\n%1$s -game.crash.reason.mod_resolution0=当前游戏因为一些模组出现问题,无法继续运行。\n你可以查看日志寻找出错模组。 -game.crash.reason.fabric_reports_an_error_and_gives_a_solution=Fabric 可能已经提供了错误信息。\n你可以查看日志,并根据错误报告中的日志信息进行对应处。\n如果没有看到报错信息,可以查看错误报告了解错误具体是如何发生的。 -game.crash.reason.java_version_is_too_high=当前游戏因为 Java 虚拟机版本过高,无法继续运行。\n请在全局(特定)游戏设置的 Java 路径选项卡中改用较低版本的 Java,然后再启动游戏。\n如果没有,可以从 java.com(Java8)BellSoft Liberica Full JRE(Java17) 等平台下载、安装一个(安装完后需重启启动器)。 -game.crash.reason.mod_name=当前游戏因为模组文件名称问题,无法继续运行。\n模组文件名称应只使用英文全半角的大小写字母(Aa~Zz)、数字(0~9)、横线(-)、下划线(_)和点(.)。\n请到模组文件夹中将所有不合规的模组文件名称添加一个上述的合规的字符。 -game.crash.reason.incomplete_forge_installation=当前游戏因为 Forge / NeoForge 安装不完整,无法继续运行。\n请在 版本设置 - 自动安装 中卸载 Forge 并重新安装。 -game.crash.reason.optifine_is_not_compatible_with_forge=当前游戏因为 OptiFine 与当前版本的 Forge 不兼容,导致了游戏崩溃。\n点击 此处 查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏或在 版本设置 - 自动安装 中更换版本。\n经测试,Forge 版本过高或过低都可能导致崩溃。 -game.crash.reason.mod_files_are_decompressed=当前游戏因为模组文件被解压了,无法继续运行。\n请直接把整个模组文件放进模组文件夹中即可。\n解压模组会导致游戏出错,请删除模组文件夹中已被解压的模组,然后再启动游戏。 -game.crash.reason.shaders_mod=当前游戏因为同时安装了 OptiFine 和 Shaders 模组,无法继续运行。\n因为 OptiFine 已集成 Shaders 模组的功能,只需删除 Shaders 模组即可。 -game.crash.reason.rtss_forest_sodium=当前游戏因为 RivaTuner Statistics Server (RTSS) 与 Sodium 不兼容,导致了游戏崩溃。\n点击 此处 查看详情。 -game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=当前游戏因为您所安装的模组过多,超出了游戏的 ID 限制,无法继续运行。\n请尝试安装 JEID 等修复模组,或删除部分大型模组。 -game.crash.reason.optifine_causes_the_world_to_fail_to_load=当前游戏可能因为 OptiFine ,无法继续运行。\n该问题只在特定 OptiFine 版本中出现,你可以尝试在 版本设置 - 自动安装 中更换 OptiFine 的版本。 -game.crash.reason.modlauncher_8=当前游戏因为您所使用的 Forge 版本与当前使用的 Java 冲突崩溃,请尝试更新 Forge 到 36.2.26 或更高版本或换用版本低于 1.8.0.320 的 Java,Liberica JDK 8u312+7。 -game.crash.reason.no_class_def_found_error=当前游戏因为代码不完整,无法继续运行。\n你的游戏可能缺失了某个模组,或者某些模组文件不完整,或者模组与游戏的版本不匹配。\n你可能需要重新安装游戏和模组,或请求他人帮助。\n缺失:\n%1$s -game.crash.reason.no_such_method_error=当前游戏因为代码不完整,无法继续运行。\n你的游戏可能缺失了某个模组,或者某些模组文件不完整,或者模组与游戏的版本不匹配。\n你可能需要重新安装游戏和模组,或请求他人帮助。 -game.crash.reason.opengl_not_supported=当前游戏因为你的显卡驱动存在问题,无法继续运行。\n原因是 OpenGL 不受支持,你现在是否在远程桌面或者串流模式下?如果是,请直接使用原电脑启动游戏。\n或者尝试升级你的显卡驱动到最新版本后再尝试启动游戏。如果你的电脑存在独立显卡,你需要检查游戏是否使用集成/核心显卡启动,如果是,请尝试使用独立显卡启动 HMCL 与游戏。如果仍有问题,你可能需要考虑换一个新显卡或新电脑。 -game.crash.reason.openj9=当前游戏无法运行在 OpenJ9 虚拟机上,请你在全局(特定)游戏设置中更换 Hotspot Java 虚拟机,并重新启动游戏。如果没有下载安装,你可以在网上自行下载。 -game.crash.reason.out_of_memory=当前游戏因为内存不足,无法继续运行。\n这可能是内存分配太小,或者模组数量过多导致的。\n你可以在全局(特定)游戏设置中调大游戏内存分配值以允许游戏在更大的内存下运行。\n如果仍然出现该错误,你可能需要换一台更好的电脑。 -game.crash.reason.resolution_too_high=当前游戏因为材质包分辨率过高,无法继续运行\n你可以更换一个分辨率更低的材质,或者更换一个显存更大的显卡。 +game.crash.reason.forge_repeat_installation=当前游戏由于 Forge 重复安装,无法继续运行。此为已知问题\n建议将日志上传并反馈至 GitHub,以便我们找到更多线索并修复此问题。\n目前你可以在“版本设置 → 自动安装”中卸载 Forge 并重新安装。 +game.crash.reason.optifine_repeat_installation=当前游戏由于 OptiFine 重复安装,无法继续运行。\n请删除模组文件夹下的 OptiFine 或前往“版本设置 → 自动安装”卸载安装的 OptiFine。 +game.crash.reason.forgemod_resolution=当前游戏由于模组依赖问题,无法继续运行。Forge/NeoForge 提供了如下信息:\n%1$s +game.crash.reason.forge_found_duplicate_mods=当前游戏由于模组重复安装,无法继续运行。Forge/NeoForge 提供了如下信息:\n%1$s +game.crash.reason.modmixin_failure=当前游戏由于某些模组注入失败,无法继续运行。\n这一般代表着该模组存在问题,或与当前环境不兼容。\n你可以查看日志寻找出错模组。 +game.crash.reason.night_config_fixes=当前游戏由于 Night Config 库的一些问题,无法继续运行。\n你可以尝试安装 Night Config Fixes 模组,这或许能帮助你解决这个问题。\n更多详情,可访问该模组的 GitHub 仓库。 +game.crash.reason.forge_error=Forge/NeoForge 可能已经提供了错误信息。\n你可以查看日志,并根据错误报告中的日志信息进行对应处理。\n如果没有看到报错信息,可以查看错误报告了解错误具体是如何发生的。\n%1$s +game.crash.reason.mod_resolution0=当前游戏由于一些模组出现问题,无法继续运行。\n你可以查看日志寻找出错模组。 +game.crash.reason.java_version_is_too_high=当前游戏由于 Java 虚拟机版本过高,无法继续运行。\n请在“(全局/版本特定) 游戏设置 → 游戏 Java”中改用较低版本的 Java,然后再启动游戏。\n如果没有,可以从 java.com (Java 8)BellSoft Liberica Full JRE (Java 17) 等平台下载、安装一个 (安装完后需重启启动器)。 +game.crash.reason.mod_name=当前游戏由于模组文件名称问题,无法继续运行。\n模组文件名称应只使用半角的大小写字母 (Aa~Zz)、数字 (0~9)、横线 (-)、下划线 (_)和点 (.)。\n请到模组文件夹中将所有不合规的模组文件名修改为上述合规字符。 +game.crash.reason.incomplete_forge_installation=当前游戏由于 Forge/NeoForge 安装不完整,无法继续运行。\n请在“版本设置 → 自动安装”中卸载 Forge 并重新安装。 +game.crash.reason.optifine_is_not_compatible_with_forge=当前游戏由于 OptiFine 与当前版本的 Forge 不兼容,导致游戏崩溃。\n点击 此处 查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏或在“版本设置 → 自动安装”中更换版本。\n经测试,Forge 版本过高或过低都可能导致崩溃。 +game.crash.reason.mod_files_are_decompressed=当前游戏由于模组文件被解压了,无法继续运行。\n请直接把整个模组文件放进模组文件夹中即可。\n解压模组会导致游戏出错,请删除模组文件夹中已被解压的模组,然后再启动游戏。 +game.crash.reason.shaders_mod=当前游戏由于同时安装了 OptiFine 和 Shaders 模组,无法继续运行。\n由于 OptiFine 已集成 Shaders 模组的功能,所以只需删除 Shaders 模组即可。 +game.crash.reason.rtss_forest_sodium=当前游戏由于 RivaTuner Statistics Server (RTSS) 与 Sodium 不兼容,导致游戏崩溃。\n点击 此处 查看详情。 +game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=当前游戏由于你所安装的模组过多,超出了游戏的 ID 限制,无法继续运行。\n请尝试安装 JEID 等修复模组,或删除部分大型模组。 +game.crash.reason.optifine_causes_the_world_to_fail_to_load=当前游戏可能由于 OptiFine 而无法继续运行。\n该问题只在特定 OptiFine 版本中出现,你可以尝试在“版本设置 → 自动安装”中更换 OptiFine 的版本。 +game.crash.reason.modlauncher_8=当前游戏由于你所使用的 Forge 版本与当前使用的 Java 冲突而崩溃,请尝试更新 Forge 到 36.2.26 或更高版本或换用版本低于 1.8.0.320 的 Java。Liberica JDK 8u312+7 +game.crash.reason.no_class_def_found_error=当前游戏由于代码不完整,无法继续运行。\n你的游戏可能缺失了某个模组,或者某些模组文件不完整,或者模组与游戏的版本不匹配。\n你可能需要重新安装游戏和模组,或寻求他人帮助。\n缺失:\n%1$s +game.crash.reason.no_such_method_error=当前游戏由于代码不完整,无法继续运行。\n你的游戏可能缺失了某个模组,或者某些模组文件不完整,或者模组与游戏的版本不匹配。\n你可能需要重新安装游戏和模组,或寻求他人帮助。 +game.crash.reason.opengl_not_supported=当前游戏由于你的显卡驱动存在问题,无法继续运行。\n原因是 OpenGL 不受支持,你现在是否在远程桌面或者串流模式下?如果是,请直接使用原电脑启动游戏。\n或者尝试升级你的显卡驱动到最新版本后再尝试启动游戏。如果你的电脑存在独立显卡,你需要检查游戏是否使用集成/核心显卡启动,如果是,请尝试使用独立显卡启动 HMCL 与游戏。如果仍有问题,你可能需要考虑换一个新显卡或新电脑。 +game.crash.reason.openj9=当前游戏无法在 OpenJ9 虚拟机上运行,请你在“(全局/版本特定) 游戏设置 → 游戏 Java”中更换 Hotspot Java 虚拟机,并重新启动游戏。如果没有下载安装,你可以在网上自行下载。 +game.crash.reason.out_of_memory=当前游戏由于内存不足,无法继续运行。\n这可能是内存分配太小,或者模组数量过多导致的。\n你可以在全局(特定)游戏设置中调大游戏内存分配值以允许游戏在更大的内存下运行。\n如果仍然出现该错误,你可能需要换一台更好的电脑。 +game.crash.reason.resolution_too_high=当前游戏由于材质包分辨率过高,无法继续运行\n你可以更换一个分辨率更低的材质,或者更换一个显存更大的显卡。 game.crash.reason.stacktrace=原因未知,请点击日志按钮查看详细信息。\n下面是一些关键词,其中可能包含模组名称,你可以通过搜索的方式查找有关信息。\n%s -game.crash.reason.too_old_java=当前游戏因为 Java 虚拟机版本过低,无法继续运行。\n你需要在全局(特定)游戏设置中更换 Java %1$s 或更新版本的 Java 虚拟机,并重新启动游戏。如果没有下载安装,你可以点击 此处 下载 Liberica JDK。 +game.crash.reason.too_old_java=当前游戏由于 Java 虚拟机版本过低,无法继续运行。\n你需要在“(全局/版本特定) 游戏设置 → 游戏 Java”中更换 Java %1$s 或更新版本的 Java 虚拟机,并重新启动游戏。如果没有下载安装,你可以点击 此处 下载 Microsoft JDK。 game.crash.reason.unknown=原因未知,请点击日志按钮查看详细信息。 -game.crash.reason.unsatisfied_link_error=当前游戏因为缺少本地库,无法继续运行。\n这些本地库缺失:%1$s。\n如果你在全局(特定)游戏设置中修改了本地库路径选项,请你修改回预设模式。\n如果你正在使用预设模式,请检查游戏路径是否只包含英文大小写字母,数字,下划线,\n如果是,那么请检查是否是由于模组或者 HMCL 导致了本地库缺失的问题。如果你确定是 HMCL 引起的,建议你向我们反馈。\n你可以尝试在控制在 控制面板 时钟和区域 区域 管理 更改系统区域设置 中将 当前系统区域设置选项卡修改为:中文(简体,中国),并且把 使用Unicode UTF-8提供全球语言支持 关闭;\n或将游戏路径中的所有 非英文字符的名称 修改为 英文字符(例如中文,空格等)\n如果你确实需要自定义本地库路径,你需要保证其中包含缺失的本地库! -game.crash.reason.failed_to_load_a_library=当前游戏因为加载本地库失败,无法继续运行。\n如果你在全局(特定)游戏设置中修改了本地库路径选项,请你修改回预设模式。\n如果已经在预设模式下,请检查本地库缺失是否是 Mod 引起的,或由 HMCL 引起的。如果你确定是 HMCL 引起的,建议你向我们反馈。\n你可以尝试在控制在 控制面板 时钟和区域 区域 管理 更改系统区域设置 中将 当前系统区域设置选项卡修改为:中文(简体,中国),并且把 使用Unicode UTF-8提供全球语言支持 关闭;\n或将游戏路径中的所有 非英文字符的名称 修改为 英文字符(例如中文,空格等)\n如果你确实需要自定义本地库路径,你需要保证其中包含缺失的本地库! +game.crash.reason.unsatisfied_link_error=当前游戏由于缺少本地库,无法继续运行。\n这些本地库缺失:%1$s。\n如果你在“(全局/版本特定) 游戏设置 → 高级设置”中修改了本地库路径选项,请你修改回默认模式。\n如果你正在使用默认模式,请检查游戏文件夹路径是否只包含英文字母、数字和下划线,\n如果是,那么请检查是否为模组或 HMCL 导致了本地库缺失的问题。如果你确定是 HMCL 引起的,建议你向我们反馈。\n对于 Windows 用户,你还可以尝试在“控制面板 → 时钟和区域 → 区域 → 管理 → 更改系统区域设置”中将“当前系统区域设置”修改为“中文(简体,中国大陆)”,并关闭“Beta 版:使用 Unicode UTF-8 提供全球语言支持”选项;\n或将游戏文件夹路径中的所有非英文字符的名称 (例如中文、空格等) 修改为英文字符。\n如果你确实需要自定义本地库路径,你需要保证其中包含缺失的本地库! game.crash.title=游戏意外退出 -game.directory=游戏路径 +game.directory=游戏文件夹路径 game.version=游戏版本 help=帮助 From 55b01ab1017f3897be5ee62568a3915b4a130b82 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 19 Oct 2024 21:35:57 +0800 Subject: [PATCH 039/169] Revise zh_CN part 3 (#3348) * Revise zh_CN part 3 * Update --- .../assets/lang/I18N_zh_CN.properties | 127 +++++++++--------- 1 file changed, 63 insertions(+), 64 deletions(-) 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 1d385ff7d6..c378a1c7bd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -477,7 +477,7 @@ game.version=游戏版本 help=帮助 help.doc=Hello Minecraft! Launcher 帮助文档 -help.detail=可查阅数据包、整合包制作指南等内容。 +help.detail=可查阅数据包、整合包制作指南等内容 input.email=用户名必须是邮箱 input.number=必须是数字 @@ -492,35 +492,35 @@ install.failed.downloading=安装失败,部分文件未能完成下载 install.failed.downloading.detail=未能下载文件:%s install.failed.downloading.timeout=下载超时:%s install.failed.install_online=无法识别要安装的组件。如果你要安装模组,你需要在模组管理页面安装模组。 -install.failed.malformed=下载的文件格式损坏。您可以在设置-下载中切换到其他下载源来尝试解决此问题。 -install.failed.optifine_conflict=暂不支持 OptiFine, Fabric 或 OptiFine , Forge 同时安装在 Minecraft 1.13 及以上版本 -install.failed.optifine_forge_1.17=Minecraft 1.17.1 下,仅 OptiFine H1 Pre2 及以上版本能兼容 Forge。你可以从 OptiFine 测试版中选择最新版本。 +install.failed.malformed=下载的文件已损坏。你可以在“设置 → 下载 → 下载源”中切换其他下载源来尝试解决此问题。 +install.failed.optifine_conflict=暂不支持在 Minecraft 1.13 及更高版本同时安装 OptiFine 与 Fabric。 +install.failed.optifine_forge_1.17=对于 Minecraft 1.17.1 版本,仅 OptiFine H1 pre2 及更高版本与 Forge 兼容。你可以在 OptiFine 预览版 (Preview versions) 中选择最新版本。 install.failed.version_mismatch=该组件需要的游戏版本为 %s,但实际的游戏版本为 %s。 install.installer.change_version=%s 与当前游戏不兼容,请更换版本 install.installer.choose=选择 %s 版本 install.installer.depend=需要先安装 %s install.installer.fabric=Fabric install.installer.fabric-api=Fabric API -install.installer.fabric-api.warning=警告:Fabric API 是一个模组,将会被安装到新游戏的模组文件夹,请你在安装游戏后不要修改当前游戏的版本隔离/游戏运行路径设置,如果你在之后修改了相关设置,Fabric API 需要被重新安装。 +install.installer.fabric-api.warning=警告:Fabric API 是一个模组,将会被安装到新游戏的模组文件夹,请你在安装游戏后不要修改当前游戏的“运行路径”设置,如果你在之后修改了相关设置,则需要重新安装 Fabric API。 install.installer.forge=Forge install.installer.neoforge=NeoForge install.installer.game=Minecraft install.installer.incompatible=与 %s 不兼容 install.installer.install=安装 %s install.installer.install_offline=从本地文件安装/升级 -install.installer.install_offline.extension=Forge/OptiFine 安装器 -install.installer.install_offline.tooltip=支持导入已经下载好的 Forge/OptiFine 安装器 +install.installer.install_offline.extension=(Neo)Forge/OptiFine 安装器 +install.installer.install_offline.tooltip=支持导入已经下载好的 (Neo)Forge/OptiFine 安装器 install.installer.install_online=在线安装 -install.installer.install_online.tooltip=支持安装 Fabric、Forge、OptiFine、LiteLoader +install.installer.install_online.tooltip=支持安装 Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine install.installer.liteloader=LiteLoader install.installer.not_installed=不安装 install.installer.optifine=OptiFine install.installer.quilt=Quilt install.installer.quilt-api=QSL/QFAPI install.installer.version=%s -install.installer.external_version=%s 由外部安装的版本,无法卸载或更换 +install.installer.external_version=%s (由外部安装的版本,无法卸载或更换) install.modpack=安装整合包 -install.new_game=安装新游戏版本 +install.new_game=安装新游戏 install.new_game.already_exists=此版本已经存在,请换一个名字 install.new_game.current_game_version=当前游戏版本 install.new_game.malformed=名字不合法 @@ -530,7 +530,7 @@ install.success=安装成功 java.add=添加 Java java.add.failed=Java 无效或与当前平台不兼容。 java.disable=禁用此 Java -java.disable.confirm=您确定要禁用此 Java 吗? +java.disable.confirm=你确定要禁用此 Java 吗? java.disabled.management=管理已禁用的 Java java.disabled.management.remove=从列表中移除此 Java java.disabled.management.restore=重新启用此 Java @@ -553,48 +553,48 @@ java.install.failed.invalid=该压缩包不是合法的 Java 安装包,无法 java.install.failed.unsupported_platform=此 Java 与当前平台不兼容,无法安装。 java.install.name=名称 java.install.warning.invalid_character=名称中包含非法字符 -java.reveal=浏览 Java 目录 +java.reveal=浏览 Java 文件夹 java.uninstall=卸载此 Java -java.uninstall.confirm=您确定要卸载此 Java 吗?此操作无法撤销! +java.uninstall.confirm=你确定要卸载此 Java 吗?此操作无法撤销! -lang=简体中文 +lang=简体中文 (中国大陆) lang.default=跟随系统语言 -launch.advice=%s是否继续启动? +launch.advice==%s 是否继续启动? launch.advice.multi=检测到以下问题:\n\n%s\n\n这些问题可能导致游戏无法正常启动或影响游戏体验,是否继续启动?\n你可以点击右上角帮助按钮进行求助。 -launch.advice.java.auto=当前选择的 Java 虚拟机版本不满足游戏要求\n点击“是”即可由 HMCL 来自动选取合适的 Java 虚拟机版本\n或者你可以到全局(特定)游戏设置中选择一个合适的 Java 虚拟机版本。 -launch.advice.java.modded_java_7=Minecraft 1.7.2 及以下版本需要 Java 7 及以下版本。 -launch.advice.corrected=我们已经修复了 Java 虚拟机版本问题。如果您确实希望使用您自定义的 Java 虚拟机,您可以在全局(特定)游戏设置往下滑,关闭 Java 虚拟机兼容性检查。 -launch.advice.uncorrected=如果您确实希望使用您自定义的 Java 虚拟机,您可以在全局(特定)游戏设置往下滑,关闭 Java 虚拟机兼容性检查 +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.corrected=我们已经修复了 Java 虚拟机版本问题。如果你确实希望使用你自定义的 Java 虚拟机,你可以在“(全局/版本特定) 游戏设置 → 高级设置”中往下滑,开启“不检查 JVM 与游戏的兼容性”。 +launch.advice.uncorrected=如果你确实希望使用你自定义的 Java 虚拟机,你可以在“(全局/版本特定) 游戏设置 → 高级设置”中往下滑,开启“不检查 JVM 与游戏的兼容性”。 launch.advice.different_platform=你正在使用 32 位 Java 启动游戏,建议更换至 64 位 Java。 -launch.advice.forge2760_liteloader=Forge 2760 与 LiteLoader 不兼容,请更新 Forge 至 2773 或更新的版本。 -launch.advice.forge28_2_2_optifine=Forge 28.2.2 或更高版本与 OptiFine 不兼容。请将 Forge 降级至 28.2.1 或更低版本。 -launch.advice.forge37_0_60=Forge 低于 37.0.60 的版本不兼容 Java 17。请更新 Forge 到 37.0.60 或更高版本,或者使用 Java 16 启动游戏。 -launch.advice.java8_1_13=Minecraft 1.13 及以上版本只能运行在 Java 8 或更高版本上,请使用 Java 8 或最新版本。 +launch.advice.forge2760_liteloader=Forge 14.23.5.2760 与 LiteLoader 不兼容,请更新 Forge 至 14.23.5.2773 或更高版本。 +launch.advice.forge28_2_2_optifine=Forge 28.2.2 及更高版本与 OptiFine 不兼容。请降级 Forge 至 28.2.1 或更低版本。 +launch.advice.forge37_0_60=Forge 37.0.59 及更低版本与 Java 17 不兼容。请更新 Forge 至 37.0.60 或更高版本,或使用 Java 16 启动游戏。 +launch.advice.java8_1_13=Minecraft 1.13 及更高版本只能在 Java 8 或更高版本上运行,请使用 Java 8 或最新版本。 launch.advice.java8_51_1_13=低于 1.8.0_51 的 Java 版本可能会导致 Minecraft 1.13 崩溃,建议更新 Java 至 1.8.0_51 或更高版本后再次启动。 -launch.advice.java9=低于 1.13 的有安装模组的 Minecraft 版本不支持 Java 9 或更高版本,请使用 Java 8。 +launch.advice.java9=低于 1.13 的有安装模组的 Minecraft 版本与 Java 9 或更高版本不兼容,请使用 Java 8。 launch.advice.modded_java=部分模组可能与高版本 Java 不兼容,建议使用 Java %s 启动 Minecraft %s。 -launch.advice.modlauncher8=您所使用的 Forge 版本与当前使用的 Java 不兼容,请更新 Forge。 +launch.advice.modlauncher8=你所使用的 Forge 版本与当前使用的 Java 不兼容,请更新 Forge。 launch.advice.newer_java=检测到你正在使用旧版本 Java 启动游戏,这可能导致部分模组引发游戏崩溃,建议更新至 Java 8 后再次启动。 -launch.advice.not_enough_space=你设置的内存大小过大,超过了系统内存容量 %dMB,可能导致游戏无法启动。 +launch.advice.not_enough_space=你设置的内存大小过大,超过了系统内存容量 %d MB,可能导致游戏无法启动。 launch.advice.require_newer_java_version=当前游戏版本需要 Java %s,但 HMCL 未能找到该 Java 版本,你可以点击“是”,HMCL 会自动下载他,是否下载?\n如遇到问题,你可以点击右上角帮助按钮进行求助。 -launch.advice.too_large_memory_for_32bit=您设置的内存大小过大,由于可能超过了 32 位 Java 的内存分配限制,所以可能无法启动游戏,请将内存调至 1024MB 或更小。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 -launch.advice.vanilla_linux_java_8=对于 Linux x86-64 平台,Minecraft 1.12.2 及以下版本与 Java 9+ 不兼容,请使用 Java 8 启动游戏。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 -launch.advice.vanilla_x86.translation=Minecraft 尚未为您的平台提供完善支持,所以可能影响游戏体验或无法启动游戏。\n你可以在 这里 下载 X86-64 架构的 Java 以获得更完整的体验。 +launch.advice.too_large_memory_for_32bit=你设置的内存大小过大,由于可能超过了 32 位 Java 的内存分配限制,所以可能无法启动游戏,请将内存调至 1024 MB 或更小。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +launch.advice.vanilla_linux_java_8=对于 Linux x86-64 平台,Minecraft 1.12.2 及更低版本与 Java 9+ 不兼容,请使用 Java 8 启动游戏。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +launch.advice.vanilla_x86.translation=Minecraft 尚未为你的平台提供完善支持,所以可能影响游戏体验或无法启动游戏。\n你可以在 这里 下载 x86-64 架构的 Java 以获得更完整的体验。 launch.advice.unknown=由于以下原因,无法继续启动游戏: launch.failed=启动失败 -launch.failed.cannot_create_jvm=截获到无法创建 Java 虚拟机,可能是 Java 参数有问题,可以在设置中开启无参数模式启动。 +launch.failed.cannot_create_jvm=无法创建 Java 虚拟机,可能是 Java 参数有问题,你可以在“(全局/版本特定) 游戏设置 → 高级设置 → Java 虚拟机设置”中移除所有 Java 虚拟机参数后,尝试再次启动游戏。 launch.failed.creating_process=启动失败,在创建新进程时发生错误,可能是 Java 路径错误。 -launch.failed.command_too_long=命令长度超过限制,无法创建 bat 脚本,请导出为 PowerShell 脚本。 +launch.failed.command_too_long=命令长度超过限制,无法创建批处理脚本,请导出为 PowerShell 脚本。 launch.failed.decompressing_natives=未能解压游戏本地库。 -launch.failed.download_library=未能下载游戏依赖 %s +launch.failed.download_library=未能下载游戏依赖“%s” launch.failed.executable_permission=未能为启动文件添加执行权限。 launch.failed.execution_policy=设置执行策略 launch.failed.execution_policy.failed_to_set=设置执行策略失败 -launch.failed.execution_policy.hint=当前执行策略阻止您执行 PowerShell 脚本。\n点击“确定”允许当前用户执行本地 PowerShell 脚本,或点击“取消”保持现状。 +launch.failed.execution_policy.hint=当前执行策略阻止你执行 PowerShell 脚本。\n点击“确定”允许当前用户执行本地 PowerShell 脚本,或点击“取消”保持现状。 launch.failed.exited_abnormally=游戏非正常退出,请查看日志文件,或联系他人寻求帮助。 launch.failed.java_version_too_low=你所指定的 Java 版本过低,请重新设置 Java 版本。 -launch.failed.no_accepted_java=找不到适合当前游戏使用的 Java,是否使用默认 Java 启动游戏?点击“是”使用默认 Java 继续启动游戏,\n或者请到全局(特定)游戏设置中选择一个合适的 Java 虚拟机版本。\n你可以点击右上角帮助按钮进行求助。 +launch.failed.no_accepted_java=找不到适合当前游戏使用的 Java,是否使用默认 Java 启动游戏?点击“是”使用默认 Java 继续启动游戏,\n或者在“(全局/版本特定) 游戏设置 → 游戏 Java”中选择一个合适的 Java 虚拟机版本。\n你可以点击右上角帮助按钮进行求助。 launch.failed.sigkill=游戏被用户或系统强制终止。 launch.state.dependencies=处理游戏依赖 launch.state.done=启动完成 @@ -609,26 +609,26 @@ launcher.agreement=用户协议与免责声明 launcher.agreement.accept=同意 launcher.agreement.decline=拒绝 launcher.agreement.hint=同意本软件的用户协议与免责声明以使用本软件。 -launcher.background=背景地址 -launcher.background.choose=选择背景路径 +launcher.background=背景图片 +launcher.background.choose=选择背景图片 launcher.background.classic=经典 -launcher.background.default=默认(自动检索启动器同目录下的 background.png/jpg/gif 及 bg 文件夹内的图片) +launcher.background.default=默认 (自动检索启动器同文件夹下的“background.png/.jpg/.gif”及“bg”文件夹内的图片) launcher.background.network=网络 launcher.background.translucent=半透明 -launcher.cache_directory=文件下载缓存目录 +launcher.cache_directory=文件下载缓存文件夹 launcher.cache_directory.clean=清理缓存 -launcher.cache_directory.choose=选择文件下载缓存目录 -launcher.cache_directory.default=默认(%AppData%/.minecraft 或者 ~/.minecraft) -launcher.cache_directory.disabled=禁用(总是使用游戏路径) -launcher.cache_directory.invalid=无法创建自定义的缓存目录,恢复默认设置 +launcher.cache_directory.choose=选择文件下载缓存文件夹 +launcher.cache_directory.default=默认 ("%AppData%/.minecraft" 或 "~/.minecraft") +launcher.cache_directory.disabled=禁用 (总是使用游戏文件夹路径) +launcher.cache_directory.invalid=无法创建自定义的缓存文件夹,恢复默认设置 launcher.contact=联系我们 -launcher.crash=Hello Minecraft! Launcher 遇到了无法处理的错误,请复制下列内容并点击右下角的按钮反馈 bug。 +launcher.crash=Hello Minecraft! Launcher 遇到了无法处理的错误,请复制下列内容并点击右下角的按钮反馈问题。 launcher.crash.java_internal_error=Hello Minecraft! Launcher 由于当前 Java 损坏而无法继续运行,请卸载当前 Java,点击 此处 安装合适的 Java 版本。 -launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher 遇到了无法处理的错误,已检测到您的启动器不是最新版本,请更新后再试。 -launcher.update_java=请更新您的 Java \n你可以访问\n https://docs.hmcl.net/help.html \n页面寻求帮助。 +launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher 遇到了无法处理的错误,已检测到你的启动器不是最新版本,请更新后再试。 +launcher.update_java=请更新你的 Java。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。 login.empty_username=你还未设置用户名! -login.enter_password=请输入您的密码 +login.enter_password=请输入你的密码 logwindow.show_lines=显示行数 logwindow.terminate_game=结束游戏进程 @@ -637,20 +637,20 @@ logwindow.help=你可以前往 HMCL 社区,寻找他人帮助 logwindow.autoscroll=自动滚动 logwindow.export_game_crash_logs=导出游戏崩溃信息 logwindow.export_dump=导出游戏运行栈 -logwindow.export_dump.no_dependency=你的 Java 不包含用于创建游戏运行栈的依赖。请前往 HMCL QQ 群或 Discord 频道寻求帮助。 +logwindow.export_dump.no_dependency=你的 Java 不包含用于创建游戏运行栈的依赖。请前往 HMCL QQ 群或 Discord 寻求帮助。 main_page=主页 message.cancelled=操作被取消 message.confirm=提示 -message.copied=已拷贝至剪贴板 +message.copied=已复制到剪贴板 message.default=默认 message.doing=请耐心等待 message.downloading=正在下载 message.error=错误 message.failed=操作失败 message.info=提示 -message.success=已完成 +message.success=完成 message.unknown=未知 message.warning=警告 @@ -660,27 +660,27 @@ modpack.choose.local=导入本地整合包文件 modpack.choose.local.detail=你可以直接将整合包文件拖入本页面以安装 modpack.choose.remote=从互联网下载整合包 modpack.choose.remote.detail=需要提供整合包的下载链接 -modpack.choose.repository=从 Curseforge / Modrinth 下载整合包 +modpack.choose.repository=从 CurseForge/Modrinth 下载整合包 modpack.choose.repository.detail=下载后记得回到这个界面,把整合包拖进来哦 modpack.choose.remote.tooltip=要下载的整合包的链接 modpack.completion=下载整合包相关文件 -modpack.desc=描述你要制作的整合包,比如整合包注意事项和更新记录,支持 HTML(图片请用网络图) +modpack.desc=描述你要制作的整合包,比如整合包注意事项和更新记录,支持 Markdown (图片请用网络链接) modpack.description=整合包描述 modpack.download=下载整合包 modpack.enter_name=给游戏起个你喜欢的名字 modpack.export=导出整合包 -modpack.export.as=请选择整合包类型 (若无法决定,请选择我的世界中文论坛整合包标准) +modpack.export.as=请选择整合包类型 (若无法决定,请选择“我的世界中文论坛整合包标准”) modpack.file_api=整合包下载链接前缀 modpack.files.blueprints=BuildCraft 蓝图 modpack.files.config=模组配置文件 modpack.files.dumps=NEI 调试输出 modpack.files.hmclversion_cfg=启动器配置文件 -modpack.files.liteconfig=模组配置文件 +modpack.files.liteconfig=LiteLoader 相关文件 modpack.files.mods=模组 modpack.files.mods.voxelmods=VoxelMods 配置,如小地图 -modpack.files.options_txt=游戏设定 -modpack.files.optionsshaders_txt=光影设定 -modpack.files.resourcepacks=资源包(材质包) +modpack.files.options_txt=游戏设置 +modpack.files.optionsshaders_txt=光影设置 +modpack.files.resourcepacks=资源包 (纹理包) modpack.files.saves=游戏存档 modpack.files.scripts=MineTweaker 配置 modpack.files.servers_dat=多人游戏服务器列表 @@ -688,19 +688,18 @@ modpack.install=安装 %s 整合包 modpack.installing=正在安装整合包 modpack.introduction=支持 Curse、Modrinth、MultiMC、MCBBS 整合包。 modpack.invalid=无效的整合包升级文件,可能是下载时出现问题。 -modpack.mismatched_type=整合包类型不匹配,当前游戏是 %s 整合包,但是提供的整合包更新文件是 %s 整合包。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +modpack.mismatched_type=整合包类型不匹配,当前游戏为“%s”整合包,但是提供的整合包更新文件为“%s”整合包。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 modpack.name=整合包名称 modpack.not_a_valid_name=不是一个有效的整合包名称 modpack.origin=来源 modpack.origin.url=官方网站 modpack.origin.mcbbs=MCBBS -modpack.origin.mcbbs.prompt=贴子 id +modpack.origin.mcbbs.prompt=帖子 ID modpack.scan=解析整合包 modpack.task.install=导入整合包 modpack.task.install.error=无法识别该整合包,目前仅支持导入 Curse、Modrinth、MultiMC、MCBBS 整合包。\n你可以点击右上角帮助按钮进行求助。 modpack.type.curse=Curse -modpack.type.curse.tolerable_error=但未能完成该整合包所需的依赖下载,您可以在启动该游戏版本时继续该整合包文件的下载。由于网络问题,您可能需要重试多次。\n你可以点击右上角帮助按钮进行求助。 -modpack.type.curse.error=未能完成该整合包所需的依赖下载,请多次重试或设置代理。\n你可以点击右上角帮助按钮进行求助。 +modpack.type.curse.error=未能完成该整合包所需的依赖下载,请再次尝试或设置代理。\n你可以点击右上角帮助按钮进行求助。 modpack.type.curse.not_found=部分必需文件已经在网络中被删除并且再也无法下载,请尝试该整合包的最新版本或者安装其他整合包。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 modpack.type.manual.warning=该整合包由发布者手动打包,其中可能已经包含启动器,建议尝试解压后使用其自带的启动器运行游戏。\n如遇到问题,你可以点击右上角帮助按钮进行求助。\nHMCL 可以尝试导入该整合包,但不保证可用性,是否继续? modpack.type.mcbbs=我的世界中文论坛整合包标准 @@ -710,21 +709,21 @@ modpack.type.multimc=MultiMC modpack.type.multimc.export=可以被 Hello Minecraft! Launcher 和 MultiMC 导入 modpack.type.server=服务器自动更新整合包 modpack.type.server.export=允许服务器管理员远程更新游戏客户端 -modpack.type.server.malformed=服务器整合包配置格式错误,请联系服务器管理员解决此问题\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +modpack.type.server.malformed=服务器整合包配置格式错误,请联系服务器管理员解决此问题。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 modpack.unsupported=Hello Minecraft! Launcher 不支持该整合包格式 modpack.update=正在升级整合包 modpack.wizard=导出整合包向导 modpack.wizard.step.1=基本设置 modpack.wizard.step.1.title=设置整合包的主要信息 modpack.wizard.step.2=文件选择 -modpack.wizard.step.2.title=选中你想加到整合包中的文件或文件夹 +modpack.wizard.step.2.title=选中你想添加到整合包中的文件或文件夹 modpack.wizard.step.3=整合包类型 modpack.wizard.step.3.title=选择整合包导出类型 modpack.wizard.step.initialization.exported_version=要导出的游戏版本 -modpack.wizard.step.initialization.force_update=强制升级整合包至最新版本(需要自建服务器) +modpack.wizard.step.initialization.force_update=强制升级整合包至最新版本 (需要自建服务器) modpack.wizard.step.initialization.include_launcher=包含启动器 modpack.wizard.step.initialization.save=选择要导出到的游戏整合包位置 -modpack.wizard.step.initialization.warning=在制作整合包前,请您确认您选择的版本可以正常启动,\n并保证您的 Minecraft 是正式版而非快照版,\n而且不应当将不允许非官方途径传播的模组、材质包等纳入整合包。\n整合包会保存您目前的下载源设置\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +modpack.wizard.step.initialization.warning=在制作整合包前,请你确认你选择的版本可以正常启动,\n并保证你的 Minecraft 是正式版而非快照,\n而且不应当将不允许非官方途径传播的模组、资源 (纹理) 包等纳入整合包。\n整合包会保存你目前的下载源设置。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 modpack.wizard.step.initialization.server=点击此处查看有关服务器自动更新整合包的制作教程 modrinth.category.adventure=冒险 From 655f42734a4051c2bf7fb6eb138e5399b5729c04 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 19 Oct 2024 21:41:54 +0800 Subject: [PATCH 040/169] Revise zh_TW part 1 (#3356) * Revise zh_TW part 1 * Update * Update * Update --- .../resources/assets/lang/I18N_zh.properties | 308 +++++++++--------- 1 file changed, 150 insertions(+), 158 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 8b279a9bc4..db6718b50d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -19,151 +19,143 @@ # Contributors: pan93412 about=關於 about.copyright=著作權 -about.copyright.statement=著作權所有 © 2024 huangyuhui。 +about.copyright.statement=著作權所有 © 2024 huangyuhui about.author=作者 -about.author.statement=bilibili: @huanghongxun -about.claim=用戶協議 +about.author.statement=bilibili @huanghongxun +about.claim=使用者協議 about.claim.statement=點擊連結以查看全文 about.dependency=相依元件 -about.legal=法律聲明 +about.legal=法律宣告 about.thanks_to=鳴謝 -about.thanks_to.bangbang93.statement=提供 BMCLAPI 下載地點。請贊助支持 BMCLAPI! -about.thanks_to.burningtnt.statement=為 HMCL 貢獻許多技術支持 -about.thanks_to.contributors=所有通過 Issues、Pull Requests 等管道參與本項目的貢獻者 -about.thanks_to.contributors.statement=沒有開源社區的支持,Hello Minecraft! Launcher 無法走到今天 +about.thanks_to.bangbang93.statement=提供 BMCLAPI 下載來源。請贊助支援 BMCLAPI! +about.thanks_to.burningtnt.statement=為 HMCL 貢獻許多技術支援 +about.thanks_to.contributors=所有透過 Issue、Pull Request 等管道參與本項目的貢獻者 +about.thanks_to.contributors.statement=沒有開源社群的支援,HMCL 無法走到今天 about.thanks_to.gamerteam.statement=提供預設背景圖 about.thanks_to.glavo.statement=負責 HMCL 的日常維護 -about.thanks_to.zekerzhayard.statement=為 HMCL 貢獻許多技術支持 -about.thanks_to.zkitefly.statement=負責維護 HMCL 的文檔 -about.thanks_to.mcbbs=MCBBS 我的世界中文論壇 +about.thanks_to.zekerzhayard.statement=為 HMCL 貢獻許多技術支援 +about.thanks_to.zkitefly.statement=負責維護 HMCL 的文件 +about.thanks_to.mcbbs=MCBBS (我的世界中文論壇) about.thanks_to.mcbbs.statement=提供 MCBBS 下載源 (現已停止服務) -about.thanks_to.mcmod=MC 百科 -about.thanks_to.mcmod.statement=提供 Mod 中文名映射表與 Mod 百科 +about.thanks_to.mcmod=MC 百科 (mcmod.cn) +about.thanks_to.mcmod.statement=提供模組簡體中文名映射表與模組百科 about.thanks_to.red_lnn.statement=提供預設背景圖 -about.thanks_to.shulkersakura.statement=提供 HMCL 的圖標 -about.thanks_to.users=HMCL 用戶群成員 -about.thanks_to.users.statement=感謝用戶群成員贊助充電、積極催更、迴響問題、出謀劃策 -about.thanks_to.yushijinhun.statement=authlib-injector 相关支援 +about.thanks_to.shulkersakura.statement=提供 HMCL 的標誌 +about.thanks_to.users=HMCL 使用者群組成員 +about.thanks_to.users.statement=感謝使用者群組成員贊助充電、積極催更、回報問題、出謀劃策 +about.thanks_to.yushijinhun.statement=提供 authlib-injector 相關支援 about.open_source=開放原始碼 about.open_source.statement=GPL v3 (https://github.com/HMCL-dev/HMCL/) account=帳戶 account.cape=披風 account.character=角色 -account.choose=請選擇角色 +account.choose=請選取角色 account.create=建立帳戶 -account.create.microsoft=添加微軟帳戶 -account.create.offline=添加離線模式帳戶 -account.create.authlibInjector=添加外置登入帳戶 (authlib-injector) +account.create.microsoft=加入 Microsoft 帳戶 +account.create.offline=加入離線模式帳戶 +account.create.authlibInjector=加入 authlib-injector 帳戶 account.email=電子信箱 -account.failed=帳戶刷新失敗 +account.failed=帳戶重新整理失敗 account.failed.character_deleted=已刪除此角色 -account.failed.connect_authentication_server=無法連線至認證伺服器,可能是網路問題,請檢查設備能否正常上網或使用代理服務 -account.failed.connect_injector_server=無法連線至認證伺服器,可能是網路故障,請檢查設備能否正常上網、檢查網址是否輸入錯誤或使用代理服務 -account.failed.injector_download_failure=無法下載 authlib-injector,請檢查網路或嘗試切換下載來源 -account.failed.invalid_credentials=您的使用者名稱或密碼錯誤,或者登入次數過多被暫時禁止登入,請稍後再試 +account.failed.connect_authentication_server=無法連線至認證伺服器,可能是網路問題,請檢查裝置能否正常上網或使用代理服務。 +account.failed.connect_injector_server=無法連線至認證伺服器,可能是網路故障,請檢查裝置能否正常上網、檢查網址是否輸入錯誤或使用代理服務。 +account.failed.injector_download_failure=無法下載 authlib-injector,請檢查網路或嘗試切換下載來源。 +account.failed.invalid_credentials=你的使用者名稱或密碼錯誤,或者登入次數過多被暫時禁止登入,請稍後再試。 account.failed.invalid_password=密碼無效 -account.failed.invalid_token=請嘗試登出並重新輸入密碼登入 -account.failed.migration=你的帳號需要被遷移至微軟帳號。如果你已經遷移,你需要使用微軟登錄方式登錄遷移後的微軟帳號 -account.failed.no_character=該帳戶沒有角色 -account.failed.server_disconnected=無法訪問登錄伺服器,賬戶信息刷新失敗。\n\ - 您可以選擇“再次刷新賬戶”重新嘗試。\n\ - 您也可以選擇“跳過賬戶刷新”繼續啟動遊戲,但可能會使賬戶信息不是最新的。\n\ - 若最近沒有刷新賬戶信息,則可能導致賬戶信息過期失效,\n\ - 若為 微軟賬戶 啟動遊戲,賬戶信息過期失效可能將無法進入需賬戶驗證的伺服器。\n\ - 若嘗試多次無法成功刷新,可嘗試重新添加該賬戶嘗試解決該問題。 -account.failed.server_response_malformed=無法解析認證伺服器回應,可能是伺服器故障 -account.failed.ssl=連接服務器時發生了 SSL 錯誤,可能網站證書已過期或你使用的 Java 版本過低,請嘗試更新 Java -account.failed.wrong_account=登錄了錯誤的帳號 -account.hmcl.hint=你需要點擊“登入”按鈕,並在打開的網頁中完成登入 +account.failed.invalid_token=請嘗試登出並重新輸入密碼登入。 +account.failed.migration=你的帳戶需要遷移至 Microsoft 帳戶。如果你已經遷移,你需要使用 Microsoft 方式登入遷移後的帳戶。 +account.failed.no_character=該帳戶沒有角色。 +account.failed.server_disconnected=無法訪問登入伺服器,帳戶資訊重新整理失敗。\n\ + 你可以選取「再次重新整理帳戶」重新嘗試。\n\ + 你也可以選取「跳過帳戶重新整理」繼續啟動遊戲,但可能會導致帳戶資訊未同步更新。\n\ + 若最近沒有重新整理帳戶資訊,則可能導致帳戶資訊過期失效。\n\ + 若使用 Microsoft/authlib-injector 帳戶啟動遊戲,帳戶資訊過期失效可能將無法進入需線上驗證的伺服器。\n\ + 若嘗試多次無法重新整理,可嘗試重新加入該帳戶,或許可以解決該問題。 +account.failed.server_response_malformed=無法解析認證伺服器回應,可能是伺服器故障。 +account.failed.ssl=連線伺服器時發生了 SSL 錯誤,可能網站證書已過期或你使用的 Java 版本過低,請嘗試更新 Java。 +account.failed.wrong_account=登入了錯誤的帳戶 +account.hmcl.hint=你需要點擊「登入」按鈕,並在打開的網頁中完成登入 account.injector.add=新增認證伺服器 account.injector.empty=無 (按一下右側 + 加入) -account.injector.http=警告: 此伺服器使用不安全的 HTTP 協定,您的密碼在登入時會被明文傳輸。 +account.injector.http=警告: 此伺服器使用不安全的 HTTP 協定,你的密碼在登入時會被明文傳輸。 account.injector.link.homepage=首頁 account.injector.link.register=註冊 account.injector.server=認證伺服器 account.injector.server_url=伺服器位址 account.injector.server_name=伺服器名稱 account.login=登入 -account.login.hint=我們不會保存你的密碼 -account.login.skip=跳過刷新帳戶 -account.login.retry=再次刷新帳戶 -account.login.refresh=重新登錄 -account.login.refresh.microsoft.hint=因為賬戶授權失效,你需要重新添加微軟賬戶 +account.login.hint=我們不會儲存你的密碼 +account.login.skip=跳過重新整理帳戶 +account.login.retry=再次重新整理帳戶 +account.login.refresh=重新登入 +account.login.refresh.microsoft.hint=由於帳戶授權失效,你需要重新加入 Microsoft 帳戶 account.logout=登出 account.register=註冊 -account.manage=帳戶列表 -account.copy_uuid=複製該賬戶的 UUID。 +account.manage=帳戶清單 +account.copy_uuid=複製該帳戶的 UUID account.methods=登入方式 account.methods.authlib_injector=authlib-injector 登入 -account.methods.microsoft=微軟帳戶 +account.methods.microsoft=Microsoft 帳戶 account.methods.microsoft.birth=如何修改帳戶出生日期 account.methods.microsoft.deauthorize=解除帳戶授權 -account.methods.microsoft.close_page=已完成微軟帳號授權,接下來啟動器還需要完成剩餘登入步驟。你已經可以關閉本頁面了。 -account.methods.microsoft.error.add_family=由於你未滿 18 歲,你的帳戶必須被加入到家庭中才能登錄遊戲。你也可以點擊上方連結更改你的帳戶的出生日期,使年齡滿 18 歲以上以繼續登錄。 -account.methods.microsoft.error.add_family_probably=請檢查你的帳戶設置,如果你未滿 18 歲,你的帳戶必須被加入到家庭中才能登錄遊戲。你也可以點擊上方連結更改你的帳戶的出生日期,使年齡滿 18 歲以上以繼續登錄。 -account.methods.microsoft.error.country_unavailable=你所在的國家或地區不受 XBox Live 的支援。 -account.methods.microsoft.error.missing_xbox_account=你的微軟帳號尚未關聯 XBox 帳號,你必須先創建 XBox 帳號,才能登入遊戲。 -account.methods.microsoft.error.no_character=該帳戶未包含 Minecraft Java 版購買記錄\n可能未創建遊戲檔案,請點擊上方鏈接創建 +account.methods.microsoft.close_page=已完成 Microsoft 帳戶授權,接下來啟動器還需要完成其餘登入步驟。你現在可以關閉本頁面了。 +account.methods.microsoft.error.add_family=由於你未滿 18 歲,你的帳戶必須被加入到家庭中才能登入遊戲。你也可以點擊上方連結更改你的帳戶的出生日期,使年齡滿 18 歲以上以繼續登入。 +account.methods.microsoft.error.add_family_probably=請檢查你的帳戶設定,如果你未滿 18 歲,你的帳戶必須被加入到家庭中才能登入遊戲。你也可以點擊上方連結更改你的帳戶的出生日期,使年齡滿 18 歲以上以繼續登入。 +account.methods.microsoft.error.country_unavailable=你所在的國家或地區不受 Xbox Live 的支援。 +account.methods.microsoft.error.missing_xbox_account=你的 Microsoft 帳戶尚未關聯 Xbox 帳戶,你必須先建立 Xbox 帳戶,才能登入遊戲。 +account.methods.microsoft.error.no_character=該帳戶未包含 Minecraft: Java 版購買記錄。\n若已購買,則可能未建立遊戲檔案,請點擊上方連結建立。 account.methods.microsoft.error.unknown=登入失敗,錯誤碼:%d -account.methods.microsoft.error.wrong_verify_method=請在 Microsoft 帳號登陸頁面使用帳號 + 密碼登入。請不要使用驗證碼登入。 -account.methods.microsoft.logging_in=登入中... -account.methods.microsoft.makegameidsettings=創建檔案/編輯檔案名稱 -account.methods.microsoft.hint=你需要按照以下步驟添加賬戶:\n\ - 1.點擊“登入”按鈕\n\ - 2.在網頁瀏覽器顯示的網站中輸入 HMCL 顯示的代碼(自動拷貝,直接粘貼即可),並點擊“下一步”\n\ - 3.按照網站的提示登入\n\ - 4.當網站顯示“ 是否允許此應用訪問你的信息?”的標識時,請點擊“是”\n\ - 5.在網站提示“大功告成”後,只需等待帳戶完成添加即可\n\ - 若網站提示“出现错误”的標識,請嘗試重新按照以上步驟登入\n\ - -若賬戶添加失敗,請嘗試重新按照以上步驟登入\n\ - -若登入微軟賬號的 Token 洩露,可點擊下方“解除帳戶授權”解除登入授權,然後等待 Token 過期\n\ +account.methods.microsoft.error.wrong_verify_method=請在 Microsoft 帳戶登入頁面使用密碼登入,不要使用驗證碼登入。 +account.methods.microsoft.logging_in=登入中…… +account.methods.microsoft.makegameidsettings=建立檔案 / 編輯檔案名稱 +account.methods.microsoft.hint=請點擊「登入」按鈕,稍後複製此處顯示的代碼,在打開的登入網頁中完成登入過程。\n\ + \n\ + 如果登入 Microsoft 帳戶的令牌洩露,可點擊下方連結解除授權,然後等待令牌過期。\n\ + \n\ 如遇到問題,你可以點擊右上角幫助按鈕進行求助。 -account.methods.microsoft.manual=你需要按照以下步驟添加账户:\n\ - 1.點擊“登入”按鈕\n\ - 2.在網頁瀏覽器顯示的網站中輸入該代碼:%1$s(已自動拷貝,請點此處再次拷貝),並點擊“下一步”\n\ - 3.按照網站的提示登入\n\ - 4.當網站顯示“ 是否允許此應用訪問你的信息?”的標識時,請點擊“是”\n\ - 5.在網站提示“大功告成”後,只需等待帳戶完成添加即可\n\ - -若網站提示“出现错误”的標識或賬戶添加失敗時,請嘗試重新按照以上步驟登入\n\ - -若網站未能打開,請手動在網頁瀏覽器中打開:%2$s\n\ - -若登入微軟賬號的 Token 洩露,可點擊下方“解除帳戶授權”解除登入授權,然後等待 Token 過期\n\ +account.methods.microsoft.manual=你的代碼為 %1$s,請點擊此處複製。\n\ + \n\ + 點擊「登入」按鈕後,你應該在打開的登入網頁中完成登入過程。如果網頁沒有打開,你可以自行在瀏覽器中訪問 %2$s\n\ + \n\ + 如果登入 Microsoft 帳戶的令牌洩露,可點擊下方連結解除授權,然後等待令牌過期。\n\ + \n\ 如遇到問題,你可以點擊右上角幫助按鈕進行求助。 -account.methods.microsoft.profile=帳戶設置頁 +account.methods.microsoft.profile=帳戶設定頁 account.methods.microsoft.purchase=購買 Minecraft account.methods.forgot_password=忘記密碼 -account.methods.microsoft.snapshot=你正在使用非官方構建的 HMCL,請下載官方構建進行微軟登入。 +account.methods.microsoft.snapshot=你正在使用第三方提供的 HMCL,請下載官方版本進行登入。 account.methods.microsoft.snapshot.website=官方網站 account.methods.offline=離線模式 -account.methods.offline.name.special_characters=建議使用英文字符、數字以及下劃線命名 -account.methods.offline.name.invalid=正常情況下,遊戲用戶名只能包括英文字符、數字以及下劃線,且長度不能超過 16 個字符。\n\ - 一些合法的用戶名:HuangYu,huang_Yu,Huang_Yu_123;\n\ - 一些不合法的用戶名:黃魚,Huang Yu,Huang-Yu_%%%,Huang_Yu_hello_world_hello_world。\n\ - 如果你相信服務器端有相應的 Mod 或插件來解除此限制,你可以忽略本警告。 +account.methods.offline.name.special_characters=建議使用英文字母、數字以及底線命名 +account.methods.offline.name.invalid=遊戲使用者名稱通常僅允許使用英文字母、數字及底線,且長度不能超過 16 個字元。\n\ + \ · 一些有效的使用者名稱:HuangYu、huang_Yu、Huang_Yu_123;\n\ + \ · 一些無效的使用者名稱:黃魚,Huang Yu、Huang-Yu_%%%、Huang_Yu_hello_world_hello_world。\n\ + 如果你相信伺服器端有相應的模組或插件來解除此限制,你可以忽略本警告。 account.methods.offline.uuid=UUID -account.methods.offline.uuid.hint=UUID 是 Minecraft 對玩家角色的唯一標識符,每個啟動器生成 UUID 的方式可能不同。通過修改 UUID 選項至原啟動器所生成的 UUID,你可以保證在切換啟動器後,遊戲還能將你的遊戲角色識別為給定 UUID 所對應的角色,從而保留原來角色的背包物品。UUID 選項為高級選項,除非你知道你在做什麼,否則你不需要調整該選項。 +account.methods.offline.uuid.hint=UUID 是 Minecraft 玩家的唯一標識符,每個啟動器生成 UUID 的方式可能不同。\n透過修改 UUID 選項至原啟動器所生成的 UUID,你可以保證在切換啟動器後,遊戲還能將你的遊戲角色識別為給定 UUID 所對應的角色,從而保留原來角色的背包物品。\nUUID 選項為進階選項,除非你知道你在做什麼,否則你不需要調整該選項。 account.methods.offline.uuid.malformed=格式錯誤 account.missing=沒有遊戲帳戶 account.missing.add=按一下此處加入帳戶 -account.move_to_global=轉換為全域帳戶 -account.move_to_portable=轉換為便攜帳戶 +account.move_to_global=轉換為全域帳戶\n該帳戶的資訊會儲存至系統目前使用者目錄的配置檔案中 +account.move_to_portable=轉換為可攜式帳戶\n該帳戶的資訊會儲存至與 HMCL 同目錄的配置檔案中 account.not_logged_in=未登入 account.password=密碼 -account.portable=便攜帳戶 -account.skin=皮膚 -account.skin.file=皮膚圖片檔案 +account.portable=可攜式帳戶 +account.skin=外觀 +account.skin.file=外觀圖片檔案 account.skin.model=模型 -account.skin.model.default=經典 -account.skin.model.slim=苗條 +account.skin.model.default=寬型 +account.skin.model.slim=纖細 account.skin.type.csl_api=Blessing Skin 伺服器 account.skin.type.csl_api.location=伺服器位址 account.skin.type.csl_api.location.hint=CustomSkinAPI 位址 account.skin.type.little_skin=LittleSkin 皮膚站 -account.skin.type.little_skin.hint=你需要在皮膚站中創建並使用和該離線帳戶角色同名角色,此時離線帳戶皮膚將為皮膚站上角色所設定的皮膚。 -account.skin.type.local_file=本地皮膚圖片檔案 -account.skin.upload=上傳皮膚 -account.skin.upload.failed=皮膚上傳失敗 -account.skin.invalid_skin=無法識別的皮膚檔案 +account.skin.type.little_skin.hint=你需要在皮膚站中建立並使用和該離線帳戶同名角色,此時離線帳戶外觀將為皮膚站上角色所設定的外觀。 +account.skin.type.local_file=本機外觀圖片檔案 +account.skin.upload=上傳/編輯外觀 +account.skin.upload.failed=外觀上傳失敗 +account.skin.invalid_skin=無法識別的外觀檔案 account.username=使用者名稱 archive.author=作者 @@ -173,7 +165,7 @@ archive.version=版本 assets.download=下載資源 assets.download_all=驗證資源檔案完整性 -assets.index.malformed=資源檔案的索引檔案損壞,您可以在遊戲 [設定] 頁面右上角的設定按鈕中選擇 [更新遊戲資源檔案],以修復該問題 +assets.index.malformed=資源檔案的索引檔案損壞,你可以在相應實例的「實例設定」頁面中,點擊設定頁面左下角的「設定」按鈕並選取「更新遊戲資源檔案」,以修復該問題。 button.cancel=取消 button.change_source=切換下載源 @@ -187,10 +179,10 @@ button.no=否 button.ok=確定 button.refresh=重新整理 button.remove=刪除 -button.remove.confirm=您確認要刪除嗎?該操作無法撤銷! +button.remove.confirm=你確認要刪除嗎?該操作無法復原! button.retry=重試 button.save=儲存 -button.save_as=另存為 +button.save_as=另存新檔 button.select_all=全選 button.view=查看 button.yes=是 @@ -200,15 +192,15 @@ chat=官方群組 color.recent=建議 color.custom=自訂顏色 -crash.NoClassDefFound=請確認 Hello Minecraft! Launcher 本體是否完整,或更新您的 Java。 -crash.user_fault=您的系統或 Java 環境可能安裝不當導致本軟體當機,請檢查您的 Java 環境或您的電腦! 可以嘗試重新安裝 Java。 +crash.NoClassDefFound=請確認 Hello Minecraft! Launcher 本體是否完整,或更新你的 Java。 +crash.user_fault=你的系統或 Java 環境可能安裝不當導致本軟體當機,請檢查你的 Java 環境或你的電腦!可以嘗試重新安裝 Java。 curse.category.0=全部 # https://addons-ecs.forgesvc.net/api/v2/category/section/4471 curse.category.4474=科幻 curse.category.4481=輕量模組包 -curse.category.4483=戰鬥 PVP +curse.category.4483=戰鬥 PvP curse.category.4477=小遊戲 curse.category.4478=任務 curse.category.4484=多人 @@ -228,15 +220,15 @@ curse.category.7418=恐怖 curse.category.5299=教育 curse.category.5232=額外行星 curse.category.5129=原版增強 -curse.category.5189=實用與QOL +curse.category.5189=實用與 QOL curse.category.6814=性能 -curse.category.6954=動態聯合/集成動力 (Integrated Dynamics) +curse.category.6954=動態聯合/整合動力 (Integrated Dynamics) curse.category.6484=機械動力 (Create) curse.category.6821=錯誤修復 curse.category.6145=空島 -curse.category.5190=QoL -curse.category.5191=實用與QoL -curse.category.5192=夢幻菜單 +curse.category.5190=QOL +curse.category.5191=實用與 QOL +curse.category.5192=夢幻選單 curse.category.423=訊息展示 curse.category.426=模組擴展 curse.category.434=裝備武器 @@ -265,7 +257,7 @@ curse.category.433=林業 (Forestry) curse.category.425=其他 curse.category.4545=應用能源 2 (Applied Energistics 2) curse.category.416=農業 -curse.category.421=支持庫 +curse.category.421=支援庫 curse.category.4780=Fabric curse.category.424=裝飾 curse.category.406=世界生成 @@ -293,7 +285,7 @@ curse.category.393=16x curse.category.403=傳統 curse.category.394=32x curse.category.404=動態效果 -curse.category.4465=模組支持 +curse.category.4465=模組支援 curse.category.402=中世紀風格 curse.category.401=現代風格 @@ -317,88 +309,88 @@ curse.category.4549=指引書 curse.category.4547=配置 curse.category.4550=任務 curse.category.4555=世界生成 -curse.category.4552=腳本 +curse.category.4552=指令碼 curse.sort.author=作者 -curse.sort.date_created=創建日期 +curse.sort.date_created=建立日期 curse.sort.last_updated=最近更新 curse.sort.name=名稱 curse.sort.popularity=熱度 curse.sort.total_downloads=下載量 download=下載 -download.hint=安裝遊戲和整合包或下載模組、資源包和地圖 -download.code.404=遠端伺服器沒有需要下載的檔案: %s +download.hint=安裝遊戲和模組包或下載模組、資源包和地圖 +download.code.404=遠端伺服器沒有需要下載的檔案:%s download.content=遊戲內容 -download.curseforge.unavailable=HMCL 預覽版暫不支持訪問 CurseForge,請使用穩定版或測試版進行下載。 -download.existing=檔案已存在,無法保存。你可以選擇另存為將檔案保存至其他地方。 +download.curseforge.unavailable=HMCL 快照版暫不支援訪問 CurseForge,請使用穩定版或測試版進行下載。 +download.existing=檔案已存在,無法儲存。你可以將檔案儲存至其他地方。 download.external_link=打開下載網站 -download.failed=下載失敗: %1$s,錯誤碼:%2$d -download.failed.empty=沒有能安裝的版本,按一下此處返回。 -download.failed.no_code=下載失敗: %s -download.failed.refresh=載入版本列表失敗,按一下此處重試。 +download.failed=下載失敗:%1$s\n錯誤碼:%2$d +download.failed.empty=沒有可供安裝的版本,按一下此處返回。 +download.failed.no_code=下載失敗:%s +download.failed.refresh=載入版本清單失敗,按一下此處重試。 download.game=新遊戲 download.provider.bmclapi=BMCLAPI (bangbang93,https://bmclapi2.bangbang93.com/) -download.provider.mojang=官方伺服器 (OptiFine 自動安裝的下載來源是 BMCLAPI) -download.provider.official=儘量使用官方源(最新,但可能加載慢) -download.provider.balanced=選擇加載速度快的下載源(平衡,但可能不是最新) -download.provider.mirror=儘量使用鏡像源(加載快,但可能不是最新) +download.provider.mojang=官方伺服器 (OptiFine 由 BMCLAPI 提供) +download.provider.official=盡量使用官方源 (最新,但可能載入慢) +download.provider.balanced=選取載入速度快的下載源 (平衡,但可能不是最新) +download.provider.mirror=盡量使用鏡像源 (載入快,但可能不是最新) download.java=下載 Java download.java.override=此 Java 版本已經存在,是否移除並重新安裝? -download.javafx=正在下載必要的運行時組件 -download.javafx.notes=正在通過網絡下載 HMCL 必要的運行時組件。\n點擊“切換下載源”按鈕查看詳情以及選擇下載源,點擊“取消”按鈕停止並退出。\n注意:如果下載速度過慢,請嘗試切换下載源。 -download.javafx.component=正在下載模塊 %s +download.javafx=正在下載必要的執行時元件 +download.javafx.notes=正在透過網路下載 HMCL 必要的執行時元件。\n點擊「切換下載源」按鈕查看詳情以及選取下載源,點擊「取消」按鈕停止並退出。\n注意:如果下載速度過慢,請嘗試切換下載源。 +download.javafx.component=正在下載元件「%s」 download.javafx.prepare=準備開始下載 -exception.access_denied=因為無法存取檔案 %s,HMCL 沒有對該文件的訪問權限,或者該文件被其他程序打開。\n\ - 請你檢查當前操作系統帳戶是否能訪存取檔案,比如非管理員用戶可能不能訪問其他帳戶的個人資料夾內的文件。\n\ - 對於 Windows 用戶,你還可以嘗試通過資源監視器查看是否有程序占用了該文件,如果是,你可以關閉占用此文件相關程序,或者重啟電腦再試。 -exception.artifact_malformed=下載的文件正確,無法通過校驗。 -exception.ssl_handshake=無法建立 SSL 連接,因為當前 Java 虛擬機缺少相關的 SSL 證書。你可以嘗試使用其他的 Java 虛擬機或關閉網絡代理啟動 HMCL 再試。 +exception.access_denied=無法存取檔案「%s」,因為 HMCL 沒有對該檔案的訪問權限,或者該檔案已被其他程式打開。\n\ + 請你檢查目前作業系統帳戶是否能訪存取檔案,比如非管理員使用者可能不能訪問其他帳戶的個人目錄內的檔案。\n\ + 對於 Windows 使用者,你還可以嘗試透過資源監視器查看是否有程式占用了該檔案,如果是,你可以關閉占用此檔案的程式,或者重啟電腦再試。 +exception.artifact_malformed=下載的檔案正確,但無法透過校驗。 +exception.ssl_handshake=無法建立 SSL 連線,因為目前 Java 虛擬機缺少相關的 SSL 證書。你可以嘗試使用其他的 Java 虛擬機或關閉網路代理啟動 HMCL 再試。 -extension.bat=Windows 指令碼 +extension.bat=Windows 批次檔 extension.mod=模組檔案 extension.png=圖片檔案 extension.ps1=PowerShell 指令碼 extension.sh=Bash 指令碼 -fatal.javafx.incompatible=缺少 JavaFX 運行環境。\nHMCL 無法在低於 Java 11 的 Java 環境上自行補全 JavaFX 運行環境,請更新到 Java 11 或更高版本。 -fatal.javafx.incomplete=JavaFX 運行環境不完整,請嘗試更換你的 Java 或者重新安裝 OpenJFX。 -fatal.javafx.missing=缺少 JavaFX 運行環境,請使用包含 OpenJFX 的 Java 運行環境啟動 Hello Minecraft! Launcher。\n你可以訪問 https://docs.hmcl.net/help.html 頁面尋求幫助。 +fatal.javafx.incompatible=缺少 JavaFX 執行環境。\nHMCL 無法在低於 Java 11 的 Java 環境上自行補全 JavaFX 執行環境,請更新到 Java 11 或更高版本。 +fatal.javafx.incomplete=JavaFX 執行環境不完整,請嘗試更換你的 Java 或者重新安裝 OpenJFX。 +fatal.javafx.missing=缺少 JavaFX 執行環境,請使用包含 OpenJFX 的 Java 執行環境啟動 Hello Minecraft! Launcher。 fatal.config_change_owner_root=你正在使用 root 帳戶啟動 Hello Minecraft! Launcher,這可能導致你未來無法使用其他帳戶正常啟動 Hello Minecraft! Launcher。\n是否繼續啟動? -fatal.config_in_temp_dir=你正在臨時資料夾中啟動 Hello Minecraft! Launcher,你的設定和遊戲數據可能會遺失,建議將 HMCL 移動至其他位置再啟動。\n是否繼續啟動? -fatal.config_loading_failure=Hello Minecraft! Launcher 無法載入設定檔案。\n請確保 Hello Minecraft! Launcher 對 "%s" 目錄及該目錄下的檔案擁有讀寫權限。 -fatal.config_loading_failure.unix=Hello Minecraft! Launcher 無法載入設定檔案,因為設定檔案是由用戶 %1$s 創建的。\n請使用 root 帳戶啟動 HMCL (不推薦),或在終端中執行以下命令將設定檔案的所有權變更為當前用戶:\n%2$s -fatal.mac_app_translocation=由於 macOS 的安全機制,Hello Minecraft! Launcher 被系統隔離至臨時資料夾中。\n請將Hello Minecraft! Launcher 移動到其他資料夾後再嘗試啟動,否則你的設定和遊戲數據可能會在重啟後遺失。\n是否繼續啟動? +fatal.config_in_temp_dir=你正在暫存目錄中啟動 Hello Minecraft! Launcher,你的設定和遊戲資料可能會遺失,建議將 Hello Minecraft! Launcher 移動至其他位置再啟動。\n是否繼續啟動? +fatal.config_loading_failure=Hello Minecraft! Launcher 無法載入設定檔案。\n請確保 Hello Minecraft! Launcher 對「%s」目錄及該目錄下的檔案擁有讀寫權限。 +fatal.config_loading_failure.unix=Hello Minecraft! Launcher 無法載入設定檔案,因為設定檔案是由使用者「%1$s」建立的。\n請使用 root 帳戶啟動 HMCL (不推薦),或在終端中執行以下指令將設定檔案的所有權變更為目前使用者:\n%2$s +fatal.mac_app_translocation=由於 macOS 的安全機制,Hello Minecraft! Launcher 被系統隔離至暫存目錄中。\n請將 Hello Minecraft! Launcher 移動到其他目錄後再嘗試啟動,否則你的設定和遊戲資料可能會在重啟後遺失。\n是否繼續啟動? fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher 即將升級完成,請重新開啟 Hello Minecraft! Launcher。 -fatal.apply_update_failure=我們很抱歉 Hello Minecraft! Launcher 無法自動完成升級程式,因為出現了一些問題。\n但你依然可以從 %s 處手動下載 Hello Minecraft! Launcher 來完成升級。\n你可以訪問 https://docs.hmcl.net/help.html 網頁進行迴響。 +fatal.apply_update_failure=我們很抱歉 Hello Minecraft! Launcher 無法自動完成升級程式,因為出現了一些問題。\n但你依然可以從 %s 處手動下載 Hello Minecraft! Launcher 來完成升級。 fatal.apply_update_need_win7=Hello Minecraft! Launcher 無法在 Windows XP/Vista 上進行自動更新,請從 %s 處手動下載 Hello Minecraft! Launcher 來完成升級。 -fatal.samba=如果您正在通過 Samba 共亯的資料夾中運行 Hello Minecraft! Launcher,啟動器可能無法正常工作,請嘗試更新您的 Java 或在本地資料夾內運行 HMCL。 -fatal.illegal_char=由於您的用戶資料夾路徑中存在非法字元‘=’,您將無法使用外置登入帳戶以及離線登入更換皮膚功能。 -fatal.unsupported_platform=Minecraft 尚未你您的平臺提供完善支持,所以可能影響遊戲體驗或無法啟動遊戲。\n若無法啟動 Minecraft 1.17 及以上版本,可以嘗試在版本設定中打開“使用 OpenGL 軟渲染器”選項,使用 CPU 渲染以獲得更好的相容性。 +fatal.samba=如果您正在透過 Samba 共亯的目錄中執行 Hello Minecraft! Launcher,啟動器可能無法正常工作,請嘗試更新您的 Java 或在本機目錄內執行 HMCL。 +fatal.illegal_char=由於您的使用者目錄路徑中存在無效字元『=』,您將無法使用外部登入帳戶以及離線登入更換外觀功能。 +fatal.unsupported_platform=Minecraft 尚未你您的平臺提供完善支援,所以可能影響遊戲體驗或無法啟動遊戲。\n若無法啟動 Minecraft 1.17 及更高版本,可以嘗試在「(全域/實例特定) 遊戲設定 → 進階設定 → 除錯選項」中將「繪製器」切換為「軟繪製器」,以獲得更好的相容性。 fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher 已為龍芯提供支援。\n如果遇到問題,你可以點擊右上角幫助按鈕進行求助。 fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher 已為 Apple Silicon 平臺提供支援,使用 ARM 原生 Java 啟動遊戲以獲得更流暢的遊戲體驗。\n如果你在遊戲中遭遇問題,使用 x86-64 架構的 Java 啟動遊戲可能有更好的相容性。 -fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已為 Windows on Arm 平臺提供原生支持。如果你在遊戲中遭遇問題,請嘗試使用 x86 架構的 Java 啟動遊戲。\n\n如果你正在使用高通平臺,你可能需要安裝 OpenGL 相容包後才能進行遊戲。點擊連結前往 Microsoft Store 安裝相容包。 +fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已為 Windows on ARM 平臺提供原生支援。如果你在遊戲中遭遇問題,請嘗試使用 x86 架構的 Java 啟動遊戲。\n\n如果你正在使用高通平臺,你可能需要安裝 OpenGL 相容包後才能進行遊戲。點擊連結前往 Microsoft Store 安裝相容包。 -feedback=反饋 -feedback.channel=反饋渠道 +feedback=回報 +feedback.channel=回報管道 feedback.discord=Discord -feedback.discord.statement=歡迎加入 Discord 討論區,加入後請遵守討論區規定。 -feedback.github=GitHub Issue -feedback.github.statement=打開一個 GitHub Issue。 -feedback.qq_group=HMCL 用戶群 -feedback.qq_group.statement=歡迎加入 HMCL 用戶群,加入後請遵守群規。 +feedback.discord.statement=歡迎加入 Discord 討論區,加入後請遵守討論區規定 +feedback.github=GitHub Issues +feedback.github.statement=提交一個 GitHub Issue +feedback.qq_group=HMCL 使用者群組 +feedback.qq_group.statement=歡迎加入 HMCL 使用者群組,加入後請遵守群規 file=檔案 -folder.config=設定資料夾 -folder.game=遊戲資料夾 -folder.logs=日誌文件夾 -folder.mod=MOD 模組資料夾 -folder.resourcepacks=資源包資料夾 -folder.shaderpacks=著色器包文件夾 -folder.saves=遊戲存檔資料夾 -folder.screenshots=截圖資料夾 +folder.config=模組設定目錄 +folder.game=實例執行目錄 +folder.logs=日誌目錄 +folder.mod=模組目錄 +folder.resourcepacks=資源包目錄 +folder.shaderpacks=著色器包目錄 +folder.saves=遊戲存檔目錄 +folder.screenshots=截圖目錄 game=遊戲 game.crash.feedback=請不要將本界面截圖給他人! 如果你要求助他人,請你點擊左下角 導出遊戲崩潰信息 後將導出的文件發送給他人以供分析。\n你可以點擊下方的 幫助 前往社區尋求幫助。 From c157d4e0d1fdd10f4a1f7b4970057102c58bf330 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 19 Oct 2024 21:48:30 +0800 Subject: [PATCH 041/169] Revise zh_TW part 4 (#3359) --- .../resources/assets/lang/I18N_zh.properties | 297 +++++++++--------- 1 file changed, 151 insertions(+), 146 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index db6718b50d..5687f8b5cd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -720,7 +720,7 @@ modpack.wizard.step.initialization.exported_version=要匯出的遊戲版本 modpack.wizard.step.initialization.force_update=強制升級模組包至最新版本(需要自建伺服器) modpack.wizard.step.initialization.include_launcher=包含啟動器 modpack.wizard.step.initialization.save=選擇要匯出到的遊戲模組包位置 -modpack.wizard.step.initialization.warning=在製作模組包前,請您確認您選擇的版本可以正常啟動,\n並保證您的 Minecraft 是正式版而非快照版,\n而且不應將不允許非官方途徑傳播的 Mod 模組、材質包等納入模組包。\n模組包會儲存您目前的下載來源設定 +modpack.wizard.step.initialization.warning=在製作模組包前,請您確認您選擇的版本可以正常啟動,\n並保證您的 Minecraft 是正式版而非快照,\n而且不應將不允許非官方途徑傳播的 Mod 模組、材質包等納入模組包。\n模組包會儲存您目前的下載來源設定 modpack.wizard.step.initialization.server=點選此處查看有關伺服器自動更新模組包的製作教學 modrinth.category.adventure=冒險 @@ -786,31 +786,31 @@ modrinth.category.folia=Folia mods=模組 mods.add=新增模組 -mods.add.failed=新增模組 %s 失敗。 -mods.add.success=成功新增模組 %s。 -mods.broken_dependency.title=損壞的前置模組 -mods.broken_dependency.desc=該前置模組曾經在該模組倉庫上存在過,但現在被刪除了,換個下載源試試吧。 +mods.add.failed=新增模組「%s」失敗。 +mods.add.success=成功新增模組「%s」。 +mods.broken_dependency.title=損壞的相依模組 +mods.broken_dependency.desc=該相依模組曾經在該平臺上存在過,但現在被刪除了,換個下載源試試吧。 mods.category=類別 mods.channel.alpha=Alpha mods.channel.beta=Beta mods.channel.release=Release mods.check_updates=檢查模組更新 -mods.check_updates.current_version=當前版本 +mods.check_updates.current_version=目前版本 mods.check_updates.empty=沒有需要更新的模組 mods.check_updates.failed=部分檔案下載失敗 mods.check_updates.file=檔案 mods.check_updates.source=來源 mods.check_updates.target_version=目標版本 mods.check_updates.update=更新 -mods.choose_mod=選擇模組 +mods.choose_mod=選取模組 mods.curseforge=CurseForge -mods.dependency.embedded=內置前端模組(作者已經打包在模組檔中,無需額外下載) -mods.dependency.optional=可選的前模組(如果缺少遊戲,遊戲可以運行,但模組功能可能缺失) -mods.dependency.required=必需的預模式(必須單獨下載,缺少可能會導致遊戲無法啟動) -mods.dependency.tool=前端庫(必須單獨下載,缺少可能會導致遊戲無法啟動) -mods.dependency.include=內置前綴模組(作者已經打包在模組檔中,無需額外下載) -mods.dependency.incompatible=模組不相容(同時安裝模組和模組都下載會導致遊戲無法啟動) -mods.dependency.broken=損壞的前綴(這個前綴曾經存在於 mod 倉庫中,但現在已被刪除)。嘗試其他下載源。 +mods.dependency.embedded=內建相依模組 (作者已經打包在模組檔中,無需單獨下載) +mods.dependency.optional=可選相依模組 (如果不安裝,遊戲可以執行,但模組功能可能缺失) +mods.dependency.required=必需相依模組 (必須單獨下載,缺少可能會導致遊戲無法啟動) +mods.dependency.tool=相依庫 (必須單獨下載,缺少可能會導致遊戲無法啟動) +mods.dependency.include=內建相依模組 (作者已經打包在模組檔中,無需單獨下載) +mods.dependency.incompatible=不相容模組 (同時安裝此模組和正在下載的模組會導致遊戲無法啟動) +mods.dependency.broken=損壞的相依模組 (這個模組曾經存在於平臺中,但現在已被刪除,請嘗試其他下載源) mods.disable=停用 mods.download=模組下載 mods.download.title=模組下載 - %1s @@ -820,26 +820,26 @@ mods.manage=模組管理 mods.mcbbs=MCBBS mods.mcmod=MC 百科 mods.mcmod.page=MC 百科頁面 -mods.mcmod.search=MC 百科蒐索 +mods.mcmod.search=MC 百科檢索 mods.modrinth=Modrinth mods.name=名稱 -mods.not_modded=你需要先在自動安裝頁面安裝 Fabric、Forge、Quilt 或 LiteLoader 才能進行模組管理。 +mods.not_modded=你需要先在「自動安裝」頁面安裝 Forge、NeoForge、Fabric、Quilt 或 LiteLoader 才能管理模組。 mods.restore=回退 mods.url=官方頁面 -mods.update_modpack_mod.warning=更新模組包中的 Mod 可能導致綜合包損壞,使模組包無法正常啟動。該操作不可逆,確定要更新嗎? -mods.install=安裝到當前實例 -mods.save_as=下載到本地目錄 +mods.update_modpack_mod.warning=更新模組包中的模組可能導致模組包損壞,使模組包無法正常啟動。該操作不可逆,確定要更新嗎? +mods.install=安裝到目前實例 +mods.save_as=下載到本機目錄 nbt.entries=%s 個條目 nbt.open.failed=打開檔案失敗 -nbt.save.failed=保存檔案失敗 +nbt.save.failed=儲存檔案失敗 nbt.title=查看檔案 - %s datapack=資料包 datapack.add=加入資料包 -datapack.choose_datapack=選擇要匯入的資料包壓縮檔 +datapack.choose_datapack=選取要匯入的資料包壓縮檔 datapack.extension=資料包 -datapack.title=世界 %s - 資料包 +datapack.title=世界 [%s] - 資料包 web.failed=加載頁面失敗 web.open_in_browser=是否要在瀏覽器中打開此連結:\n%s @@ -849,23 +849,23 @@ world=世界 world.add=加入世界 world.datapack=管理資料包 world.datapack.1_13=僅 Minecraft 1.13 及之後的版本支援資料包 -world.description=%s. 上一次遊戲時間: %s. 遊戲版本: %s +world.description=%s | 上一次遊戲時間: %s | 遊戲版本: %s world.download=存檔下載 world.export=匯出此世界 -world.export.title=選擇該世界的儲存位置 +world.export.title=選取該世界的儲存位置 world.export.location=儲存到 -world.export.wizard=匯出世界 %s +world.export.wizard=匯出世界「%s」 world.extension=存檔壓縮檔 world.import.already_exists=此世界已經存在 -world.import.choose=選擇要匯入的存檔壓縮檔 +world.import.choose=選取要匯入的存檔壓縮檔 world.import.failed=無法匯入此世界: %s -world.import.invalid=無法識別的存檔壓縮包 -world.info.title=世界 %s - 世界資訊 +world.import.invalid=無法識別的存檔壓縮檔 +world.info.title=世界 [%s] - 世界資訊 world.info.basic=基本資訊 -world.info.allow_cheats=允許作弊 -world.info.dimension.the_nether=下界 +world.info.allow_cheats=允許指令 +world.info.dimension.the_nether=地獄 world.info.dimension.the_end=末地 -world.info.difficulty=難度 +world.info.difficulty=難易度 world.info.difficulty.peaceful=和平 world.info.difficulty.easy=簡單 world.info.difficulty.normal=普通 @@ -878,42 +878,42 @@ world.info.player.food_level=饑餓值 world.info.player.game_type=遊戲模式 world.info.player.game_type.adventure=冒險 world.info.player.game_type.creative=創造 -world.info.player.game_type.spectator=旁觀 +world.info.player.game_type.spectator=旁觀者 world.info.player.game_type.survival=生存 world.info.player.health=生命值 world.info.player.last_death_location=上次死亡位置 world.info.player.location=位置 world.info.player.spawn=床/重生錨位置 world.info.player.xp_level=經驗等級 -world.info.random_seed=種子 +world.info.random_seed=種子碼 world.info.time=遊戲內時間 world.info.time.format=%s 天 world.game_version=遊戲版本 world.manage=世界/資料包 world.name=世界名稱 world.name.enter=輸入世界名稱 -world.reveal=開啟資料夾 +world.reveal=開啟目錄 world.show_all=全部顯示 -world.time=yyyy年MM月dd日 HH:mm:ss +world.time=yyyy/M/d HH:mm:ss profile=遊戲目錄 profile.already_exists=該名稱已存在 profile.default=目前目錄 profile.home=官方啟動器目錄 -profile.instance_directory=遊戲路徑 -profile.instance_directory.choose=選擇遊戲路徑 -profile.manage=遊戲目錄列表 +profile.instance_directory=遊戲目錄路徑 +profile.instance_directory.choose=選取遊戲目錄路徑 +profile.manage=遊戲目錄清單 profile.name=名稱 -profile.new=建立設定 +profile.new=建立新目錄 profile.title=遊戲目錄 profile.selected=已選取 -profile.use_relative_path=如可行,則在遊戲目錄使用相對路徑 +profile.use_relative_path=如可行,則對於遊戲目錄使用相對路徑 -repositories.custom=自定義 Maven 倉庫(%s) -repositories.maven_central=全球(Maven Central) -repositories.tencentcloud_mirror=中國大陸(騰訊雲 Maven 倉庫) -repositories.chooser=缺少 JavaFX 運行環境,HMCL 需要 JavaFX 才能正常運行。\n點擊“確認”從指定下載源下載 JavaFX 運行時組件並啟動 HMCL,點擊“取消”退出程式。\n選擇下載源: -repositories.chooser.title=選擇下載源下載JavaFX +repositories.custom=自訂 Maven 倉庫 (%s) +repositories.maven_central=全球 (Maven Central) +repositories.tencentcloud_mirror=中國大陸 (騰訊雲 Maven 倉庫) +repositories.chooser=缺少 JavaFX 執行環境,HMCL 需要 JavaFX 才能正常執行。\n點擊「確認」從指定下載源下載 JavaFX 執行時元件並啟動 HMCL,點擊「取消」退出程式。\n選取下載源: +repositories.chooser.title=選取 JavaFX 下載源 resourcepack=資源包 @@ -928,41 +928,41 @@ search.next_page=下一頁 search.last_page=最後一頁 search.page_n=%d / %s -selector.choose=選擇 -selector.choose_file=選擇檔案 +selector.choose=選取 +selector.choose_file=選取檔案 selector.custom=自訂 -settings=遊戲設定 +settings=設定 settings.advanced=進階設定 -settings.advanced.modify=修改進階設定 +settings.advanced.modify=編輯進階設定 settings.advanced.title=進階設定 - %s -settings.advanced.custom_commands=自訂命令 -settings.advanced.custom_commands.hint=自訂命令被調用時將包含如下的環境變數:\n\ - \ - $INST_NAME: 版本名稱\n\ - \ - $INST_ID: 版本名稱\n\ - \ - $INST_DIR: 版本資料夾\n\ - \ - $INST_MC_DIR: 遊戲運行路徑\n\ - \ - $INST_JAVA: 遊戲運行使用的 Java 路徑\n\ - \ - $INST_FORGE: 若安裝了 Forge,將會存在本環境變數\n\ - \ - $INST_NEOFORGE: 若安裝了 NeoForge,將會存在本環境變數\n\ - \ - $INST_LITELOADER: 若安裝了 LiteLoader,將會存在本環境變數\n\ - \ - $INST_OPTIFINE: 若安裝了 OptiFine,將會存在本環境變數\n\ - \ - $INST_FABRIC: 若安裝了 Fabric,將會存在本環境變數\n\ - \ - $INST_QUILT: 若安裝了 Quilt,將會存在本環境變數 +settings.advanced.custom_commands=自訂指令 +settings.advanced.custom_commands.hint=自訂指令被呼叫時將包含如下的環境變數:\n\ + \ · $INST_NAME: 實例名稱;\n\ + \ · $INST_ID: 實例名稱;\n\ + \ · $INST_DIR: 目前實例執行路徑;\n\ + \ · $INST_MC_DIR: 目前遊戲目錄路徑;\n\ + \ · $INST_JAVA: 遊戲執行使用的 Java 路徑;\n\ + \ · $INST_FORGE: 若安裝了 Forge,將會存在本環境變數;\n\ + \ · $INST_NEOFORGE: 若安裝了 NeoForge,將會存在本環境變數;\n\ + \ · $INST_LITELOADER: 若安裝了 LiteLoader,將會存在本環境變數;\n\ + \ · $INST_OPTIFINE: 若安裝了 OptiFine,將會存在本環境變數;\n\ + \ · $INST_FABRIC: 若安裝了 Fabric,將會存在本環境變數;\n\ + \ · $INST_QUILT: 若安裝了 Quilt,將會存在本環境變數。 settings.advanced.dont_check_game_completeness=不檢查遊戲完整性 settings.advanced.dont_check_jvm_validity=不檢查 JVM 與遊戲的相容性 -settings.advanced.dont_patch_natives=不嘗試自動替換本機庫 +settings.advanced.dont_patch_natives=不嘗試自動取代本機庫 settings.advanced.environment_variables=環境變數 -settings.advanced.game_dir.default=預設(.minecraft/) -settings.advanced.game_dir.independent=各版本獨立(.minecraft/versions/<版本名>/,除 assets、libraries) +settings.advanced.game_dir.default=預設 (".minecraft/") +settings.advanced.game_dir.independent=各實例獨立 (".minecraft/versions/<實例名>/",除 assets、libraries 外) settings.advanced.java_permanent_generation_space=記憶體永久儲存區域 -settings.advanced.java_permanent_generation_space.prompt=格式: MB +settings.advanced.java_permanent_generation_space.prompt=單位 MB settings.advanced.jvm=Java 虛擬機設定 settings.advanced.jvm_args=Java 虛擬機參數 -settings.advanced.jvm_args.prompt=- 若在“Java 虛擬機參數”中輸入的參數與默認參數相同,則不會添加\n\ -- 在“Java 虛擬機參數”輸入任何 GC 參數,默認參數的 G1 參數會禁用\n\ -- 點擊下方“不添加默認的 JVM 參數”可在啟動遊戲時不添加默認參數 +settings.advanced.jvm_args.prompt=\ · 若在「Java 虛擬機參數」中輸入的參數與預設參數相同,則不會加入;\n\ + \ · 在「Java 虛擬機參數」輸入任何 GC 參數,預設參數的 G1 參數會禁用;\n\ + \ · 點擊下方「不使用預設的 JVM 參數」可在啟動遊戲時不加入預設參數。 settings.advanced.launcher_visibility.close=遊戲啟動後結束啟動器 settings.advanced.launcher_visibility.hide=遊戲啟動後隱藏啟動器 settings.advanced.launcher_visibility.hide_and_reopen=隱藏啟動器並在遊戲結束後重新開啟 @@ -970,27 +970,27 @@ settings.advanced.launcher_visibility.keep=不隱藏啟動器 settings.advanced.launcher_visible=啟動器可見性 settings.advanced.minecraft_arguments=Minecraft 額外參數 settings.advanced.minecraft_arguments.prompt=預設 -settings.advanced.natives_directory=本地庫路徑(LWJGL) -settings.advanced.natives_directory.choose=選擇本地庫路徑 -settings.advanced.natives_directory.custom=自訂(由你提供遊戲需要的本地庫) -settings.advanced.natives_directory.default=預設(由啟動器提供遊戲本地庫) -settings.advanced.natives_directory.hint=本選項提供給 Apple M1 等未受遊戲官方支持的平台來自訂遊戲本地庫,如果你不知道本選項的含義,請你不要修改本選項,否則會導致遊戲無法啟動。\n如果你要修改本選項,你需要保證自訂目錄下有遊戲所需的本地庫文件,如 lwjgl.dll(liblwjgl.so), openal.dll(libopenal.so) 等文件。啟動器不會幫你補全缺少的本地庫文件。\n注意:建議指定的本地庫文件路徑使用全英文字符,否則可能導致遊戲啟動失敗。 +settings.advanced.natives_directory=本機庫路徑 (LWJGL) +settings.advanced.natives_directory.choose=選取本機庫路徑 +settings.advanced.natives_directory.custom=自訂 (由你提供遊戲需要的本機庫) +settings.advanced.natives_directory.default=預設 (由啟動器提供遊戲本機庫) +settings.advanced.natives_directory.hint=本選項提供給 Apple M1 等未受遊戲官方支援的平台來自訂遊戲本機庫,如果你不知道本選項的含義,請你不要修改本選項,否則會導致遊戲無法啟動。\n如果你要修改本選項,你需要保證自訂目錄下有遊戲所需的本機庫檔案,如 lwjgl.dll (liblwjgl.so), openal.dll (libopenal.so) 等檔案。啟動器不會幫你補全缺少的本機庫檔案。\n注意:建議指定的本機庫檔案路徑使用全英文字元,否則可能導致遊戲啟動失敗。 settings.advanced.no_jvm_args=不使用預設的 JVM 參數 settings.advanced.precall_command=遊戲啟動前執行指令 settings.advanced.precall_command.prompt=將在遊戲啟動前呼叫使用 -settings.advanced.process_priority=進程優先度 -settings.advanced.process_priority.low=低(節省遊戲占用資源,可能會造成遊戲卡頓) -settings.advanced.process_priority.below_normal=較低(節省遊戲占用資源,可能會造成遊戲卡頓) -settings.advanced.process_priority.normal=中(平衡) -settings.advanced.process_priority.above_normal=較高(優先保證遊戲運行,但可能會導致其他程式卡頓) -settings.advanced.process_priority.high=高(優先保證遊戲運行,但可能會導致其他程式卡頓) -settings.advanced.post_exit_command=遊戲結束後執行命令 +settings.advanced.process_priority=處理程序優先度 +settings.advanced.process_priority.low=低 (節省遊戲占用資源,可能會造成遊戲卡頓) +settings.advanced.process_priority.below_normal=較低 (節省遊戲占用資源,可能會造成遊戲卡頓) +settings.advanced.process_priority.normal=中 (平衡) +settings.advanced.process_priority.above_normal=較高 (優先保證遊戲執行,但可能會導致其他程式卡頓) +settings.advanced.process_priority.high=高 (優先保證遊戲執行,但可能會導致其他程式卡頓) +settings.advanced.post_exit_command=遊戲結束後執行指令 settings.advanced.post_exit_command.prompt=將在遊戲結束後呼叫使用 -settings.advanced.renderer=渲染器 -settings.advanced.renderer.default=OpenGL(默認) -settings.advanced.renderer.d3d12=DirectX 12(效能與相容性較差,用於調試) -settings.advanced.renderer.llvmpipe=軟渲染器(效能較差,相容性最好) -settings.advanced.renderer.zink=Vulkan(效能最好,相容性較差) +settings.advanced.renderer=繪製器 +settings.advanced.renderer.default=OpenGL (預設) +settings.advanced.renderer.d3d12=DirectX 12 (效能與相容性較差,用於除錯) +settings.advanced.renderer.llvmpipe=軟繪製器 (效能較差,相容性最好) +settings.advanced.renderer.zink=Vulkan (效能最好,相容性較差) settings.advanced.server_ip=伺服器位址 settings.advanced.server_ip.prompt=預設,啟動遊戲後直接進入對應伺服器 settings.advanced.use_native_glfw=使用系統 GLFW @@ -998,7 +998,7 @@ settings.advanced.use_native_openal=使用系統 OpenAL settings.advanced.workaround=除錯選項 settings.advanced.workaround.warning=除錯選項僅提供給專業玩家使用。修改除錯選項可能會導致遊戲無法啟動。除非你知道你在做什麼,否則請不要修改這些選項。 settings.advanced.wrapper_launcher=前置指令 -settings.advanced.wrapper_launcher.prompt=如填寫 optirun 後,啟動命令將從 "java ..." 變為 "optirun java ..." +settings.advanced.wrapper_launcher.prompt=如填寫「optirun」後,啟動指令將從「java ...」變為「optirun java ...」 settings.custom=自訂 @@ -1007,45 +1007,45 @@ settings.game.current=遊戲 settings.game.dimension=遊戲介面解析度大小 settings.game.exploration=瀏覽 settings.game.fullscreen=全螢幕 -settings.game.java_directory=Java 路徑 -settings.game.java_directory.auto=自動選擇合適的 Java +settings.game.java_directory=遊戲 Java +settings.game.java_directory.auto=自動選取合適的 Java settings.game.java_directory.auto.not_found=沒有合適的 Java settings.game.java_directory.bit=%s 位 -settings.game.java_directory.choose=選擇 Java 路徑 +settings.game.java_directory.choose=選取 Java settings.game.java_directory.invalid=Java 路徑不正確 settings.game.java_directory.version=指定 Java 版本 -settings.game.java_directory.template=%s(%s) +settings.game.java_directory.template=%s (%s) settings.game.management=管理 -settings.game.working_directory=執行路徑(版本隔離,修改後請自行移動相關遊戲檔案,如存檔模組設定等) -settings.game.working_directory.choose=選擇執行路徑 -settings.game.working_directory.hint=在“運行路徑(版本隔離)”選項中開啟“各版本獨立”使當前版本獨立存放設定、存檔、模組等數據,使用模組時建議開啟此選項以避免不同版本模組衝突。修改此選項後請自行移動存檔等檔案。 +settings.game.working_directory=執行路徑 (修改後請自行移動相關遊戲檔案,如存檔、模組設定等) +settings.game.working_directory.choose=選取執行目錄 +settings.game.working_directory.hint=在「執行路徑」選項中選取「各實例獨立」使目前實例獨立存放設定、存檔、模組等資料,使用模組時建議開啟此選項以避免不同版本模組衝突。修改此選項後需自行移動存檔等檔案。 settings.icon=遊戲圖示 settings.launcher=啟動器設定 settings.launcher.appearance=外觀 -settings.launcher.common_path.tooltip=啟動器將所有遊戲資源及相依元件庫檔案放於此集中管理,如果遊戲資料夾內有現成的將不會使用公共庫檔案 +settings.launcher.common_path.tooltip=啟動器將所有遊戲資源及相依元件庫檔案放於此集中管理,如果遊戲目錄內有現成的將不會使用公共庫檔案。 settings.launcher.debug=除錯 settings.launcher.download=下載 -settings.launcher.download.threads=並發數 -settings.launcher.download.threads.auto=自動選擇並發數 -settings.launcher.download.threads.hint=並發數過大可能導致系統卡頓。你的下載速度會受到寬頻運營商、伺服器等方面的影響,調大下載並發數不一定能大幅提升總下載速度。 +settings.launcher.download.threads=執行緒數 +settings.launcher.download.threads.auto=自動選取執行緒數 +settings.launcher.download.threads.hint=執行緒數過高可能導致系統卡頓。你的下載速度會受到網際網路運營商、下載來源伺服器等方面的影響,調高下載執行緒數不一定能大幅提升總下載速度。 settings.launcher.download_source=下載來源 -settings.launcher.download_source.auto=自動選擇下載來源 -settings.launcher.enable_game_list=在首頁內顯示遊戲列表 +settings.launcher.download_source.auto=自動選取下載來源 +settings.launcher.enable_game_list=在首頁內顯示遊戲清單 settings.launcher.font=字體 -settings.launcher.general=通用 +settings.launcher.general=一般 settings.launcher.language=語言 (重啟後生效) settings.launcher.launcher_log.export=匯出啟動器日誌 settings.launcher.launcher_log.reveal=打開日誌目錄 -settings.launcher.launcher_log.export.failed=無法匯出日誌 -settings.launcher.launcher_log.export.success=日誌已儲存到 %s -settings.launcher.log=記錄 -settings.launcher.log.font=記錄字體 +settings.launcher.launcher_log.export.failed=無法匯出日誌。 +settings.launcher.launcher_log.export.success=日誌已儲存到「%s」。 +settings.launcher.log=日誌 +settings.launcher.log.font=日誌字體 settings.launcher.proxy=代理 settings.launcher.proxy.authentication=身份驗證 settings.launcher.proxy.disable=使用系統代理 -settings.launcher.proxy.host=主機 +settings.launcher.proxy.host=IP 位址 settings.launcher.proxy.http=HTTP settings.launcher.proxy.none=不使用代理 settings.launcher.proxy.password=密碼 @@ -1055,7 +1055,7 @@ settings.launcher.proxy.username=帳戶 settings.launcher.theme=主題 settings.launcher.title_transparent=標題欄透明 settings.launcher.turn_off_animations=關閉動畫 (重啟後生效) -settings.launcher.version_list_source=版本列表來源 +settings.launcher.version_list_source=版本清單來源 settings.memory=遊戲記憶體 settings.memory.allocate.auto=最低分配 %1$.1f GB / 實際分配 %2$.1f GB @@ -1066,91 +1066,96 @@ settings.memory.auto_allocate=自動分配 settings.memory.lower_bound=最低分配 settings.memory.used_per_total=已使用 %1$.1f GB / 總記憶體 %2$.1f GB settings.physical_memory=實體記憶體大小 -settings.show_log=查看記錄 -settings.skin=現已支持離線帳戶更換皮膚,你可以到帳戶頁面更改離線帳戶的皮膚和披風(多人遊戲下其他玩家無法看到你的皮膚) +settings.show_log=查看日誌 +settings.skin=現已支援離線帳戶更換外觀,你可以到帳戶頁面更改離線帳戶的外觀和披風 (多人遊戲下其他玩家無法看到你的外觀)。 settings.tabs.installers=自動安裝 settings.take_effect_after_restart=重啟後生效 -settings.type=版本設定類型 -settings.type.global=全域版本設定(使用該設定的版本共用一套設定) +settings.type=實例遊戲設定類型 +settings.type.global=全域遊戲設定 (未啟用「實例特定遊戲設定」的實例共用一套設定) settings.type.global.manage=全域遊戲設定 settings.type.global.edit=編輯全域遊戲設定 -settings.type.special.enable=啟用遊戲特別設定(不影響其他遊戲版本) -settings.type.special.edit=編輯遊戲特定設置 -settings.type.special.edit.hint=當前遊戲版本 %s 啟動了遊戲特定設置,本頁面選項不對當前遊戲生效。點擊連結以修改當前遊戲設置。 +settings.type.special.enable=啟用實例特定遊戲設定 (不影響其他實例) +settings.type.special.edit=編輯實例特定遊戲設定 +settings.type.special.edit.hint=目前實例「%s」啟用了「實例特定遊戲設定」設定,本頁面選項不對目前實例生效。點擊連結以修改目前實例設定。 sponsor=贊助 -sponsor.bmclapi=大中華區下載源由 BMCLAPI 提供高速下載服務 -sponsor.hmcl=Hello Minecraft! Launcher 是一個免費、開源的 Minecraft 啟動器,允許玩家方便快捷地安裝、管理、執行遊戲。點選此處查閱更多詳細訊息。 +sponsor.bmclapi=中國大陸下載源由 BMCLAPI 提供高速下載服務。 +sponsor.hmcl=Hello Minecraft! Launcher 是一個自由、開源的 Minecraft 啟動器,允許玩家方便快捷地安裝、管理、執行遊戲。點選此處查閱更多詳細訊息。 system.architecture=架構 -system.operating_system=操作系統 +system.operating_system=作業系統 -unofficial.hint=你正在使用非官方構建的 HMCL,我們無法保證其安全性,請注意甄別。 +unofficial.hint=你正在使用第三方提供的 HMCL,我們無法保證其安全性,請注意甄別。 update=啟動器更新 update.accept=更新 update.changelog=更新日誌 update.channel.dev=測試版 -update.channel.dev.hint=你正在使用測試版。測試版包含一些未在正式版中包含的測試性功能,僅用於體驗新功能。\n\ - 測試版功能未受充分驗證,使用起來可能不穩定!\n\ - 如果你遇到了使用問題,可以在設置的 回饋頁面 中進行回饋,或加入回饋頁面中提供的 DiscordQQ 群以回饋問題。\n\n\ - 點擊此處為當前版本隱藏該提示。 +update.channel.dev.hint=你正在使用 HMCL 測試版。測試版包含一些未在正式版中包含的測試性功能,僅用於體驗新功能。測試版功能未受充分驗證,使用起來可能不穩定!\n\ + \n\ + 如果你遇到了使用問題,可以透過「設定 → 回報」頁面或下方提供的管道進行回報。\n\ + \n\ + Discord QQ 群 GitHub\n\ + \n\ + 為目前版本隱藏該提示。 update.channel.dev.title=測試版提示 update.channel.nightly=預覽版 -update.channel.nightly.hint=你正在使用預覽版。預覽版可能會每天更新一次,包含一些未在正式版和測試版中包含的測試性功能,僅用於體驗新功能\n\ - 測試版功能未受充分驗證,使用起來可能不穩定!\n\ - 如果你遇到了使用問題,可以在設置的 回饋頁面 中進行回饋,或加入 DiscordQQ 群以回饋問題。 +update.channel.nightly.hint=你正在使用 HMCL 預覽版。預覽版更新較為頻繁,包含一些未在正式版和測試版中包含的測試性功能,僅用於體驗新功能。預覽版功能未受充分驗證,使用起來可能不穩定!\n\ + \n\ + 如果你遇到了使用問題,可以透過「設定 → 回報」頁面或下方提供的管道進行回報。\n\ + \n\ + Discord QQ 群 GitHub update.channel.nightly.title=預覽版提示 update.channel.stable=建議版本 update.checking=正在檢查更新 update.failed=更新失敗 update.found=發現到更新 -update.newest_version=最新版本為: %s -update.bubble.title=發現更新: %s +update.newest_version=最新版本為:%s +update.bubble.title=發現更新:%s update.bubble.subtitle=點選此處進行升級 -update.note=測試版與開發版包含更多的功能以及錯誤修復,但也可能會包含其他的問題。 +update.note=測試版與預覽版包含更多的功能以及錯誤修復,但也可能會包含其他的問題。 update.latest=目前版本為最新版本 -update.no_browser=無法開啟瀏覽器,網址已經複製到剪貼簿了,您可以手動複製網址開啟頁面 +update.no_browser=無法開啟瀏覽器,網址已經複製到剪貼簿了,你可以手動複製網址開啟頁面。 update.tooltip=更新 version=遊戲 -version.name=遊戲版本名稱 +version.name=遊戲實例名稱 version.cannot_read=讀取遊戲版本失敗,無法進行自動安裝 version.empty=沒有遊戲版本 version.empty.add=進入下載頁安裝遊戲 version.empty.launch=沒有可啟動的遊戲,你可以點擊左側邊欄內的下載按鈕安裝遊戲 version.empty.hint=沒有已安裝的遊戲,你可以切換其他遊戲目錄,或者點擊此處進入遊戲下載頁面 -version.game.old=老舊版本 -version.game.release=穩定版本 -version.game.releases=穩定版本 -version.game.snapshot=測試版本 -version.game.snapshots=測試版本 +version.game.old=歷史版本 +version.game.release=正式版 +version.game.releases=正式版 +version.game.snapshot=快照 +version.game.snapshots=快照 version.launch=啟動遊戲 version.launch.test=測試遊戲 -version.switch=切換版本 +version.switch=切換實例 version.launch_script=生成啟動指令碼 version.launch_script.failed=生成啟動指令碼失敗 version.launch_script.save=儲存啟動指令碼 version.launch_script.success=啟動指令碼已生成完畢: %s -version.manage=遊戲列表 +version.manage=實例清單 version.manage.clean=清理遊戲目錄 -version.manage.clean.tooltip=清理 logs, crash-reports +version.manage.clean.tooltip=清理「logs」與「crash-reports」目錄 version.manage.duplicate=複製遊戲實例 version.manage.duplicate.duplicate_save=複製存檔 version.manage.duplicate.prompt=請輸入新遊戲實例名稱 -version.manage.duplicate.confirm=將鎖定複製產生的新遊戲實例:強制版本隔離、遊戲設置獨立。 -version.manage.manage=遊戲管理 -version.manage.manage.title=遊戲管理 - %1s +version.manage.duplicate.confirm=新的遊戲將複製該實例目錄 (".minecraft/versions/<實例名>") 下的檔案,並帶有獨立的執行目錄和設定。 +version.manage.manage=實例設定 +version.manage.manage.title=實例設定 - %1s version.manage.redownload_assets_index=更新遊戲資源檔案 version.manage.remove=刪除該版本 -version.manage.remove.confirm=真的要刪除版本 %s 嗎? 你將無法找回被刪除的檔案! -version.manage.remove.confirm.trash=真的要刪除版本 %s 嗎? 你可以在系統的資源回收桶 (或垃圾桶) 中還原資料夾 %s 來找回該版本。 -version.manage.remove.confirm.independent=由於該遊戲使用了版本隔離,所以刪除該版本將導致該遊戲的存檔等資料一同被刪除,真的要刪除版本 %s 嗎? +version.manage.remove.confirm=真的要刪除實例「%s」嗎? 你將無法找回被刪除的檔案!!! +version.manage.remove.confirm.trash=真的要刪除實例「%s」嗎? 你可以在系統的資源回收筒 (或垃圾桶) 中還原目錄「%s」來找回該實例。 +version.manage.remove.confirm.independent=由於該實例啟用了「(全域/實例特定) 遊戲設定 → 執行路徑 → 各實例獨立」設定,所以刪除該實例將導致該遊戲的存檔等資料一同被刪除,真的要刪除實例「%s」嗎? version.manage.remove_assets=刪除所有遊戲資源檔案 -version.manage.remove_libraries=刪除所有函式庫檔案 +version.manage.remove_libraries=刪除所有支援庫檔案 version.manage.rename=重新命名該版本 version.manage.rename.message=請輸入新名稱 -version.manage.rename.fail=重新命名版本失敗,可能檔案被佔用或者名稱有特殊字元 +version.manage.rename.fail=重新命名版本失敗,可能檔案被佔用或者名稱有特殊字元。 version.settings=遊戲設定 version.update=更新模組包 From 5c767deaf3b581540a265e194f996dd714ebe218 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 19 Oct 2024 22:25:47 +0800 Subject: [PATCH 042/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20WorldInfoPage=20(#?= =?UTF-8?q?3361)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update * update --- .../hmcl/ui/versions/WorldInfoPage.java | 51 +++++++++++++++---- .../hmcl/ui/versions/WorldListItem.java | 6 +-- .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldInfoPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldInfoPage.java index d7ab4e1863..a8d7e2c5bd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldInfoPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldInfoPage.java @@ -1,3 +1,20 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2024 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package org.jackhuang.hmcl.ui.versions; import com.github.steveice10.opennbt.tag.builtin.*; @@ -10,11 +27,14 @@ import javafx.collections.ObservableList; import javafx.geometry.Pos; import javafx.scene.control.Label; +import javafx.scene.control.ProgressIndicator; import javafx.scene.control.ScrollPane; import javafx.scene.layout.BorderPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.jackhuang.hmcl.game.World; +import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.construct.ComponentList; import org.jackhuang.hmcl.ui.construct.DoubleValidator; @@ -32,22 +52,36 @@ import static org.jackhuang.hmcl.util.i18n.I18n.formatDateTime; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; +/** + * @author Glavo + */ public final class WorldInfoPage extends StackPane implements DecoratorPage { private final World world; - private final CompoundTag levelDat; - private final CompoundTag dataTag; + private CompoundTag levelDat; - private final ObjectProperty stateProperty = new SimpleObjectProperty<>(); + private final ObjectProperty stateProperty; - public WorldInfoPage(World world) throws IOException { + public WorldInfoPage(World world) { this.world = world; - this.levelDat = world.readLevelDat(); - this.dataTag = levelDat.get("Data"); + this.stateProperty = new SimpleObjectProperty<>(State.fromTitle(i18n("world.info.title", world.getWorldName()))); + + this.getChildren().add(new ProgressIndicator()); + Task.supplyAsync(world::readLevelDat) + .whenComplete(Schedulers.javafx(), ((result, exception) -> { + if (exception == null) { + this.levelDat = result; + loadWorldInfo(); + } else { + LOG.warning("Failed to load level.dat", exception); + this.getChildren().setAll(new Label(i18n("world.info.failed"))); + } + })).start(); + } + private void loadWorldInfo() { + CompoundTag dataTag = levelDat.get("Data"); CompoundTag worldGenSettings = dataTag.get("WorldGenSettings"); - stateProperty.set(State.fromTitle(i18n("world.info.title", world.getWorldName()))); - ScrollPane scrollPane = new ScrollPane(); scrollPane.setFitToHeight(true); scrollPane.setFitToWidth(true); @@ -483,7 +517,6 @@ String formatPosition(Tag tag) { Tag z = listTag.get(2); if (x instanceof DoubleTag && y instanceof DoubleTag && z instanceof DoubleTag) { - //noinspection MalformedFormatString return this == OVERWORLD ? String.format("(%.2f, %.2f, %.2f)", x.getValue(), y.getValue(), z.getValue()) : String.format("%s (%.2f, %.2f, %.2f)", name, x.getValue(), y.getValue(), z.getValue()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java index 5f98c22554..933bb0887e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java @@ -102,10 +102,6 @@ public void manageDatapacks() { } public void showInfo() { - try { - Controllers.navigate(new WorldInfoPage(world)); - } catch (Exception e) { - // TODO - } + Controllers.navigate(new WorldInfoPage(world)); } } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 90fd793e5c..82fc17d1c5 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1010,6 +1010,7 @@ world.info.difficulty.peaceful=Peaceful world.info.difficulty.easy=Easy world.info.difficulty.normal=Normal world.info.difficulty.hard=Hard +world.info.failed=Failed to read the world info world.info.game_version=Game Version world.info.last_played=Last Played world.info.generate_features=Generate Structures diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 5687f8b5cd..fe57454e06 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -870,6 +870,7 @@ world.info.difficulty.peaceful=和平 world.info.difficulty.easy=簡單 world.info.difficulty.normal=普通 world.info.difficulty.hard=困難 +world.info.failed=讀取世界資訊失敗 world.info.game_version=遊戲版本 world.info.last_played=上一次遊戲時間 world.info.generate_features=生成建築 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 c378a1c7bd..184a894720 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -874,6 +874,7 @@ world.info.difficulty.peaceful=和平 world.info.difficulty.easy=简单 world.info.difficulty.normal=普通 world.info.difficulty.hard=困难 +world.info.failed=读取世界信息失败 world.info.game_version=游戏版本 world.info.last_played=上一次游戏时间 world.info.generate_features=生成建筑 From a27671560d9e7ab013dc76d4703952fa355eeaef Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 19 Oct 2024 22:59:40 +0800 Subject: [PATCH 043/169] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=B8=8B=E8=BD=BD=20?= =?UTF-8?q?OpenJ9=20(#3363)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 支持下载 OpenJ9 * update --- .../jackhuang/hmcl/ui/main/JavaDownloadDialog.java | 11 +++++++++-- .../download/java/disco/DiscoJavaDistribution.java | 9 ++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java index 7e4e80f66d..cb19775476 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java @@ -312,8 +312,15 @@ private void onDownload() { getIntegrityCheck = Task.completed(new FileDownloadTask.IntegrityCheck(fileInfo.getChecksumType(), fileInfo.getChecksum())); else if (StringUtils.isNotBlank(fileInfo.getChecksumUri())) getIntegrityCheck = new GetTask(downloadProvider.injectURLWithCandidates(fileInfo.getChecksumUri())) - .thenApplyAsync(checksum -> - new FileDownloadTask.IntegrityCheck(fileInfo.getChecksumType(), checksum.trim())); + .thenApplyAsync(checksum -> { + checksum = checksum.trim(); + + int idx = checksum.indexOf(' '); + if (idx > 0) + checksum = checksum.substring(0, idx); + + return new FileDownloadTask.IntegrityCheck(fileInfo.getChecksumType(), checksum); + }); else throw new IOException("Unable to get checksum for file"); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java index 7cc6c3e20a..52d013bf1c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java @@ -35,6 +35,7 @@ /** * @author Glavo + * @see discoapi */ public enum DiscoJavaDistribution implements JavaDistribution { TEMURIN("Eclipse Temurin", "temurin", "Adoptium", @@ -65,7 +66,13 @@ public boolean testVersion(DiscoJavaRemoteVersion version) { EnumSet.of(JDK), pair(WINDOWS, EnumSet.of(X86_64)), pair(LINUX, EnumSet.of(X86_64, ARM64)), - pair(OSX, EnumSet.of(X86_64, ARM64))); + pair(OSX, EnumSet.of(X86_64, ARM64))), + SEMERU("IBM Semeru (OpenJ9)", "semeru", "IBM", + EnumSet.of(JDK, JRE), + pair(WINDOWS, EnumSet.of(X86_64)), + pair(LINUX, EnumSet.of(X86_64, ARM64, PPC64LE, S390X)), + pair(OSX, EnumSet.of(X86_64, ARM64)) + ); public static DiscoJavaDistribution of(String name) { for (DiscoJavaDistribution distribution : values()) { From 1f9c0736aa2ea56969ce299e93abfee8ed945cc5 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sun, 20 Oct 2024 21:33:35 +0800 Subject: [PATCH 044/169] Capitalize choose player dialog title text (#3368) --- .../java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java index 9a17ba55cc..28d1df6d0d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java @@ -65,6 +65,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.concurrent.CountDownLatch; @@ -637,7 +638,7 @@ public DialogCharacterSelector() { StackPane.setAlignment(cancel, Pos.BOTTOM_RIGHT); cancel.setOnAction(e -> latch.countDown()); - listBox.startCategory(i18n("account.choose")); + listBox.startCategory(i18n("account.choose").toUpperCase(Locale.ROOT)); setCenter(listBox); From a5067cb1dd8e15e551a1ec5c40978ffaaffdae16 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 20 Oct 2024 21:33:55 +0800 Subject: [PATCH 045/169] Bump JavaFX to 17.0.13 (#3364) --- .../assets/openjfx-dependencies.json | 48 +++++++++---------- javafx.gradle.kts | 11 +++-- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/HMCL/src/main/resources/assets/openjfx-dependencies.json b/HMCL/src/main/resources/assets/openjfx-dependencies.json index 728d293332..cebc7ca4d6 100644 --- a/HMCL/src/main/resources/assets/openjfx-dependencies.json +++ b/HMCL/src/main/resources/assets/openjfx-dependencies.json @@ -30,25 +30,25 @@ "module": "javafx.base", "groupId": "org.openjfx", "artifactId": "javafx-base", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "win", - "sha1": "f33d0776b2b027c2ea9267c184f9048ef94c4deb" + "sha1": "ae86377359860449040372d3693bccf046148513" }, { "module": "javafx.graphics", "groupId": "org.openjfx", "artifactId": "javafx-graphics", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "win", - "sha1": "951ca77bd50ef4fd44f4b7fb1e38301088fde4e2" + "sha1": "bc0055a059b201d6c0be2293ccf72b6d2874fd1c" }, { "module": "javafx.controls", "groupId": "org.openjfx", "artifactId": "javafx-controls", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "win", - "sha1": "78ac7de48d0aac48e7d5282efc81bab7f337b587" + "sha1": "bcd765dca36fa9e5fb4c997491a2d908947603f5" } ], "windows-arm64": [ @@ -82,25 +82,25 @@ "module": "javafx.base", "groupId": "org.openjfx", "artifactId": "javafx-base", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "mac", - "sha1": "73e422d8426aaa23e8c712b9f4d9bebf70d3bfb9" + "sha1": "e1744403a6691aaa6b65a7e9b4ff9aad98831bb1" }, { "module": "javafx.graphics", "groupId": "org.openjfx", "artifactId": "javafx-graphics", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "mac", - "sha1": "6ab6f3e23421fcfa04e692d9d26a8f55a830c114" + "sha1": "dbe733470094abee56560067d0fea3ad24991d2b" }, { "module": "javafx.controls", "groupId": "org.openjfx", "artifactId": "javafx-controls", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "mac", - "sha1": "b7786b1b63e741c0e234829825fae5fef9d96c31" + "sha1": "0d43a776d6c9e2622e3581ed04501e2cadcd6e65" } ], "osx-arm64": [ @@ -108,25 +108,25 @@ "module": "javafx.base", "groupId": "org.openjfx", "artifactId": "javafx-base", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "mac-aarch64", - "sha1": "1d0d887c492330ed527b0614d115a4f32d2d05a4" + "sha1": "d4dc7d2864c07b56a27e39fa5691856ddccf0ba4" }, { "module": "javafx.graphics", "groupId": "org.openjfx", "artifactId": "javafx-graphics", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "mac-aarch64", - "sha1": "64db28799e61e0f8f51e471c732599b2a6961803" + "sha1": "d6a49f19e90db56c134757d1bbab4935de075d45" }, { "module": "javafx.controls", "groupId": "org.openjfx", "artifactId": "javafx-controls", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "mac-aarch64", - "sha1": "3a14bd5f3ebe45d344c1f2bade0fe074e6ea2a83" + "sha1": "ad564497edc49f7a6135c3b52d360962e19a2539" } ], "linux-x86_64": [ @@ -134,25 +134,25 @@ "module": "javafx.base", "groupId": "org.openjfx", "artifactId": "javafx-base", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "linux", - "sha1": "9e4ca5ce2b87c479d2cc445ff411a48aeae76936" + "sha1": "875f02b498b00c9692f6ed0af3da373b1d07bf03" }, { "module": "javafx.graphics", "groupId": "org.openjfx", "artifactId": "javafx-graphics", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "linux", - "sha1": "27c64e4e1569ddf198f28eda84cf8d014ab80693" + "sha1": "103f3bba5a177ba8912a92ef2ee0855de7ba050c" }, { "module": "javafx.controls", "groupId": "org.openjfx", "artifactId": "javafx-controls", - "version": "19.0.2.1", + "version": "17.0.13", "classifier": "linux", - "sha1": "b5b2a8ead40bd43476740aa51697bb1cac23de5c" + "sha1": "940e9e05a974a3e484d5ec241d88a0c77ad013f2" } ], "linux-arm32": [ diff --git a/javafx.gradle.kts b/javafx.gradle.kts index ac94aca785..aaa266e241 100644 --- a/javafx.gradle.kts +++ b/javafx.gradle.kts @@ -4,11 +4,12 @@ buildscript { } dependencies { - classpath("com.google.code.gson:gson:2.10.1") + classpath("com.google.code.gson:gson:2.11.0") } } -val jfxVersion = "19.0.2.1" +val jfxVersion = "17.0.13" +val oldJfxVersion = "19.0.2.1" data class Platform( val name: String, @@ -29,14 +30,14 @@ val jfxModules = listOf("base", "graphics", "controls") val jfxMirrorRepos = listOf("https://mirrors.cloud.tencent.com/nexus/repository/maven-public") val jfxDependenciesFile = project.file("HMCL/src/main/resources/assets/openjfx-dependencies.json") val jfxPlatforms = listOf( - Platform("windows-x86", "win-x86"), + Platform("windows-x86", "win-x86", version = oldJfxVersion), Platform("windows-x86_64", "win"), Platform("windows-arm64", "win", groupId = "org.glavo.hmcl.openjfx", version = "18.0.2+1-arm64"), Platform("osx-x86_64", "mac"), Platform("osx-arm64", "mac-aarch64"), Platform("linux-x86_64", "linux"), - Platform("linux-arm32", "linux-arm32-monocle"), - Platform("linux-arm64", "linux-aarch64"), + Platform("linux-arm32", "linux-arm32-monocle", version = oldJfxVersion), + Platform("linux-arm64", "linux-aarch64", version = oldJfxVersion), Platform("linux-loongarch64", "linux", groupId = "org.glavo.hmcl.openjfx", version = "17.0.8-loongarch64"), Platform("linux-loongarch64_ow", "linux", groupId = "org.glavo.hmcl.openjfx", version = "19-ea+10-loongson64"), Platform("linux-riscv64", "linux", groupId = "org.glavo.hmcl.openjfx", version = "19.0.2.1-riscv64"), From 965995ad202acd9d9477b9e543fcf7cfb1eb485a Mon Sep 17 00:00:00 2001 From: lijiaxuan <132456728+lijiaxuan1811@users.noreply.github.com> Date: Sun, 20 Oct 2024 09:35:27 -0400 Subject: [PATCH 046/169] =?UTF-8?q?=E7=95=A5=E5=BE=AE=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=BA=86=E4=B8=80=E4=B8=8B=E8=8B=B1=E6=96=87=E7=89=88=E7=9A=84?= =?UTF-8?q?readme.md=20(#3354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updated English version of readme.md 修改了英文版的readme.md,并未增加或删除内容,只是让一些句子更加自然了一些 * Update README.md Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> --------- Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0afa0119df..e2ed0764a3 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ ## Introduction -HMCL is a cross-platform Minecraft launcher which supports Mod Management, Game Customizing, ModLoader Installing (Forge, NeoForge, Fabric, Quilt, LiteLoader and OptiFine), Modpack Creating, UI Customization, and more. +HMCL is an open-source, cross-platform Minecraft launcher that supports Mod Management, Game Customizing, ModLoader Installing (Forge, NeoForge, Fabric, Quilt, LiteLoader and OptiFine), Modpack Creating, UI Customization, and more. -HMCL has amazing cross-platform capabilities. It can not only run on different operating systems such as Windows, Linux, and macOS, but also supports multiple CPU architectures such as x86, ARM, MIPS, and LoongArch. You can easily play Minecraft on different platforms through HMCL. +HMCL has amazing cross-platform capabilities. Not only does it run on different operating systems like Windows, Linux, and macOS, but it also supports various CPU architectures such as x86, ARM, MIPS, and LoongArch. You can easily enjoy Minecraft across different platforms through HMCL. For systems and CPU architectures supported by HMCL, see [this table](PLATFORM.md). @@ -20,13 +20,13 @@ For systems and CPU architectures supported by HMCL, see [this table](PLATFORM.m Download the latest version from [the official website](https://hmcl.huangyuhui.net/download). -You can also download the latest version of HMCL in [GitHub Releases](https://github.com/HMCL-dev/HMCL/releases). +You can also find the latest version of HMCL in [GitHub Releases](https://github.com/HMCL-dev/HMCL/releases). -Although not necessary, it is recommended to download the ones from the official website. +Although not necessary, it is recommended only to download releases from the official websites listed above. ## License -The software is distributed under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) with additional terms. +The software is distributed under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) license with the following additional terms: ### Additional terms under GPLv3 Section 7 @@ -38,7 +38,7 @@ The software is distributed under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.h ## Contribution -If you want to submit a pull request, there are some requirements: +If you want to submit a pull request, here are some requirements: * IDE: IntelliJ IDEA * Compiler: Java 1.8 or Java 11+ @@ -52,7 +52,7 @@ Simply execute the following command in project root directory: ./gradlew clean build ``` -Make sure you have Java installed with JavaFX 8 at least. Liberica Full JDK 8 or later is recommended. +Make sure you have at least JavaFX 8 installed. Liberica Full JDK 8 or later is recommended. ## JVM Options (for debugging) @@ -68,4 +68,4 @@ Make sure you have Java installed with JavaFX 8 at least. Liberica Full JDK 8 or | `-Dhmcl.openjfx.repo=` | Add custom Maven repository for download OpenJFX | | `-Dhmcl.native.encoding=` | Override the native encoding | | `-Dhmcl.microsoft.auth.id=` | Override Microsoft OAuth App ID | -| `-Dhmcl.microsoft.auth.secret=` | Override Microsoft OAuth App secret | \ No newline at end of file +| `-Dhmcl.microsoft.auth.secret=` | Override Microsoft OAuth App secret | From 0a17aad9d68d99bb9decffac48e2aa0f8a02218b Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sun, 20 Oct 2024 21:36:01 +0800 Subject: [PATCH 047/169] Revise readme (#3362) --- README.md | 4 ++-- README_cn.md | 10 +++++----- README_tw.md | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e2ed0764a3..b0118ea253 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # ⛏ Hello Minecraft! Launcher 💎 [![Build Status](https://ci.huangyuhui.net/job/HMCL/badge/icon?.svg)](https://ci.huangyuhui.net/job/HMCL) -![Downloads](https://img.shields.io/github/downloads/huanghongxun/HMCL/total?style=flat) -![Stars](https://img.shields.io/github/stars/huanghongxun/HMCL?style=flat) +![Downloads](https://img.shields.io/github/downloads/HMCL-dev/HMCL/total?style=flat) +![Stars](https://img.shields.io/github/stars/HMCL-dev/HMCL?style=flat) [![Discord](https://img.shields.io/discord/995291757799538688.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/jVvC7HfM6U) [![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=tencentqq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) diff --git a/README_cn.md b/README_cn.md index c94c7e5b62..2d8d7d0d40 100644 --- a/README_cn.md +++ b/README_cn.md @@ -1,8 +1,8 @@ # ⛏ Hello Minecraft! Launcher 💎 [![Build Status](https://ci.huangyuhui.net/job/HMCL/badge/icon?.svg)](https://ci.huangyuhui.net/job/HMCL) -![Downloads](https://img.shields.io/github/downloads/huanghongxun/HMCL/total?style=flat) -![Stars](https://img.shields.io/github/stars/huanghongxun/HMCL?style=flat) +![Downloads](https://img.shields.io/github/downloads/HMCL-dev/HMCL/total?style=flat) +![Stars](https://img.shields.io/github/stars/HMCL-dev/HMCL?style=flat) [![Discord](https://img.shields.io/discord/995291757799538688.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/jVvC7HfM6U) [![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=tencentqq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) @@ -10,7 +10,7 @@ ## 简介 -HMCL 是一款跨平台 Minecraft 启动器,支持模组管理、游戏自定义、游戏自动安装 (Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine)、整合包创建、界面自定义等功能。 +HMCL 是一款开源、跨平台的 Minecraft 启动器,支持模组管理、游戏自定义、游戏自动安装 (Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine)、整合包创建、界面自定义等功能。 HMCL 有着强大的跨平台能力。它不仅支持 Windows、Linux、macOS 等常见的操作系统,同时也支持 x86、ARM、MIPS 和 LoongArch 等不同的 CPU 架构。你可以使用 HMCL 在不同平台上轻松地游玩 Minecraft。 @@ -26,7 +26,7 @@ HMCL 有着强大的跨平台能力。它不仅支持 Windows、Linux、macOS ## 开源协议 -该程序在 [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) 开源协议下发布,同时附有附加条款。 +该程序在 [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) 开源协议下发布,同时附有以下附加条款。 ### 附加条款 (依据 GPLv3 开源协议第七条) @@ -46,7 +46,7 @@ HMCL 有着强大的跨平台能力。它不仅支持 Windows、Linux、macOS ### 编译 -于项目根目录执行以下命令: +于项目根文件夹执行以下命令: ```bash ./gradlew clean build diff --git a/README_tw.md b/README_tw.md index 3441b4ccb2..4fcebadbfb 100644 --- a/README_tw.md +++ b/README_tw.md @@ -1,8 +1,8 @@ # ⛏ Hello Minecraft! Launcher 💎 [![Build Status](https://ci.huangyuhui.net/job/HMCL/badge/icon?.svg)](https://ci.huangyuhui.net/job/HMCL) -![Downloads](https://img.shields.io/github/downloads/huanghongxun/HMCL/total?style=flat) -![Stars](https://img.shields.io/github/stars/huanghongxun/HMCL?style=flat) +![Downloads](https://img.shields.io/github/downloads/HMCL-dev/HMCL/total?style=flat) +![Stars](https://img.shields.io/github/stars/HMCL-dev/HMCL?style=flat) [![Discord](https://img.shields.io/discord/995291757799538688.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/jVvC7HfM6U) [![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=tencentqq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) @@ -10,7 +10,7 @@ ## 簡介 -HMCL 是一款跨平臺 Minecraft 啟動器,支援模組管理、遊戲自訂、遊戲自動安裝 (Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine)、模組包建立、介面自訂等功能。 +HMCL 是一款開源、跨平臺的 Minecraft 啟動器,支援模組管理、遊戲自訂、遊戲自動安裝 (Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine)、模組包建立、介面自訂等功能。 HMCL 有著強大的跨平臺能力。它不僅支援 Windows、Linux、macOS 等常見的作業系統,同時也支援 x86、ARM、MIPS 和 LoongArch 等不同的 CPU 架構。你可以使用 HMCL 在不同平臺上輕鬆地遊玩 Minecraft。 @@ -26,7 +26,7 @@ HMCL 有著強大的跨平臺能力。它不僅支援 Windows、Linux、macOS ## 開源協議 -該程式在 [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) 開源協議下發布,同時附有附加條款。 +該程式在 [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) 開源協議下發布,同時附有以下附加條款。 ### 附加條款 (依據 GPLv3 開源協議第七條) @@ -58,12 +58,12 @@ HMCL 有著強大的跨平臺能力。它不僅支援 Windows、Linux、macOS | 參數 | 簡介 | | -------------------------------------------- | -------------------------------------------------------------------- | -| `-Dhmcl.home=` | 覆蓋 HMCL 使用者資料夾 | +| `-Dhmcl.home=` | 覆蓋 HMCL 使用者目錄 | | `-Dhmcl.self_integrity_check.disable=true` | 檢查更新時繞過本體完整性檢查 | | `-Dhmcl.bmclapi.override=` | 覆蓋 BMCLAPI 的 API Root,預設值為 `https://bmclapi2.bangbang93.com` | | `-Dhmcl.font.override=` | 覆蓋字族 | | `-Dhmcl.version.override=` | 覆蓋版本號 | -| `-Dhmcl.update_source.override=` | 覆蓋 HMCL 更新源 | +| `-Dhmcl.update_source.override=` | 覆蓋 HMCL 更新來源 | | `-Dhmcl.authlibinjector.location=` | 使用指定的 authlib-injector (而非下載一個) | | `-Dhmcl.openjfx.repo=` | 添加用於下載 OpenJFX 的自訂 Maven 倉庫 | | `-Dhmcl.native.encoding=` | 覆蓋原生編碼 | From 99c3ef8a57ed9064c2fa87ea5e97eb25a5c8001f Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 20 Oct 2024 22:26:38 +0800 Subject: [PATCH 048/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20Java=20=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E5=8A=9F=E8=83=BD=20(#3369)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update * update --- .../hmcl/download/java/JavaPackageType.java | 6 ++--- .../java/disco/DiscoFetchJavaListTask.java | 22 ++++++++++++++----- .../java/disco/DiscoJavaDistribution.java | 12 +++++++--- .../java/disco/DiscoJavaRemoteVersion.java | 2 +- .../org/jackhuang/hmcl/java/JavaInfo.java | 1 + 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaPackageType.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaPackageType.java index 42cc195d8f..1512a1705a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaPackageType.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaPackageType.java @@ -21,10 +21,10 @@ * @author Glavo */ public enum JavaPackageType { - JDK(true, false), JRE(false, false), - JDKFX(true, true), - JREFX(false, true); + JDK(true, false), + JREFX(false, true), + JDKFX(true, true); private final boolean jdk; private final boolean javafx; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java index d4f333b34e..adfd14cde9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java @@ -46,22 +46,27 @@ private static String getArchitectureName(Architecture arch) { } private final DiscoJavaDistribution distribution; + private final String packageType; + private final boolean isJavaFXBundled; + private final String archiveType; private final Task fetchPackagesTask; public DiscoFetchJavaListTask(DownloadProvider downloadProvider, DiscoJavaDistribution distribution, Platform platform, JavaPackageType packageType) { this.distribution = distribution; + this.packageType = packageType.isJDK() ? "jdk" : "jre"; + this.isJavaFXBundled = packageType.isJavaFXBundled(); + this.archiveType = platform.getOperatingSystem() == OperatingSystem.WINDOWS ? "zip" : "tar.gz"; HashMap params = new HashMap<>(); params.put("distribution", distribution.getApiParameter()); - params.put("package", packageType.isJDK() ? "jdk" : "jre"); - params.put("javafx_bundled", Boolean.toString(packageType.isJavaFXBundled())); + params.put("package", this.packageType); + params.put("javafx_bundled", Boolean.toString(isJavaFXBundled)); params.put("operating_system", getOperatingSystemName(platform.getOperatingSystem())); params.put("architecture", getArchitectureName(platform.getArchitecture())); - params.put("archive_type", platform.getOperatingSystem() == OperatingSystem.WINDOWS ? "zip" : "tar.gz"); + params.put("archive_type", archiveType); params.put("directly_downloadable", "true"); - if (platform.getOperatingSystem() == OperatingSystem.LINUX) { + if (platform.getOperatingSystem() == OperatingSystem.LINUX) params.put("lib_c_type", "glibc"); - } this.fetchPackagesTask = new GetTask(downloadProvider.injectURLWithCandidates(NetworkUtils.withQuery(API_ROOT + "/packages", params))); } @@ -79,6 +84,13 @@ public void execute() throws Exception { TreeMap map = new TreeMap<>(); for (DiscoJavaRemoteVersion version : result) { + if (!distribution.getApiParameter().equals(version.getDistribution()) + || !version.isDirectlyDownloadable() + || !packageType.equals(version.getPackageType()) + || !archiveType.equals(version.getArchiveType()) + || isJavaFXBundled != version.isJavaFXBundled()) + continue; + if (!distribution.testVersion(version)) continue; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java index 52d013bf1c..49a5005f3e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java @@ -43,7 +43,7 @@ public enum DiscoJavaDistribution implements JavaDistribution Date: Wed, 23 Oct 2024 21:49:35 +0800 Subject: [PATCH 049/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20Java=20=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E5=8A=9F=E8=83=BD=20(#3371)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update * update * update --- .../hmcl/ui/main/JavaDownloadDialog.java | 230 +++++++++--------- .../hmcl/download/java/JavaDistribution.java | 7 - .../hmcl/download/java/JavaPackageType.java | 7 + .../java/disco/DiscoFetchJavaListTask.java | 29 +-- .../java/disco/DiscoJavaDistribution.java | 7 - .../java/disco/DiscoJavaRemoteVersion.java | 4 + .../java/mojang/MojangJavaDistribution.java | 9 - 7 files changed, 135 insertions(+), 158 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java index cb19775476..231be4b2b5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java @@ -21,7 +21,6 @@ import javafx.beans.binding.Bindings; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.value.ChangeListener; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.control.Label; @@ -46,7 +45,6 @@ import org.jackhuang.hmcl.ui.construct.DialogPane; import org.jackhuang.hmcl.ui.construct.JFXHyperlink; import org.jackhuang.hmcl.ui.wizard.SinglePageWizardProvider; -import org.jackhuang.hmcl.util.Pair; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.TaskCancellationAction; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -56,6 +54,7 @@ import java.io.IOException; import java.util.*; import java.util.concurrent.CancellationException; +import java.util.function.Consumer; import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; import static org.jackhuang.hmcl.util.Lang.resolveException; @@ -118,6 +117,8 @@ private final class DownloadMojangJava extends DialogPane { button.setUserData(version); vbox.getChildren().add(button); toggleGroup.getToggles().add(button); + if (JavaManager.REPOSITORY.isInstalled(platform, version)) + button.setDisable(true); } setBody(vbox); @@ -166,19 +167,6 @@ protected void onAccept() { } private final class DownloadDiscoJava extends JFXDialogLayout { - - private boolean isLTS(int major) { - if (major <= 8) { - return true; - } - - if (major < 21) { - return major == 11 || major == 17; - } - - return major % 4 == 1; - } - private final JFXComboBox distributionBox; private final JFXComboBox remoteVersionBox; private final JFXComboBox packageTypeBox; @@ -189,11 +177,8 @@ private boolean isLTS(int major) { private final DownloadProvider downloadProvider = DownloadProviders.getDownloadProvider(); - private final ObjectProperty currentDiscoJavaVersionList = new SimpleObjectProperty<>(); - - private final Map, DiscoJavaVersionList> javaVersionLists = new HashMap<>(); - - private boolean changingDistribution = false; + private final Map javaVersionLists = new HashMap<>(); + private final ObjectProperty currentJavaVersionList = new SimpleObjectProperty<>(); DownloadDiscoJava() { assert !distributions.isEmpty(); @@ -204,7 +189,7 @@ private boolean isLTS(int major) { this.remoteVersionBox = new JFXComboBox<>(); this.remoteVersionBox.setConverter(FXUtils.stringConverter(JavaRemoteVersion::getDistributionVersion)); - this.packageTypeBox = new JFXComboBox<>(); + this.packageTypeBox = new JFXComboBox<>(FXCollections.observableArrayList()); this.downloadButton = new JFXButton(i18n("download")); downloadButton.setOnAction(e -> onDownload()); @@ -227,66 +212,91 @@ private boolean isLTS(int major) { body.addRow(2, new Label(i18n("java.download.packageType")), packageTypeBox); distributionBox.setItems(FXCollections.observableList(new ArrayList<>(distributions))); - ChangeListener updateStatusListener = (observable, oldValue, newValue) -> updateStatus(newValue); - this.currentDiscoJavaVersionList.addListener((observable, oldValue, newValue) -> { - if (oldValue != null) { - oldValue.status.removeListener(updateStatusListener); + + FXUtils.onChange(packageTypeBox.getSelectionModel().selectedItemProperty(), packageType -> { + ObservableList versions; + if (packageType == null + || currentJavaVersionList.get() == null + || (versions = currentJavaVersionList.get().versions.get(packageType)) == null) { + remoteVersionBox.setItems(null); + return; } - if (newValue != null) { - newValue.status.addListener(updateStatusListener); - updateStatus(newValue.status.get()); - } else { - updateStatus(null); + remoteVersionBox.setItems(versions); + + for (int i = 0; i < versions.size(); i++) { + DiscoJavaRemoteVersion version = versions.get(i); + if (version.getJdkVersion() == GameJavaVersion.LATEST.getMajorVersion()) { + remoteVersionBox.getSelectionModel().select(i); + return; + } } + + for (int i = 0; i < versions.size(); i++) { + DiscoJavaRemoteVersion version = versions.get(i); + if (version.isLTS()) { + remoteVersionBox.getSelectionModel().select(i); + return; + } + } + + remoteVersionBox.getSelectionModel().selectFirst(); }); - packageTypeBox.getSelectionModel().selectedItemProperty().addListener(ignored -> updateVersions()); - FXUtils.onChangeAndOperate(distributionBox.getSelectionModel().selectedItemProperty(), distribution -> { - if (distribution != null) { - changingDistribution = true; - packageTypeBox.setItems(FXCollections.observableList(new ArrayList<>(distribution.getSupportedPackageTypes()))); - packageTypeBox.getSelectionModel().select(0); - changingDistribution = false; - updateVersions(); - packageTypeBox.setDisable(false); - remoteVersionBox.setDisable(false); + Consumer updateListStatus = list -> { + remoteVersionBox.setItems(null); + packageTypeBox.getItems().clear(); + remoteVersionBox.setDisable(true); + packageTypeBox.setDisable(true); + warningLabel.setText(null); + + if (list == null || (list.versions != null && list.versions.isEmpty())) + downloadButtonPane.getChildren().setAll(downloadButton); + else if (list.status == DiscoJavaVersionList.Status.LOADING) + downloadButtonPane.getChildren().setAll(new JFXSpinner()); + else { + downloadButtonPane.getChildren().setAll(downloadButton); + + if (list.status == DiscoJavaVersionList.Status.SUCCESS) { + packageTypeBox.getItems().setAll(list.versions.keySet()); + packageTypeBox.getSelectionModel().selectFirst(); + + remoteVersionBox.setDisable(false); + packageTypeBox.setDisable(false); + } else + warningLabel.setText(i18n("java.download.load_list.failed")); + } + }; + + currentJavaVersionList.addListener((observable, oldValue, newValue) -> { + if (oldValue != null) + oldValue.listener = null; + + if (newValue != null) { + updateListStatus.accept(newValue); + + if (newValue.status == DiscoJavaVersionList.Status.LOADING) + newValue.listener = updateListStatus; } else { - packageTypeBox.setItems(null); - updateVersions(); - remoteVersionBox.setItems(null); - packageTypeBox.setDisable(true); - remoteVersionBox.setDisable(true); + currentJavaVersionList.set(null); + updateListStatus.accept(null); } }); + FXUtils.onChange(distributionBox.getSelectionModel().selectedItemProperty(), + it -> currentJavaVersionList.set(getJavaVersionList(it))); + setHeading(new Label(i18n("java.download"))); setBody(body); setActions(warningLabel, downloadButtonPane, cancelButton); } - private void updateStatus(DiscoJavaVersionList.Status status) { - if (status == DiscoJavaVersionList.Status.LOADING) { - downloadButtonPane.getChildren().setAll(new JFXSpinner()); - remoteVersionBox.setDisable(true); - warningLabel.setText(null); - } else { - downloadButtonPane.getChildren().setAll(downloadButton); - if (status == DiscoJavaVersionList.Status.SUCCESS || status == null) { - remoteVersionBox.setDisable(false); - warningLabel.setText(null); - } else if (status == DiscoJavaVersionList.Status.FAILED) { - remoteVersionBox.setDisable(true); - warningLabel.setText(i18n("java.download.load_list.failed")); - } - } - } - private void onDownload() { fireEvent(new DialogCloseEvent()); DiscoJavaDistribution distribution = distributionBox.getSelectionModel().getSelectedItem(); DiscoJavaRemoteVersion version = remoteVersionBox.getSelectionModel().getSelectedItem(); + JavaPackageType packageType = packageTypeBox.getSelectionModel().getSelectedItem(); if (version == null) return; @@ -343,7 +353,7 @@ else if (StringUtils.isNotBlank(fileInfo.getChecksumUri())) if (idx > 0) { javaVersion = javaVersion.substring(0, idx); } - String defaultName = distribution.getApiParameter() + "-" + javaVersion; + String defaultName = distribution.getApiParameter() + "-" + javaVersion + "-" + packageType.name().toLowerCase(Locale.ROOT); Controllers.getDecorator().startWizard(new SinglePageWizardProvider(controller -> new JavaInstallPage(controller::onFinish, info, version, updateInfo, defaultName, result))); } else { @@ -357,65 +367,39 @@ else if (StringUtils.isNotBlank(fileInfo.getChecksumUri())) } - private void updateVersions() { - if (changingDistribution) return; - - DiscoJavaDistribution distribution = distributionBox.getSelectionModel().getSelectedItem(); - if (distribution == null) { - this.currentDiscoJavaVersionList.set(null); - return; - } - - JavaPackageType packageType = packageTypeBox.getSelectionModel().getSelectedItem(); - - DiscoJavaVersionList list = javaVersionLists.computeIfAbsent(Pair.pair(distribution, packageType), pair -> { - DiscoJavaVersionList res = new DiscoJavaVersionList(); - new DiscoFetchJavaListTask(downloadProvider, distribution, platform, packageType).setExecutor(Schedulers.io()).thenApplyAsync(versions -> { - if (versions.isEmpty()) return Collections.emptyList(); - - int lastLTS = -1; - for (int v : versions.keySet()) { - if (isLTS(v)) { - lastLTS = v; - } - } - - ArrayList remoteVersions = new ArrayList<>(); - for (Map.Entry entry : versions.entrySet()) { - int v = entry.getKey(); - if (v >= lastLTS || isLTS(v) || v == 16) { - remoteVersions.add(entry.getValue()); - } - } - Collections.reverse(remoteVersions); - return remoteVersions; + private DiscoJavaVersionList getJavaVersionList(DiscoJavaDistribution distribution) { + if (distribution == null) + return null; + return javaVersionLists.computeIfAbsent(distribution, it -> { + DiscoJavaVersionList versionList = new DiscoJavaVersionList(it); + new DiscoFetchJavaListTask(downloadProvider, it, platform).setExecutor(Schedulers.io()).thenApplyAsync(versions -> { + EnumMap> result = new EnumMap<>(JavaPackageType.class); + if (versions.isEmpty()) + return result; + + for (Map.Entry> entry : versions.entrySet()) + for (DiscoJavaRemoteVersion version : entry.getValue().values()) + if (version.isLTS() + || version.getJdkVersion() == entry.getValue().lastKey() // latest version + || version.getJdkVersion() == 16) + result.computeIfAbsent(entry.getKey(), ignored -> FXCollections.observableArrayList()) + .add(version); + + for (List l : result.values()) + Collections.reverse(l); + return result; }).whenComplete(Schedulers.javafx(), ((result, exception) -> { if (exception == null) { - res.status.set(DiscoJavaVersionList.Status.SUCCESS); - res.versions.setAll(result); - selectLTS(res); + versionList.status = DiscoJavaVersionList.Status.SUCCESS; + versionList.versions = result; } else { LOG.warning("Failed to load java list", exception); - res.status.set(DiscoJavaVersionList.Status.FAILED); + versionList.status = DiscoJavaVersionList.Status.FAILED; } + versionList.invalidate(); })).start(); - return res; + return versionList; }); - this.currentDiscoJavaVersionList.set(list); - this.remoteVersionBox.setItems(list.versions); - selectLTS(list); - } - - private void selectLTS(DiscoJavaVersionList list) { - if (remoteVersionBox.getItems() == list.versions) { - for (int i = 0; i < list.versions.size(); i++) { - JavaRemoteVersion item = list.versions.get(i); - if (item.getJdkVersion() == GameJavaVersion.LATEST.getMajorVersion()) { - remoteVersionBox.getSelectionModel().select(i); - break; - } - } - } } } @@ -424,7 +408,19 @@ enum Status { LOADING, SUCCESS, FAILED } - final ObservableList versions = FXCollections.observableArrayList(); - final ObjectProperty status = new SimpleObjectProperty<>(Status.LOADING); + final DiscoJavaDistribution distribution; + + Status status = Status.LOADING; + EnumMap> versions; + Consumer listener; + + DiscoJavaVersionList(DiscoJavaDistribution distribution) { + this.distribution = distribution; + } + + void invalidate() { + if (listener != null) + listener.accept(this); + } } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaDistribution.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaDistribution.java index f4032bebb7..96d02c95cc 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaDistribution.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaDistribution.java @@ -17,12 +17,7 @@ */ package org.jackhuang.hmcl.download.java; -import org.jackhuang.hmcl.download.DownloadProvider; -import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.util.platform.Platform; - import java.util.Set; -import java.util.TreeMap; /** * @author Glavo @@ -31,6 +26,4 @@ public interface JavaDistribution { String getDisplayName(); Set getSupportedPackageTypes(); - - Task> getFetchJavaVersionsTask(DownloadProvider provider, Platform platform, JavaPackageType packageType); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaPackageType.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaPackageType.java index 1512a1705a..8fcf4d3739 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaPackageType.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/JavaPackageType.java @@ -34,6 +34,13 @@ public enum JavaPackageType { this.javafx = javafx; } + public static JavaPackageType of(boolean jdk, boolean javafx) { + if (jdk) + return javafx ? JDKFX : JDK; + else + return javafx ? JREFX : JRE; + } + public boolean isJDK() { return jdk; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java index adfd14cde9..df178fe576 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoFetchJavaListTask.java @@ -33,7 +33,7 @@ /** * @author Glavo */ -public final class DiscoFetchJavaListTask extends Task> { +public final class DiscoFetchJavaListTask extends Task>> { public static final String API_ROOT = System.getProperty("hmcl.discoapi.override", "https://api.foojay.io/disco/v3.0"); @@ -46,21 +46,15 @@ private static String getArchitectureName(Architecture arch) { } private final DiscoJavaDistribution distribution; - private final String packageType; - private final boolean isJavaFXBundled; private final String archiveType; private final Task fetchPackagesTask; - public DiscoFetchJavaListTask(DownloadProvider downloadProvider, DiscoJavaDistribution distribution, Platform platform, JavaPackageType packageType) { + public DiscoFetchJavaListTask(DownloadProvider downloadProvider, DiscoJavaDistribution distribution, Platform platform) { this.distribution = distribution; - this.packageType = packageType.isJDK() ? "jdk" : "jre"; - this.isJavaFXBundled = packageType.isJavaFXBundled(); this.archiveType = platform.getOperatingSystem() == OperatingSystem.WINDOWS ? "zip" : "tar.gz"; HashMap params = new HashMap<>(); params.put("distribution", distribution.getApiParameter()); - params.put("package", this.packageType); - params.put("javafx_bundled", Boolean.toString(isJavaFXBundled)); params.put("operating_system", getOperatingSystemName(platform.getOperatingSystem())); params.put("architecture", getArchitectureName(platform.getArchitecture())); params.put("archive_type", archiveType); @@ -79,29 +73,28 @@ public Collection> getDependents() { @Override public void execute() throws Exception { String json = fetchPackagesTask.getResult(); - List result = JsonUtils.fromNonNullJson(json, DiscoResult.typeOf(DiscoJavaRemoteVersion.class)).getResult(); + List list = JsonUtils.fromNonNullJson(json, DiscoResult.typeOf(DiscoJavaRemoteVersion.class)).getResult(); + EnumMap> result = new EnumMap<>(JavaPackageType.class); - TreeMap map = new TreeMap<>(); - - for (DiscoJavaRemoteVersion version : result) { + for (DiscoJavaRemoteVersion version : list) { if (!distribution.getApiParameter().equals(version.getDistribution()) || !version.isDirectlyDownloadable() - || !packageType.equals(version.getPackageType()) - || !archiveType.equals(version.getArchiveType()) - || isJavaFXBundled != version.isJavaFXBundled()) + || !archiveType.equals(version.getArchiveType())) continue; if (!distribution.testVersion(version)) continue; + JavaPackageType packageType = JavaPackageType.of("jdk".equals(version.getPackageType()), version.isJavaFXBundled()); + TreeMap map = result.computeIfAbsent(packageType, ignored -> new TreeMap<>()); + int jdkVersion = version.getJdkVersion(); DiscoJavaRemoteVersion oldVersion = map.get(jdkVersion); - if (oldVersion == null || VersionNumber.compare(version.getDistributionVersion(), oldVersion.getDistributionVersion()) > 0) { + if (oldVersion == null || VersionNumber.compare(version.getDistributionVersion(), oldVersion.getDistributionVersion()) > 0) map.put(jdkVersion, version); - } } - setResult(map); + setResult(result); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java index 49a5005f3e..5a9c696beb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaDistribution.java @@ -17,10 +17,8 @@ */ package org.jackhuang.hmcl.download.java.disco; -import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.java.JavaDistribution; import org.jackhuang.hmcl.download.java.JavaPackageType; -import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Pair; import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.OperatingSystem; @@ -131,11 +129,6 @@ public boolean isSupport(Platform platform) { return architectures != null && architectures.contains(platform.getArchitecture()); } - @Override - public Task> getFetchJavaVersionsTask(DownloadProvider provider, Platform platform, JavaPackageType packageType) { - return new DiscoFetchJavaListTask(provider, this, platform, packageType); - } - public boolean testVersion(DiscoJavaRemoteVersion version) { return this.getApiParameter().equals(version.getDistribution()); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaRemoteVersion.java index 6c74480010..ca65643db7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaRemoteVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/disco/DiscoJavaRemoteVersion.java @@ -171,6 +171,10 @@ public String getTermOfSupport() { return termOfSupport; } + public boolean isLTS() { + return "lts".equals(termOfSupport); + } + public String getOperatingSystem() { return operatingSystem; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDistribution.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDistribution.java index b8de72f728..3f257264fd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDistribution.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDistribution.java @@ -17,16 +17,12 @@ */ package org.jackhuang.hmcl.download.java.mojang; -import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.java.JavaDistribution; import org.jackhuang.hmcl.download.java.JavaPackageType; import org.jackhuang.hmcl.download.java.JavaRemoteVersion; -import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.util.platform.Platform; import java.util.Collections; import java.util.Set; -import java.util.TreeMap; /** * @author Glavo @@ -47,9 +43,4 @@ public String getDisplayName() { public Set getSupportedPackageTypes() { return Collections.singleton(JavaPackageType.JRE); } - - @Override - public Task> getFetchJavaVersionsTask(DownloadProvider provider, Platform platform, JavaPackageType packageType) { - return null; - } } From f686cb0ceb0023c21392c3d8eb9ef9eb3fd66c5a Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Wed, 23 Oct 2024 23:00:02 +0800 Subject: [PATCH 050/169] Update versions.txt (#3373) --- .../main/resources/assets/game/versions.txt | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/HMCLCore/src/main/resources/assets/game/versions.txt b/HMCLCore/src/main/resources/assets/game/versions.txt index 82cef053a6..2d8fdada50 100644 --- a/HMCLCore/src/main/resources/assets/game/versions.txt +++ b/HMCLCore/src/main/resources/assets/game/versions.txt @@ -767,4 +767,23 @@ 1.21-pre3 1.21-pre4 1.21-rc1 -1.21 \ No newline at end of file +1.21 +1.21.1-rc1 +1.21.1 +24w33a +24w34a +24w35a +24w36a +24w37a +24w38a +24w39a +24w40a +1.21.2-pre1 +1.21.2-pre2 +1.21.2-pre3 +1.21.2-pre4 +1.21.2-pre5 +1.21.2-rc1 +1.21.2-rc2 +1.21.2 +1.21.3 \ No newline at end of file From a11816884cb51213a8d7d20c4afb68b9e498de44 Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 24 Oct 2024 01:01:31 +0800 Subject: [PATCH 051/169] =?UTF-8?q?=E5=88=9B=E5=BB=BA=20@FXThread=20?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3=20(#3374)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/util/FXThread.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/FXThread.java diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/FXThread.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/FXThread.java new file mode 100644 index 0000000000..53974cb0a2 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/FXThread.java @@ -0,0 +1,32 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2024 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.jackhuang.hmcl.util; + +import java.lang.annotation.*; + +/** + * Mark a method that can only be called on the JavaFX Application Thread, + * or mark a field that can only be read/modified on the JavaFX Application Thread. + * + * @author Glavo + */ +@Documented +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.SOURCE) +public @interface FXThread { +} From e857f19b1876a242b4512b4e11ea9d18b52c03f7 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Thu, 24 Oct 2024 14:25:37 +0800 Subject: [PATCH 052/169] Revise zh_CN part 4 (#3349) * Revise zh_CN part 4 * Update * fix some typo * Revise Co-authored-by: Glavo * Revise Co-authored-by: Glavo * Revise Co-authored-by: Glavo --------- Co-authored-by: Glavo --- .../assets/lang/I18N_zh_CN.properties | 267 +++++++++--------- 1 file changed, 135 insertions(+), 132 deletions(-) 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 184a894720..e9151298c2 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -76,7 +76,7 @@ account.failed.server_disconnected=无法访问登录服务器,账户信息刷 account.failed.server_response_malformed=无法解析认证服务器响应,可能是服务器故障。 account.failed.ssl=连接服务器时发生了 SSL 错误,可能网站证书已过期或你使用的 Java 版本过低,请尝试更新 Java,或关闭网络代理后再试。\n你可以点击右上角帮助按钮进行求助。 account.failed.wrong_account=登录了错误的账户 -account.hmcl.hint=你需要点击“登录”按钮,并在打开的网页中完成登录。 +account.hmcl.hint=你需要点击“登录”按钮,并在弹出的网页中完成登录。 account.injector.add=添加认证服务器 account.injector.empty=无 (点击右侧加号添加) account.injector.http=警告:此服务器使用不安全的 HTTP 协议,你的密码在登录时会被明文传输。 @@ -111,23 +111,23 @@ account.methods.microsoft.error.wrong_verify_method=请在微软账户登录页 account.methods.microsoft.logging_in=登录中…… account.methods.microsoft.makegameidsettings=创建档案 / 编辑档案名称 account.methods.microsoft.hint=你需要按照以下步骤添加账户:\n\ - 1.点击“登录”按钮\n\ - 2.在网页浏览器显示的网站中输入 HMCL 显示的代码(自动拷贝,直接粘贴即可),并点击“下一步”\n\ - 3.按照网站的提示登录\n\ - 4.当网站提示“是否允许此应用访问你的信息?”的标识时,请点击“是”\n\ - 5.在网站提示“大功告成”后,只需等待账户完成添加即可\n\ - -若网站提示“出现错误”的标识或账户添加失败时,请重新按照以上步骤重新添加\n\ - -若设备网络环境不佳,可能登录网站加载很慢甚至无法加载,此时请使用网络代理并重试\n\ + \ 1.点击“登录”按钮;\n\ + \ 2.在弹出的网页中输入 HMCL 显示的代码,并点击“下一步”;\n\ + \ 3.按照网站的提示登录;\n\ + \ 4.当网站提示“是否允许此应用访问你的信息?”的标识时,请点击“是”;\n\ + \ 5.在网站提示“大功告成”后,只需等待账户完成添加即可。\n\ + 若网站提示“出现错误”的标识或账户添加失败时,请重新按照以上步骤重新添加。\n\ + 若设备网络环境不佳,可能登录网站加载很慢甚至无法加载,此时请使用网络代理并重试。\n\ 如遇到问题,你可以点击右上角帮助按钮进行求助。 account.methods.microsoft.manual=你需要按照以下步骤添加:\n\ - 1.点击“登录”按钮\n\ - 2.在网页浏览器显示的网站中输入:%1$s(已自动拷贝,点此再次拷贝),并点击“下一步”\n\ - 3.按照网站的提示登录\n\ - 4.当网站提示“是否允许此应用访问你的信息?”的标识时,请点击“是”\n\ - 5.在网站提示“大功告成”后,只需等待账户完成添加即可\n\ - -若网站提示“出现错误”的标识或账户添加失败时,请重新按照以上步骤重新添加\n\ - -若网站未能显示,请手动在网页浏览器中打开:%2$s\n\ - -若设备网络环境不佳,可能登录网站加载很慢甚至无法加载,此时请使用网络代理并重试\n\ + \ 1.点击“登录”按钮;\n\ + \ 2.在弹出的网页中输入:%1$s (已自动复制,点此再次复制),并点击“下一步”;\n\ + \ 3.按照网站的提示登录;\n\ + \ 4.当网站提示“是否允许此应用访问你的信息?”的标识时,请点击“是”;\n\ + \ 5.在网站提示“大功告成”后,只需等待账户完成添加即可。\n\ + 若网站未能显示,请手动在浏览器中打开:%2$s\n\ + 若网站提示“出现错误”的标识或账户添加失败时,请重新按照以上步骤重新添加。\n\ + 若设备网络环境不佳,可能登录网站加载很慢甚至无法加载,此时请使用网络代理并重试。\n\ 如遇到问题,你可以点击右上角帮助按钮进行求助。 account.methods.microsoft.profile=账户设置页 account.methods.microsoft.purchase=购买 Minecraft @@ -174,7 +174,7 @@ archive.version=版本 assets.download=下载资源 assets.download_all=检查资源文件完整性 -assets.index.malformed=资源文件的索引文件损坏,你可以在相应版本的“版本设置”页面中,点击左下角的“管理”按钮,点击“更新游戏资源文件”以修复该问题。\n你可以点击右上角帮助按钮进行求助。 +assets.index.malformed=资源文件的索引文件损坏,你可以在相应版本的“版本管理”页面中,点击左下角“管理 → 更新游戏资源文件”以修复该问题。\n你可以点击右上角帮助按钮进行求助。 button.cancel=取消 button.change_source=切换下载源 @@ -331,7 +331,7 @@ download=下载 download.hint=安装游戏和整合包或下载模组、资源包和地图 download.code.404=远程服务器不包含需要下载的文件: %s\n你可以点击右上角帮助按钮进行求助。 download.content=游戏内容 -download.curseforge.unavailable=HMCL 预览版暂不支持访问 CurseForge,请使用稳定版或测试版进行下载。 +download.curseforge.unavailable=HMCL 预览版暂不支持访问 CurseForge,请使用稳定版或开发版进行下载。 download.existing=文件已存在,无法保存。你可以将文件保存至其他地方。 download.external_link=打开下载网站 download.failed=下载失败: %1$s,\n错误码:%2$d\n你可以点击右上角帮助按钮进行求助。 @@ -380,7 +380,7 @@ fatal.illegal_char=由于你的用户文件夹路径中存在非法字符“=” fatal.unsupported_platform=Minecraft 尚未对你的平台提供完善支持,所以可能影响游戏体验或无法启动游戏。\n若无法启动 Minecraft 1.17 及更高版本,可以尝试在“(全局/版本特定) 游戏设置 → 高级设置 → 调试选项”中将“渲染器”切换为“软渲染器”,以获得更好的兼容性。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher 已为龙芯提供支持。\n如果遇到问题,你可以点击右上角帮助按钮进行求助。 fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher 已为 Apple Silicon 平台提供支持,使用 ARM 原生 Java 启动游戏以获得更流畅的游戏体验。\n如果你在游戏中遇到问题,使用 x86-64 架构的 Java 启动游戏可能有更好的兼容性。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 -fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已为 Windows on ARM 平台提供原生支持。如果你在游戏中遇到问题,请尝试使用 x86 架构的 Java 启动游戏。\n如果你正在使用 高通 平台,你可能需要安装 OpenGL 兼容包 后才能进行游戏。点击链接前往 Microsoft Store 安装兼容包。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已为 Windows on Arm 平台提供原生支持。如果你在游戏中遇到问题,请尝试使用 x86 架构的 Java 启动游戏。\n如果你正在使用 高通 平台,你可能需要安装 OpenGL 兼容包 后才能进行游戏。点击链接前往 Microsoft Store 安装兼容包。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 feedback=反馈 feedback.channel=反馈渠道 @@ -443,8 +443,8 @@ game.crash.reason.mod_resolution_missing=当前游戏由于缺少前置模组, game.crash.reason.mod_resolution_missing_minecraft=当前游戏由于模组和 Minecraft 游戏版本不匹配,无法继续运行。\n“%1$s”需要 Minecraft %2$s 才能运行。\n如果你要继续使用你已经安装的模组,你可以选择安装对应的 Minecraft 版本;如果你要继续使用当前 Minecraft 版本,你需要安装对应版本的模组。 game.crash.reason.mod_resolution_mod_version=%1$s (版本号 %2$s) game.crash.reason.mod_resolution_mod_version.any=%1$s (任意版本) -game.crash.reason.forge_repeat_installation=当前游戏由于 Forge 重复安装,无法继续运行。此为已知问题\n建议将日志上传并反馈至 GitHub,以便我们找到更多线索并修复此问题。\n目前你可以在“版本设置 → 自动安装”中卸载 Forge 并重新安装。 -game.crash.reason.optifine_repeat_installation=当前游戏由于 OptiFine 重复安装,无法继续运行。\n请删除模组文件夹下的 OptiFine 或前往“版本设置 → 自动安装”卸载安装的 OptiFine。 +game.crash.reason.forge_repeat_installation=当前游戏由于 Forge 重复安装,无法继续运行。此为已知问题\n建议将日志上传并反馈至 GitHub,以便我们找到更多线索并修复此问题。\n目前你可以在“版本管理 → 自动安装”中卸载 Forge 并重新安装。 +game.crash.reason.optifine_repeat_installation=当前游戏由于 OptiFine 重复安装,无法继续运行。\n请删除模组文件夹下的 OptiFine 或前往“版本管理 → 自动安装”卸载安装的 OptiFine。 game.crash.reason.forgemod_resolution=当前游戏由于模组依赖问题,无法继续运行。Forge/NeoForge 提供了如下信息:\n%1$s game.crash.reason.forge_found_duplicate_mods=当前游戏由于模组重复安装,无法继续运行。Forge/NeoForge 提供了如下信息:\n%1$s game.crash.reason.modmixin_failure=当前游戏由于某些模组注入失败,无法继续运行。\n这一般代表着该模组存在问题,或与当前环境不兼容。\n你可以查看日志寻找出错模组。 @@ -453,13 +453,13 @@ game.crash.reason.forge_error=Forge/NeoForge 可能已经提供了错误信息 game.crash.reason.mod_resolution0=当前游戏由于一些模组出现问题,无法继续运行。\n你可以查看日志寻找出错模组。 game.crash.reason.java_version_is_too_high=当前游戏由于 Java 虚拟机版本过高,无法继续运行。\n请在“(全局/版本特定) 游戏设置 → 游戏 Java”中改用较低版本的 Java,然后再启动游戏。\n如果没有,可以从 java.com (Java 8)BellSoft Liberica Full JRE (Java 17) 等平台下载、安装一个 (安装完后需重启启动器)。 game.crash.reason.mod_name=当前游戏由于模组文件名称问题,无法继续运行。\n模组文件名称应只使用半角的大小写字母 (Aa~Zz)、数字 (0~9)、横线 (-)、下划线 (_)和点 (.)。\n请到模组文件夹中将所有不合规的模组文件名修改为上述合规字符。 -game.crash.reason.incomplete_forge_installation=当前游戏由于 Forge/NeoForge 安装不完整,无法继续运行。\n请在“版本设置 → 自动安装”中卸载 Forge 并重新安装。 -game.crash.reason.optifine_is_not_compatible_with_forge=当前游戏由于 OptiFine 与当前版本的 Forge 不兼容,导致游戏崩溃。\n点击 此处 查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏或在“版本设置 → 自动安装”中更换版本。\n经测试,Forge 版本过高或过低都可能导致崩溃。 +game.crash.reason.incomplete_forge_installation=当前游戏由于 Forge/NeoForge 安装不完整,无法继续运行。\n请在“版本管理 → 自动安装”中卸载 Forge 并重新安装。 +game.crash.reason.optifine_is_not_compatible_with_forge=当前游戏由于 OptiFine 与当前版本的 Forge 不兼容,导致游戏崩溃。\n点击 此处 查看 OptiFine 所兼容的 Forge 版本,并严格按照对应版本重新安装游戏或在“版本管理 → 自动安装”中更换版本。\n经测试,Forge 版本过高或过低都可能导致崩溃。 game.crash.reason.mod_files_are_decompressed=当前游戏由于模组文件被解压了,无法继续运行。\n请直接把整个模组文件放进模组文件夹中即可。\n解压模组会导致游戏出错,请删除模组文件夹中已被解压的模组,然后再启动游戏。 game.crash.reason.shaders_mod=当前游戏由于同时安装了 OptiFine 和 Shaders 模组,无法继续运行。\n由于 OptiFine 已集成 Shaders 模组的功能,所以只需删除 Shaders 模组即可。 game.crash.reason.rtss_forest_sodium=当前游戏由于 RivaTuner Statistics Server (RTSS) 与 Sodium 不兼容,导致游戏崩溃。\n点击 此处 查看详情。 game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=当前游戏由于你所安装的模组过多,超出了游戏的 ID 限制,无法继续运行。\n请尝试安装 JEID 等修复模组,或删除部分大型模组。 -game.crash.reason.optifine_causes_the_world_to_fail_to_load=当前游戏可能由于 OptiFine 而无法继续运行。\n该问题只在特定 OptiFine 版本中出现,你可以尝试在“版本设置 → 自动安装”中更换 OptiFine 的版本。 +game.crash.reason.optifine_causes_the_world_to_fail_to_load=当前游戏可能由于 OptiFine 而无法继续运行。\n该问题只在特定 OptiFine 版本中出现,你可以尝试在“版本管理 → 自动安装”中更换 OptiFine 的版本。 game.crash.reason.modlauncher_8=当前游戏由于你所使用的 Forge 版本与当前使用的 Java 冲突而崩溃,请尝试更新 Forge 到 36.2.26 或更高版本或换用版本低于 1.8.0.320 的 Java。Liberica JDK 8u312+7 game.crash.reason.no_class_def_found_error=当前游戏由于代码不完整,无法继续运行。\n你的游戏可能缺失了某个模组,或者某些模组文件不完整,或者模组与游戏的版本不匹配。\n你可能需要重新安装游戏和模组,或寻求他人帮助。\n缺失:\n%1$s game.crash.reason.no_such_method_error=当前游戏由于代码不完整,无法继续运行。\n你的游戏可能缺失了某个模组,或者某些模组文件不完整,或者模组与游戏的版本不匹配。\n你可能需要重新安装游戏和模组,或寻求他人帮助。 @@ -564,8 +564,8 @@ 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.corrected=我们已经修复了 Java 虚拟机版本问题。如果你确实希望使用你自定义的 Java 虚拟机,你可以在“(全局/版本特定) 游戏设置 → 高级设置”中往下滑,开启“不检查 JVM 与游戏的兼容性”。 -launch.advice.uncorrected=如果你确实希望使用你自定义的 Java 虚拟机,你可以在“(全局/版本特定) 游戏设置 → 高级设置”中往下滑,开启“不检查 JVM 与游戏的兼容性”。 +launch.advice.corrected=我们已经修复了 Java 虚拟机版本问题。如果你确实希望使用你自定义的 Java 虚拟机,你可以在“(全局/版本特定) 游戏设置 → 高级设置”中往下滑,启用“不检查 JVM 与游戏的兼容性”。 +launch.advice.uncorrected=如果你确实希望使用你自定义的 Java 虚拟机,你可以在“(全局/版本特定) 游戏设置 → 高级设置”中往下滑,启用“不检查 JVM 与游戏的兼容性”。 launch.advice.different_platform=你正在使用 32 位 Java 启动游戏,建议更换至 64 位 Java。 launch.advice.forge2760_liteloader=Forge 14.23.5.2760 与 LiteLoader 不兼容,请更新 Forge 至 14.23.5.2773 或更高版本。 launch.advice.forge28_2_2_optifine=Forge 28.2.2 及更高版本与 OptiFine 不兼容。请降级 Forge 至 28.2.1 或更低版本。 @@ -789,7 +789,7 @@ modrinth.category.folia=Folia mods=模组 mods.add=添加模组 -mods.add.failed=添加模组 %s 失败。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +mods.add.failed=添加模组“%s”失败。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 mods.add.success=成功添加模组 %s。 mods.broken_dependency.title=损坏的前置模组 mods.broken_dependency.desc=该前置模组曾经在该模组仓库上存在过,但现在被删除了。换个下载源试试吧。 @@ -807,13 +807,13 @@ mods.check_updates.target_version=目标版本 mods.check_updates.update=更新 mods.choose_mod=选择模组 mods.curseforge=CurseForge -mods.dependency.embedded=内置的前置模组(已经由作者打包在模组文件中,无需另外下载) -mods.dependency.optional=可选的前置模组(若缺失游戏能够正常运行,但模组功能可能缺失) -mods.dependency.required=必须的前置模组(必须另外下载,缺失可能会导致游戏无法启动) -mods.dependency.tool=前置库(必须另外下载,缺失可能会导致游戏无法启动) -mods.dependency.include=内置的前置模组(已经由作者打包在模组文件中,无需另外下载) -mods.dependency.incompatible=不兼容的模组(同时安装该模组和正在下载的模组会导致游戏无法启动) -mods.dependency.broken=损坏的前置模组(该前置模组曾经在该模组仓库上存在过,但现在被删除了。换个下载源试试吧。) +mods.dependency.embedded=内置的前置模组 (已经由作者打包在模组文件中,无需另外下载) +mods.dependency.optional=可选的前置模组 (若缺失游戏能够正常运行,但模组功能可能缺失) +mods.dependency.required=必须的前置模组 (必须另外下载,缺失可能会导致游戏无法启动) +mods.dependency.tool=前置库 (必须另外下载,缺失可能会导致游戏无法启动) +mods.dependency.include=内置的前置模组 (已经由作者打包在模组文件中,无需另外下载) +mods.dependency.incompatible=不兼容的模组 (同时安装该模组和正在下载的模组会导致游戏无法启动) +mods.dependency.broken=损坏的前置模组 (该前置模组曾经在该模组仓库上存在过,但现在被删除了,换个下载源试试吧) mods.disable=禁用 mods.download=模组下载 mods.download.title=模组下载 - %1s @@ -826,12 +826,12 @@ mods.mcmod.page=MC 百科页面 mods.mcmod.search=MC 百科搜索 mods.modrinth=Modrinth mods.name=名称 -mods.not_modded=你需要先在自动安装页面安装 Fabric、Forge 或 LiteLoader 才能进行模组管理。 +mods.not_modded=你需要先在“自动安装”页面安装 Forge、NeoForge、Fabric、Quilt 或 LiteLoader 才能管理模组。 mods.restore=回退 mods.url=官方页面 mods.update_modpack_mod.warning=更新整合包中的模组可能导致整合包损坏,使整合包无法正常启动。该操作不可逆,确定要更新吗? mods.install=安装到当前版本 -mods.save_as=下载到本地目录 +mods.save_as=下载到本地文件夹 nbt.entries=%s 个条目 nbt.open.failed=打开文件失败 @@ -842,7 +842,7 @@ datapack=数据包 datapack.add=添加数据包 datapack.choose_datapack=选择要导入的数据包压缩包 datapack.extension=数据包 -datapack.title=世界 %s - 数据包 +datapack.title=世界 [%s] - 数据包 web.failed=加载页面失败 web.open_in_browser=是否要在浏览器中打开此链接:\n%s @@ -852,19 +852,19 @@ world=世界 world.add=添加世界 world.datapack=管理数据包 world.datapack.1_13=仅 Minecraft 1.13 及之后的版本支持数据包 -world.description=%s。上一次游戏时间: %s。游戏版本: %s。 +world.description=%s | 上一次游戏时间: %s | 游戏版本: %s world.download=存档下载 world.export=导出此世界 world.export.title=选择该世界的存储位置 world.export.location=保存到 -world.export.wizard=导出世界 %s +world.export.wizard=导出世界“%s” world.extension=世界压缩包 world.game_version=游戏版本 world.import.already_exists=此世界已经存在 world.import.choose=选择要导入的存档压缩包 world.import.failed=无法导入此世界:%s world.import.invalid=无法识别该存档压缩包 -world.info.title=世界 %s - 世界信息 +world.info.title=世界 [%s] - 世界信息 world.info.basic=基本信息 world.info.allow_cheats=允许作弊 world.info.dimension.the_nether=下界 @@ -883,7 +883,7 @@ world.info.player.food_level=饥饿值 world.info.player.game_type=游戏模式 world.info.player.game_type.adventure=冒险 world.info.player.game_type.creative=创造 -world.info.player.game_type.spectator=旁观 +world.info.player.game_type.spectator=旁观者 world.info.player.game_type.survival=生存 world.info.player.health=生命值 world.info.player.last_death_location=上次死亡位置 @@ -898,26 +898,26 @@ world.name=世界名称 world.name.enter=输入世界名称 world.reveal=打开文件夹 world.show_all=显示全部 -world.time=yyyy 年 MM 月 dd 日 HH:mm:ss +world.time=yyyy 年 MM 月 dd 日, HH:mm:ss -profile=游戏目录 +profile=游戏文件夹 profile.already_exists=该名称已存在 -profile.default=当前目录 -profile.home=官方启动器目录 -profile.instance_directory=游戏路径 -profile.instance_directory.choose=选择游戏路径 -profile.manage=游戏目录列表 +profile.default=当前文件夹 +profile.home=官方启动器文件夹 +profile.instance_directory=游戏文件夹路径 +profile.instance_directory.choose=选择游戏文件夹路径 +profile.manage=游戏文件夹列表 profile.name=名称 -profile.new=添加游戏目录 -profile.title=游戏目录 +profile.new=添加游戏文件夹 +profile.title=游戏文件夹 profile.selected=已选中 -profile.use_relative_path=若可能,游戏目录使用相对路径 +profile.use_relative_path=若可能,游戏文件夹使用相对路径 -repositories.custom=自定义 Maven 仓库(%s) -repositories.maven_central=全球(Maven Central) -repositories.tencentcloud_mirror=中国大陆(腾讯云镜像源 Maven 仓库) +repositories.custom=自定义 Maven 仓库 (%s) +repositories.maven_central=全球 (Maven Central) +repositories.tencentcloud_mirror=中国大陆 (腾讯云镜像源 Maven 仓库) repositories.chooser=缺少 JavaFX 运行环境,HMCL 需要 JavaFX 才能正常运行。\n点击“确认”从指定下载源下载 JavaFX 运行时组件并启动 HMCL,点击“取消”退出程序。\n选择下载源: -repositories.chooser.title=选择下载源下载 JavaFX +repositories.chooser.title=选择 JavaFX 下载源 resourcepack=资源包 @@ -939,34 +939,34 @@ selector.custom=自定义 settings=设置 settings.advanced=高级设置 -settings.advanced.modify=修改高级设置 +settings.advanced.modify=编辑高级设置 settings.advanced.title=高级设置 - %s settings.advanced.custom_commands=自定义命令 settings.advanced.custom_commands.hint=自定义命令被调用时将包含如下的环境变量:\n\ - \ - $INST_NAME: 版本名称\n\ - \ - $INST_ID: 版本名称\n\ - \ - $INST_DIR: 版本文件夹\n\ - \ - $INST_MC_DIR: 游戏运行路径\n\ - \ - $INST_JAVA: 游戏运行使用的 Java 路径\n\ - \ - $INST_FORGE: 若安装了 Forge,将会存在本环境变量\n\ - \ - $INST_NEOFORGE: 若安装了 NeoForge,将会存在本环境变量\n\ - \ - $INST_LITELOADER: 若安装了 LiteLoader,将会存在本环境变量\n\ - \ - $INST_OPTIFINE: 若安装了 OptiFine,将会存在本环境变量\n\ - \ - $INST_FABRIC: 若安装了 Fabric,将会存在本环境变量\n\ - \ - $INST_QUILT: 若安装了 Quilt,将会存在本环境变量 + \ · $INST_NAME:版本名称;\n\ + \ · $INST_ID:版本名称;\n\ + \ · $INST_DIR:当前版本运行路径;\n\ + \ · $INST_MC_DIR:当前游戏文件夹路径;\n\ + \ · $INST_JAVA:游戏运行使用的 Java 路径;\n\ + \ · $INST_FORGE:若安装了 Forge,将会存在本环境变量;\n\ + \ · $INST_NEOFORGE:若安装了 NeoForge,将会存在本环境变量;\n\ + \ · $INST_LITELOADER:若安装了 LiteLoader,将会存在本环境变量;\n\ + \ · $INST_OPTIFINE:若安装了 OptiFine,将会存在本环境变量;\n\ + \ · $INST_FABRIC:若安装了 Fabric,将会存在本环境变量;\n\ + \ · $INST_QUILT:若安装了 Quilt,将会存在本环境变量。 settings.advanced.dont_check_game_completeness=不检查游戏完整性 settings.advanced.dont_check_jvm_validity=不检查 JVM 与游戏的兼容性 settings.advanced.dont_patch_natives=不尝试自动替换本地库 settings.advanced.environment_variables=环境变量 -settings.advanced.game_dir.default=默认(.minecraft/) -settings.advanced.game_dir.independent=各版本独立(存放在 .minecraft/versions/<版本名>/,除 assets、libraries 外) +settings.advanced.game_dir.default=默认 (".minecraft/") +settings.advanced.game_dir.independent=各版本独立 (存放在 ".minecraft/versions/<版本名>/",除 assets、libraries 外) settings.advanced.java_permanent_generation_space=内存永久保存区域 settings.advanced.java_permanent_generation_space.prompt=单位 MB settings.advanced.jvm=Java 虚拟机设置 settings.advanced.jvm_args=Java 虚拟机参数 -settings.advanced.jvm_args.prompt=- 若在“Java 虚拟机参数”输入的参数与默认参数相同,则不会添加\n\ -- 在“Java 虚拟机参数”输入任何 GC 参数,默认参数的 G1 参数会禁用\n\ -- 点击下方“不添加默认的 JVM 参数”可在启动游戏时不添加默认参数 +settings.advanced.jvm_args.prompt=\ · 若在“Java 虚拟机参数”输入的参数与默认参数相同,则不会添加;\n\ + \ · 在“Java 虚拟机参数”输入任何 GC 参数,默认参数的 G1 参数会禁用;\n\ + \ · 点击下方“不添加默认的 JVM 参数”可在启动游戏时不添加默认参数。 settings.advanced.launcher_visibility.close=游戏启动后结束启动器 settings.advanced.launcher_visibility.hide=游戏启动后隐藏启动器 settings.advanced.launcher_visibility.hide_and_reopen=隐藏启动器并在游戏结束后重新打开 @@ -974,27 +974,27 @@ settings.advanced.launcher_visibility.keep=保持启动器可见 settings.advanced.launcher_visible=启动器可见性 settings.advanced.minecraft_arguments=游戏参数 settings.advanced.minecraft_arguments.prompt=默认 -settings.advanced.natives_directory=本地库路径(LWJGL) +settings.advanced.natives_directory=本地库路径 (LWJGL) settings.advanced.natives_directory.choose=选择本地库路径 -settings.advanced.natives_directory.custom=自定义(由你提供游戏需要的本地库) -settings.advanced.natives_directory.default=预设(由启动器提供游戏本地库) -settings.advanced.natives_directory.hint=本选项提供给 Apple M1 等未受游戏官方支持的平台来自定义游戏本地库,如果你不知道本选项的含义,请你不要修改本选项,否则会导致游戏无法启动!\n如果你要修改本选项,你需要保证自定义目录下有游戏所需的本地库文件,如 lwjgl.dll(liblwjgl.so), openal.dll(libopenal.so) 等文件。启动器不会帮你补全缺少的本地库文件!\n注意:指定的本地库文件路径建议只包含英文大小写字母,数字,下划线,否则可能会导致启动游戏失败。 +settings.advanced.natives_directory.custom=自定义 (由你提供游戏需要的本地库) +settings.advanced.natives_directory.default=默认 (由启动器提供游戏本地库) +settings.advanced.natives_directory.hint=本选项提供给 Apple M1 等未受游戏官方支持的平台来自定义游戏本地库,如果你不知道本选项的含义,请不要修改本选项,否则会导致游戏无法启动!\n如果你要修改本选项,你需要保证自定义文件夹下有游戏所需的本地库文件,如 lwjgl.dll (liblwjgl.so)、openal.dll (libopenal.so) 等文件。启动器不会帮你补全缺少的本地库文件!\n注意:指定的本地库文件路径建议只包含英文大小写字母、数字和下划线,否则可能会导致启动游戏失败。 settings.advanced.no_jvm_args=不添加默认的 JVM 参数 settings.advanced.precall_command=游戏启动前执行命令 settings.advanced.precall_command.prompt=将在游戏启动前调用 settings.advanced.process_priority=进程优先级 -settings.advanced.process_priority.low=低(节省游戏占用资源,可能会造成游戏卡顿) -settings.advanced.process_priority.below_normal=较低(节省游戏占用资源,可能会造成游戏卡顿) -settings.advanced.process_priority.normal=中(平衡) -settings.advanced.process_priority.above_normal=较高(优先保证游戏运行,但可能会导致其他程序卡顿) -settings.advanced.process_priority.high=高(优先保证游戏运行,但可能会导致其他程序卡顿) +settings.advanced.process_priority.low=低 (节省游戏占用资源,可能会造成游戏卡顿) +settings.advanced.process_priority.below_normal=较低 (节省游戏占用资源,可能会造成游戏卡顿) +settings.advanced.process_priority.normal=中 (平衡) +settings.advanced.process_priority.above_normal=较高 (优先保证游戏运行,但可能会导致其他程序卡顿) +settings.advanced.process_priority.high=高 (优先保证游戏运行,但可能会导致其他程序卡顿) settings.advanced.post_exit_command=游戏结束后执行命令 settings.advanced.post_exit_command.prompt=将在游戏结束后调用 settings.advanced.renderer=渲染器 -settings.advanced.renderer.default=OpenGL(默认) -settings.advanced.renderer.d3d12=DirectX 12(性能与兼容性较差,用于调试) -settings.advanced.renderer.llvmpipe=软渲染器(性能较差,兼容性最好) -settings.advanced.renderer.zink=Vulkan(性能最好,兼容性较差) +settings.advanced.renderer.default=OpenGL (默认) +settings.advanced.renderer.d3d12=DirectX 12 (性能与兼容性较差,用于调试) +settings.advanced.renderer.llvmpipe=软渲染器 (性能较差,兼容性最好) +settings.advanced.renderer.zink=Vulkan (性能最好,兼容性较差) settings.advanced.server_ip=服务器地址 settings.advanced.server_ip.prompt=默认,启动游戏后可以直接进入对应服务器 settings.advanced.use_native_glfw=使用系统 GLFW @@ -1002,7 +1002,7 @@ settings.advanced.use_native_openal=使用系统 OpenAL settings.advanced.workaround=调试选项 settings.advanced.workaround.warning=调试选项仅提供给专业玩家使用。调试选项可能会导致游戏无法启动。除非你知道你在做什么,否则请不要修改这些选项! settings.advanced.wrapper_launcher=包装命令 -settings.advanced.wrapper_launcher.prompt=如填写 optirun 后,启动命令将从 "java ..." 变为 "optirun java ..." +settings.advanced.wrapper_launcher.prompt=如填写“optirun”后,启动命令将从“java ...”变为“optirun java ...” settings.custom=自定义 @@ -1011,29 +1011,29 @@ settings.game.current=游戏 settings.game.dimension=游戏窗口分辨率 settings.game.exploration=浏览 settings.game.fullscreen=全屏 -settings.game.java_directory=Java 路径 +settings.game.java_directory=游戏 Java settings.game.java_directory.auto=自动选择合适的 Java settings.game.java_directory.auto.not_found=没有合适的 Java settings.game.java_directory.bit=%s 位 -settings.game.java_directory.choose=选择 Java 路径 +settings.game.java_directory.choose=选择 Java settings.game.java_directory.invalid=Java 路径不正确 settings.game.java_directory.version=指定 Java 版本 -settings.game.java_directory.template=%s(%s) +settings.game.java_directory.template=%s (%s) settings.game.management=管理 -settings.game.working_directory=版本隔离(建议使用模组时开启“各版本隔离”,改后需移动存档模组等相关游戏文件) -settings.game.working_directory.choose=选择运行路径 -settings.game.working_directory.hint=在“运行路径(版本隔离)”选项中开启“各版本独立”使当前版本独立存放设置、存档、模组等数据,使用模组时建议开启此选项以避免不同版本模组冲突。修改此选项后请自行移动存档等文件。 +settings.game.working_directory=版本隔离 (建议使用模组时选择“各版本独立”,改后需移动存档、模组等相关游戏文件) +settings.game.working_directory.choose=选择运行文件夹 +settings.game.working_directory.hint=在“版本隔离”中选择“各版本独立”使当前版本独立存放设置、存档、模组等数据,使用模组时建议启用此选项以避免不同版本模组冲突。修改此选项后需自行移动存档等文件。 settings.icon=游戏图标 settings.launcher=启动器设置 settings.launcher.appearance=外观 -settings.launcher.common_path.tooltip=启动器将所有游戏资源及依赖库文件放于此集中管理,如果游戏文件夹内有现成的将不会使用公共库文件 +settings.launcher.common_path.tooltip=启动器将所有游戏资源及依赖库文件存放于此集中管理,如果游戏文件夹内有现成的将不会使用公共库文件。 settings.launcher.debug=调试 settings.launcher.download=下载 -settings.launcher.download.threads=并发数 -settings.launcher.download.threads.auto=自动选择并发数 -settings.launcher.download.threads.hint=并发数过大可能导致系统卡顿。你的下载速度会受到宽带运营商、服务器等方面的影响,调大下载并发数不一定能大幅提升总下载速度。 +settings.launcher.download.threads=线程数 +settings.launcher.download.threads.auto=自动选择线程数 +settings.launcher.download.threads.hint=线程数过高可能导致系统卡顿。你的下载速度会受到互联网运营商、下载源服务器等方面的影响,调高下载线程数不一定能大幅提升总下载速度。 settings.launcher.download_source=下载源 settings.launcher.download_source.auto=自动选择下载源 settings.launcher.enable_game_list=在主页内显示版本列表 @@ -1041,9 +1041,9 @@ settings.launcher.font=字体 settings.launcher.general=通用 settings.launcher.language=语言 (重启后生效) settings.launcher.launcher_log.export=导出启动器日志 -settings.launcher.launcher_log.reveal=打开日志目录 +settings.launcher.launcher_log.reveal=打开日志文件夹 settings.launcher.launcher_log.export.failed=无法导出日志 -settings.launcher.launcher_log.export.success=日志已保存到 %s +settings.launcher.launcher_log.export.success=日志已保存到“%s” settings.launcher.log=日志 settings.launcher.log.font=日志字体 settings.launcher.proxy=代理 @@ -1071,19 +1071,19 @@ settings.memory.lower_bound=最低内存分配 settings.memory.used_per_total=设备中已使用 %1$.1f GB / 设备总内存 %2$.1f GB settings.physical_memory=物理内存大小 settings.show_log=查看日志 -settings.skin=现已支持离线账户更换皮肤,你可以到账户页面更改离线账户的皮肤和披风(多人游戏下其他玩家无法看到你的皮肤) +settings.skin=现已支持离线账户更换皮肤,你可以到账户页面更改离线账户的皮肤和披风 (多人游戏下其他玩家无法看到你的皮肤)。 settings.tabs.installers=自动安装 settings.take_effect_after_restart=重启后生效 -settings.type=版本设置类型 -settings.type.global=全局版本设置(未启用游戏特定设置的共用此设定) +settings.type=版本游戏设置类型 +settings.type.global=全局游戏设置 (未启用“版本特定游戏设置”的版本共用此设置) settings.type.global.manage=全局游戏设置 -settings.type.global.edit=编辑全局版本设置 -settings.type.special.enable=启用游戏特定设置(不影响其他游戏版本) -settings.type.special.edit=编辑游戏特定设置 -settings.type.special.edit.hint=当前游戏版本 %s 启用了游戏特定设置,因此本页面选项不对该游戏生效。点击链接前往该游戏版本的游戏特定设置页 +settings.type.global.edit=编辑全局游戏设置 +settings.type.special.enable=启用版本特定游戏设置 (不影响其他游戏版本) +settings.type.special.edit=编辑版本特定游戏设置 +settings.type.special.edit.hint=当前游戏版本“%s”启用了“版本特定游戏设置”,因此本页面选项不对该版本生效。点击链接前往该版本的“游戏设置”页。 sponsor=赞助 -sponsor.bmclapi=国内下载源由 BMCLAPI 提供高速下载服务。BMCLAPI 为公益服务,赞助 BMCLAPI 可以帮助作者更好的提供稳定高速的下载服务,[点击此处查阅详细信息] +sponsor.bmclapi=国内下载源由 BMCLAPI 提供高速下载服务。BMCLAPI 为公益服务,赞助 BMCLAPI 可以帮助作者更好的提供稳定高速的下载服务。[点击此处查阅详细信息] sponsor.hmcl=Hello Minecraft! Launcher 是一个免费、自由、开放源代码的 Minecraft 启动器。[点击此处查阅更多详细信息] system.architecture=架构 @@ -1094,27 +1094,30 @@ unofficial.hint=你正在使用非官方构建的 HMCL,我们无法保证其 update=启动器更新 update.accept=更新 update.changelog=更新日志 -update.channel.dev=测试版 -update.channel.dev.hint=你正在使用测试版。测试版包含一些未在正式版中包含的测试性功能,仅用于体验新功能。\n\ - 测试版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ - 如果你遇到了使用问题,可以在设置的 反馈页面 中进行反馈,或加入反馈页面中提供的 DiscordQQ 群以反馈问题。欢迎关注 B 站账号 huanghongxun 以关注 HMCL 的开发进展。\n\n\ - 点击此处为当前版本隐藏该提示。 -update.channel.dev.title=测试版提示 +update.channel.dev=开发版 +update.channel.dev.hint=你正在使用 HMCL 开发版。开发版包含一些未在稳定版中包含的测试性功能,仅用于体验新功能。\n\ + 开发版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ + \n\ + 如果你使用时遇到了问题,可以通过设置中 反馈页面 提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。\n\ + \n\ + 为当前版本隐藏该提示。 +update.channel.dev.title=开发版提示 update.channel.nightly=预览版 -update.channel.nightly.hint=你正在使用预览版。预览版可能会每天更新一次,包含一些未在正式版和测试版中包含的测试性功能,仅用于体验新功能。\n\ - 测试版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ - 如果你遇到了使用问题,可以在设置的 反馈页面 中进行反馈,或加入反馈页面中提供的 DiscordQQ 群以反馈问题。欢迎关注 B 站账号 huanghongxun 以关注 HMCL 的开发进展。 +update.channel.nightly.hint=你正在使用 HMCL 预览版。预览版更新较为频繁,包含一些未在稳定版和开发版中包含的测试性功能,仅用于体验新功能。\n\ + 预览版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ + \n\ + 如果你使用时遇到了问题,可以通过设置中 反馈页面 提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。 update.channel.nightly.title=预览版提示 -update.channel.stable=推荐版本 +update.channel.stable=稳定版 update.checking=正在检查更新 update.failed=更新失败 update.found=发现更新 update.newest_version=最新版本为:%s update.bubble.title=发现更新:%s update.bubble.subtitle=点击此处进行升级 -update.note=测试版与开发版包含更多的功能以及错误修复,但也可能会包含其他的问题。 +update.note=开发版与预览版包含更多的功能以及错误修复,但也可能会包含其他的问题。 update.latest=当前版本为最新版本 -update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,您可以手动粘贴网址打开页面 +update.no_browser=无法打开浏览器,网址已经复制到剪贴板,你可以手动粘贴网址打开页面。 update.tooltip=更新 version=游戏 @@ -1123,12 +1126,12 @@ version.cannot_read=读取游戏版本失败,无法进行自动安装 version.empty=没有游戏版本 version.empty.add=进入下载页安装游戏 version.empty.launch=没有可启动的游戏,你可以点击左侧边栏内的下载按钮安装游戏 -version.empty.hint=没有已安装的游戏,你可以切换其他游戏目录,或者点击此处进入游戏下载页面 +version.empty.hint=没有已安装的游戏,你可以切换其他游戏文件夹,或者点击此处进入游戏下载页面 version.game.old=远古版 version.game.release=正式版 version.game.releases=正式版 -version.game.snapshot=测试版 -version.game.snapshots=测试版 +version.game.snapshot=快照 +version.game.snapshots=快照 version.launch=启动游戏 version.launch.test=测试游戏 version.switch=切换版本 @@ -1137,24 +1140,24 @@ version.launch_script.failed=生成启动脚本失败 version.launch_script.save=保存启动脚本 version.launch_script.success=启动脚本已生成完毕:%s version.manage=版本列表 -version.manage.clean=清理游戏目录 -version.manage.clean.tooltip=清理 logs, crash-reports -version.manage.duplicate=复制游戏实例 +version.manage.clean=清理游戏文件夹 +version.manage.clean.tooltip=清理“logs”和“crash-reports”文件夹 +version.manage.duplicate=复制游戏版本 version.manage.duplicate.duplicate_save=复制存档 -version.manage.duplicate.prompt=请输入新游戏实例名称 -version.manage.duplicate.confirm=将锁定复制产生的新游戏实例:开启版本隔离、游戏设置并复制该版本产生的文件 -version.manage.manage=游戏管理 -version.manage.manage.title=游戏管理 - %1s +version.manage.duplicate.prompt=请输入新游戏名称 +version.manage.duplicate.confirm=新的游戏版本将复制该版本文件夹 (".minecraft/versions/<版本名>") 下的文件,并带有独立的运行文件夹和设置。 +version.manage.manage=版本管理 +version.manage.manage.title=版本管理 - %1s version.manage.redownload_assets_index=更新游戏资源文件 version.manage.remove=删除该版本 -version.manage.remove.confirm=真的要删除版本 %s 吗?你将无法找回被删除的文件!!! -version.manage.remove.confirm.trash=真的要删除版本 %s 吗?你可以在系统的回收站中恢复文件夹 %s 来找回该版本。 -version.manage.remove.confirm.independent=由于该游戏使用了版本隔离,所以删除该版本将导致该游戏的存档等数据一同被删除!真的要删除版本 %s 吗? +version.manage.remove.confirm=真的要删除版本“%s”吗?你将无法找回被删除的文件!!! +version.manage.remove.confirm.trash=真的要删除版本“%s”吗?你可以在系统的回收站中还原“%s”文件夹来找回该版本。 +version.manage.remove.confirm.independent=由于该游戏启用了“(全局/版本特定) 游戏设置 → 版本隔离 → 各版本独立”选项,所以删除该版本将导致该游戏的存档等数据一同被删除!真的要删除版本“%s”吗? version.manage.remove_assets=删除所有游戏资源文件 version.manage.remove_libraries=删除所有库文件 version.manage.rename=重命名该版本 version.manage.rename.message=请输入要修改的名称 -version.manage.rename.fail=重命名版本失败,可能文件被占用或者名字有特殊字符 +version.manage.rename.fail=重命名版本失败,可能文件被占用或者名字有特殊字符。 version.settings=游戏设置 version.update=更新整合包 From eae26708556ea7c9df6f894cdcfa10ef047c2aff Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 24 Oct 2024 20:03:21 +0800 Subject: [PATCH 053/169] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=9C=A8=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=99=A8=E5=86=85=E4=B8=8A=E4=BC=A0=E5=BE=AE=E8=BD=AF?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E7=9A=AE=E8=82=A4=20(#3375)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * Fix clearCache --- .../hmcl/ui/account/AccountListItem.java | 13 ++--- .../java/org/jackhuang/hmcl/auth/Account.java | 9 ++++ .../hmcl/auth/microsoft/MicrosoftAccount.java | 14 +++++- .../hmcl/auth/microsoft/MicrosoftService.java | 48 +++++++++++++------ .../hmcl/auth/yggdrasil/YggdrasilAccount.java | 10 +++- .../hmcl/auth/yggdrasil/YggdrasilService.java | 4 +- 6 files changed, 68 insertions(+), 30 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java index 22a0b39f9e..6fc255dd9b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java @@ -32,17 +32,14 @@ import org.jackhuang.hmcl.auth.CredentialExpiredException; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; -import org.jackhuang.hmcl.auth.microsoft.MicrosoftAccount; import org.jackhuang.hmcl.auth.offline.OfflineAccount; import org.jackhuang.hmcl.auth.yggdrasil.CompleteGameProfile; import org.jackhuang.hmcl.auth.yggdrasil.TextureType; -import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.setting.Accounts; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.DialogController; -import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; import org.jackhuang.hmcl.util.skin.InvalidSkinException; import org.jackhuang.hmcl.util.skin.NormalizedSkin; @@ -128,7 +125,7 @@ public ObservableBooleanValue canUploadSkin() { .orElse(emptySet()); return uploadableTextures.contains(TextureType.SKIN); }, profile); - } else if (account instanceof OfflineAccount || account instanceof MicrosoftAccount) { + } else if (account instanceof OfflineAccount || account.canUploadSkin()) { return createBooleanBinding(() -> true); } else { return createBooleanBinding(() -> false); @@ -144,11 +141,7 @@ public Task uploadSkin() { Controllers.dialog(new OfflineAccountSkinPane((OfflineAccount) account)); return null; } - if (account instanceof MicrosoftAccount) { - FXUtils.openLink("https://www.minecraft.net/msaprofile/mygames/editskin"); - return null; - } - if (!(account instanceof YggdrasilAccount)) { + if (!account.canUploadSkin()) { return null; } @@ -174,7 +167,7 @@ public Task uploadSkin() { NormalizedSkin skin = new NormalizedSkin(skinImg); String model = skin.isSlim() ? "slim" : ""; LOG.info("Uploading skin [" + selectedFile + "], model [" + model + "]"); - ((YggdrasilAccount) account).uploadSkin(model, selectedFile.toPath()); + account.uploadSkin(skin.isSlim(), selectedFile.toPath()); }) .thenComposeAsync(refreshAsync()) .whenComplete(Schedulers.javafx(), e -> { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java index 8ac98a2a98..3d40c983fe 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java @@ -30,6 +30,7 @@ import org.jackhuang.hmcl.util.ToStringBuilder; import org.jackhuang.hmcl.util.javafx.ObservableHelper; +import java.nio.file.Path; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -69,6 +70,14 @@ public abstract class Account implements Observable { */ public abstract AuthInfo playOffline() throws AuthenticationException; + public boolean canUploadSkin() { + return false; + } + + public void uploadSkin(boolean isSlim, Path file) throws AuthenticationException, UnsupportedOperationException { + throw new UnsupportedOperationException("Unsupported Operation"); + } + public abstract Map toStorage(); public void clearCache() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftAccount.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftAccount.java index 774178a725..ef9401630d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftAccount.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftAccount.java @@ -24,6 +24,7 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService; import org.jackhuang.hmcl.util.javafx.BindingMapping; +import java.nio.file.Path; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -32,7 +33,7 @@ import static java.util.Objects.requireNonNull; import static org.jackhuang.hmcl.util.logging.Logger.LOG; -public class MicrosoftAccount extends OAuthAccount { +public final class MicrosoftAccount extends OAuthAccount { protected final MicrosoftService service; protected UUID characterUUID; @@ -125,6 +126,16 @@ public AuthInfo playOffline() { return session.toAuthInfo(); } + @Override + public boolean canUploadSkin() { + return true; + } + + @Override + public void uploadSkin(boolean isSlim, Path file) throws AuthenticationException, UnsupportedOperationException { + service.uploadSkin(session.getAccessToken(), isSlim, file); + } + @Override public Map toStorage() { return session.toStorage(); @@ -150,6 +161,7 @@ public ObjectBinding>> getTextures() { @Override public void clearCache() { authenticated = false; + service.getProfileRepository().invalidate(characterUUID); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftService.java index 214f062de0..335e074d00 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftService.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftService.java @@ -25,19 +25,18 @@ import org.jackhuang.hmcl.auth.OAuth; import org.jackhuang.hmcl.auth.ServerDisconnectException; import org.jackhuang.hmcl.auth.ServerResponseMalformedException; -import org.jackhuang.hmcl.auth.yggdrasil.CompleteGameProfile; -import org.jackhuang.hmcl.auth.yggdrasil.RemoteAuthenticationException; -import org.jackhuang.hmcl.auth.yggdrasil.Texture; -import org.jackhuang.hmcl.auth.yggdrasil.TextureType; +import org.jackhuang.hmcl.auth.yggdrasil.*; +import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.*; -import org.jackhuang.hmcl.util.io.HttpRequest; -import org.jackhuang.hmcl.util.io.NetworkUtils; -import org.jackhuang.hmcl.util.io.ResponseCodeException; +import org.jackhuang.hmcl.util.io.*; import org.jackhuang.hmcl.util.javafx.ObservableOptionalCache; import java.io.IOException; +import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -261,6 +260,33 @@ public Optional getCompleteGameProfile(UUID uuid) throws Au return Optional.ofNullable(GSON.fromJson(request(NetworkUtils.toURL("https://sessionserver.mojang.com/session/minecraft/profile/" + UUIDTypeAdapter.fromUUID(uuid)), null), CompleteGameProfile.class)); } + public void uploadSkin(String accessToken, boolean isSlim, Path file) throws AuthenticationException, UnsupportedOperationException { + try { + HttpURLConnection con = NetworkUtils.createHttpConnection(NetworkUtils.toURL("https://api.minecraftservices.com/minecraft/profile/skins")); + con.setRequestMethod("POST"); + con.setRequestProperty("Authorization", "Bearer " + accessToken); + con.setDoOutput(true); + try (HttpMultipartRequest request = new HttpMultipartRequest(con)) { + request.param("variant", isSlim ? "slim" : "classic"); + try (InputStream fis = Files.newInputStream(file)) { + request.file("file", FileUtils.getName(file), "image/" + FileUtils.getExtension(file), fis); + } + } + + String response = NetworkUtils.readData(con); + if (StringUtils.isBlank(response)) { + if (con.getResponseCode() / 100 != 2) + throw new ResponseCodeException(con.getURL(), con.getResponseCode()); + } else { + MinecraftErrorResponse profileResponse = GSON.fromJson(response, MinecraftErrorResponse.class); + if (StringUtils.isNotBlank(profileResponse.errorMessage) || con.getResponseCode() / 100 != 2) + throw new AuthenticationException("Failed to upload skin, response code: " + con.getResponseCode() + ", response: " + response); + } + } catch (IOException | JsonParseException e) { + throw new AuthenticationException(e); + } + } + private static String request(URL url, Object payload) throws AuthenticationException { try { if (payload == null) @@ -272,14 +298,6 @@ private static String request(URL url, Object payload) throws AuthenticationExce } } - private static T fromJson(String text, Class typeOfT) throws ServerResponseMalformedException { - try { - return GSON.fromJson(text, typeOfT); - } catch (JsonParseException e) { - throw new ServerResponseMalformedException(text, e); - } - } - public static class XboxAuthorizationException extends AuthenticationException { private final long errorCode; private final String redirect; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java index db0f06fdeb..f253eb40b3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java @@ -203,8 +203,14 @@ public ObjectBinding>> getTextures() { } - public void uploadSkin(String model, Path file) throws AuthenticationException, UnsupportedOperationException { - service.uploadSkin(characterUUID, session.getAccessToken(), model, file); + @Override + public boolean canUploadSkin() { + return true; + } + + @Override + public void uploadSkin(boolean isSlim, Path file) throws AuthenticationException, UnsupportedOperationException { + service.uploadSkin(characterUUID, session.getAccessToken(), isSlim, file); } private static String randomClientToken() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java index 3e3b71e5ee..ef3b695626 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java @@ -148,14 +148,14 @@ public void invalidate(String accessToken, String clientToken) throws Authentica requireEmpty(request(provider.getInvalidationURL(), createRequestWithCredentials(accessToken, clientToken))); } - public void uploadSkin(UUID uuid, String accessToken, String model, Path file) throws AuthenticationException, UnsupportedOperationException { + public void uploadSkin(UUID uuid, String accessToken, boolean isSlim, Path file) throws AuthenticationException, UnsupportedOperationException { try { HttpURLConnection con = NetworkUtils.createHttpConnection(provider.getSkinUploadURL(uuid)); con.setRequestMethod("PUT"); con.setRequestProperty("Authorization", "Bearer " + accessToken); con.setDoOutput(true); try (HttpMultipartRequest request = new HttpMultipartRequest(con)) { - request.param("model", model); + request.param("model", isSlim ? "slim" : ""); try (InputStream fis = Files.newInputStream(file)) { request.file("file", FileUtils.getName(file), "image/" + FileUtils.getExtension(file), fis); } From c9d259d7f186e1d1130e4ece9cb4c0b42494af41 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Thu, 24 Oct 2024 21:32:37 +0800 Subject: [PATCH 054/169] zh_CN post-fix (#3376) - When choosing a download source, the commas in the BMCLAPI item are changed to half-width. - Remove extra line breaks in the home page hint. --- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 e9151298c2..fd2618091c 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -339,7 +339,7 @@ download.failed.empty=[没有可供安装的版本,点击此处返回]\n(你 download.failed.no_code=下载失败: %s download.failed.refresh=[加载版本列表失败,点击此处重试]\n(你可以点击右上角帮助按钮进行求助) download.game=新游戏 -download.provider.bmclapi=BMCLAPI (bangbang93,https://bmclapi2.bangbang93.com) +download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com) download.provider.mojang=官方 (OptiFine 自动安装使用 BMCLAPI 下载源) download.provider.official=尽量使用官方源 (最新,但可能加载慢) download.provider.balanced=选择加载速度快的下载源 (平衡,但可能不是最新) @@ -1097,7 +1097,6 @@ update.changelog=更新日志 update.channel.dev=开发版 update.channel.dev.hint=你正在使用 HMCL 开发版。开发版包含一些未在稳定版中包含的测试性功能,仅用于体验新功能。\n\ 开发版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ - \n\ 如果你使用时遇到了问题,可以通过设置中 反馈页面 提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。\n\ \n\ 为当前版本隐藏该提示。 @@ -1105,7 +1104,6 @@ update.channel.dev.title=开发版提示 update.channel.nightly=预览版 update.channel.nightly.hint=你正在使用 HMCL 预览版。预览版更新较为频繁,包含一些未在稳定版和开发版中包含的测试性功能,仅用于体验新功能。\n\ 预览版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ - \n\ 如果你使用时遇到了问题,可以通过设置中 反馈页面 提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。 update.channel.nightly.title=预览版提示 update.channel.stable=稳定版 From 7d339677e47eb0312d581bc2ca8d3e7c78cac58b Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 24 Oct 2024 21:50:05 +0800 Subject: [PATCH 055/169] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=85=AC=E5=91=8A?= =?UTF-8?q?=E4=B8=AD=E8=B6=85=E9=93=BE=E6=8E=A5=E7=9A=84=E9=A3=8E=E6=A0=BC?= =?UTF-8?q?=20(#3377)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 调整 MessageDialogPane 中超链接的风格 * Fix checkstyle * fix --- HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java | 11 +++++++---- .../main/resources/assets/lang/I18N_zh_CN.properties | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index 41e5d1cd6b..35705f3678 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -28,6 +28,7 @@ import javafx.beans.value.*; import javafx.geometry.Insets; import javafx.geometry.Pos; +import javafx.scene.Cursor; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; @@ -52,7 +53,6 @@ import org.glavo.png.javafx.PNGJavaFXUtils; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.animation.AnimationUtils; -import org.jackhuang.hmcl.ui.construct.JFXHyperlink; import org.jackhuang.hmcl.util.Holder; import org.jackhuang.hmcl.util.ResourceNotFoundError; import org.jackhuang.hmcl.util.StringUtils; @@ -986,8 +986,8 @@ public static List parseSegment(String segment, Consumer hyperlink Element element = (Element) node; if ("a".equals(element.getTagName())) { String href = element.getAttribute("href"); - JFXHyperlink hyperlink = new JFXHyperlink(element.getTextContent()); - hyperlink.setOnAction(e -> { + Text text = new Text(element.getTextContent()); + text.setOnMouseClicked(e -> { String link = href; try { link = new URI(href).toASCIIString(); @@ -995,7 +995,10 @@ public static List parseSegment(String segment, Consumer hyperlink } hyperlinkAction.accept(link); }); - texts.add(hyperlink); + text.setCursor(Cursor.HAND); + text.setUnderline(true); + text.setFill(Color.web("#283593")); + texts.add(text); } else if ("b".equals(element.getTagName())) { Text text = new Text(element.getTextContent()); text.getStyleClass().add("bold"); 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 fd2618091c..62127bcfd0 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1097,14 +1097,14 @@ update.changelog=更新日志 update.channel.dev=开发版 update.channel.dev.hint=你正在使用 HMCL 开发版。开发版包含一些未在稳定版中包含的测试性功能,仅用于体验新功能。\n\ 开发版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ - 如果你使用时遇到了问题,可以通过设置中 反馈页面 提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。\n\ + 如果你使用时遇到了问题,可以通过设置中反馈页面提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。\n\ \n\ 为当前版本隐藏该提示。 update.channel.dev.title=开发版提示 update.channel.nightly=预览版 update.channel.nightly.hint=你正在使用 HMCL 预览版。预览版更新较为频繁,包含一些未在稳定版和开发版中包含的测试性功能,仅用于体验新功能。\n\ 预览版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ - 如果你使用时遇到了问题,可以通过设置中 反馈页面 提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。 + 如果你使用时遇到了问题,可以通过设置中反馈页面提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。 update.channel.nightly.title=预览版提示 update.channel.stable=稳定版 update.checking=正在检查更新 From 0314921728b084d87cf8378f7b486117eef15547 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Fri, 25 Oct 2024 01:28:02 +0800 Subject: [PATCH 056/169] Revise en_US (#3367) * Revise en_US * fix * fix * Revise Co-authored-by: Zkitefly <2573874409@qq.com> * fix some English grammar * another English grammar fixes * fix fix fix... * Revise Co-authored-by: Glavo * fix * fix * fix * fix * fix --------- Co-authored-by: Zkitefly <2573874409@qq.com> Co-authored-by: Glavo --- .../resources/assets/lang/I18N.properties | 1074 +++++++++-------- 1 file changed, 561 insertions(+), 513 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 82fc17d1c5..30077aca46 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -21,62 +21,61 @@ about=About about.copyright=Copyright -about.copyright.statement=Copyright © 2024 huangyuhui. +about.copyright.statement=Copyright © 2024 huangyuhui about.author=Author -about.author.statement=@huanghongxun on bilibili +about.author.statement=bilibili @huanghongxun about.claim=EULA -about.claim.statement=Click on this link for full text. +about.claim.statement=Click this link for full text. about.dependency=Third-party Libraries about.legal=Legal Acknowledgement about.thanks_to=Thanks to -about.thanks_to.bangbang93.statement=For providing BMCLAPI download API, please consider donating. +about.thanks_to.bangbang93.statement=For providing the BMCLAPI download mirror, please consider donating! about.thanks_to.burningtnt.statement=Contribute a lot of technical support to HMCL. about.thanks_to.contributors=All contributors on GitHub -about.thanks_to.contributors.statement=Without the awesome open-source community, Hello Minecraft! Launcher would not make it so far. +about.thanks_to.contributors.statement=Without the awesome open-source community, HMCL would not make it so far. about.thanks_to.gamerteam.statement=For providing the default background image. about.thanks_to.glavo.statement=Responsible for maintaining HMCL. about.thanks_to.zekerzhayard.statement=Contribute a lot of technical support to HMCL. -about.thanks_to.zkitefly.statement=Responsible for maintaining documentation of HMCL. +about.thanks_to.zkitefly.statement=Responsible for maintaining the documentation of HMCL. about.thanks_to.mcbbs=MCBBS (Minecraft Chinese Forum) -about.thanks_to.mcbbs.statement=or providing mcbbs.net download mirror for Mainland China users. -about.thanks_to.mcmod=mcmod.cn -about.thanks_to.mcmod.statement=For providing Chinese translations and wiki for various mods. +about.thanks_to.mcbbs.statement=For providing the mcbbs.net download mirror for Chinese Mainland users. +about.thanks_to.mcmod=MCMod (mcmod.cn) +about.thanks_to.mcmod.statement=For providing the Simplified Chinese translations and wiki for various mods. about.thanks_to.red_lnn.statement=For providing the default background image. -about.thanks_to.shulkersakura.statement=For providing the icon for HMCL +about.thanks_to.shulkersakura.statement=For providing the logo for HMCL. about.thanks_to.users=HMCL User Group Members about.thanks_to.users.statement=Thanks for donations, bug reports, and so on. -about.thanks_to.yushijinhun.statement=For providing authlib-injector related support. +about.thanks_to.yushijinhun.statement=For providing the authlib-injector related support. about.open_source=Open Source about.open_source.statement=GPL v3 (https://github.com/HMCL-dev/HMCL) account=Accounts account.cape=Cape -account.character=character -account.choose=Choose a Character -account.create=Add an account -account.create.microsoft=Add a Microsoft account -account.create.offline=Add an offline account -account.create.authlibInjector=Create an authlib-injector account +account.character=Player +account.choose=Choose a Player +account.create=Add Account +account.create.microsoft=Add a Microsoft Account +account.create.offline=Add an Offline Account +account.create.authlibInjector=Add an authlib-injector Account account.email=Email -account.failed=Account refresh failed -account.failed.character_deleted=The character has already been deleted. -account.failed.connect_authentication_server=Unable to contact authentication servers, your Internet connection may be down. +account.failed=Account refresh failed. +account.failed.character_deleted=The player has already been deleted. +account.failed.connect_authentication_server=Unable to connect to the authentication server, your network connection may be down. account.failed.connect_injector_server=Unable to connect to the authentication server. Please check your network and make sure you entered the correct URL. -account.failed.injector_download_failure=Unable to download authlib-injector. Please check your network, or try switching to a different download mirror. +account.failed.injector_download_failure=Unable to download the authlib-injector. Please check your network, or try switching to a different download source. account.failed.invalid_credentials=Incorrect password or rate limited, please try again later. -account.failed.invalid_password=Invalid password +account.failed.invalid_password=Invalid password. account.failed.invalid_token=Please try logging in again. account.failed.migration=Your account needs to be migrated to a Microsoft account. If you already did, you should re-login to your migrated Microsoft account instead. account.failed.no_character=There are no characters linked to this account. -account.failed.server_disconnected=Cannot access authentication server. You can log in offline or try logging in again.\n\ - If you try multiple times and still fail, please try adding the account again. +account.failed.server_disconnected=Unable to connect to the authentication server. You can log in offline mode or try logging in again.\n\ + If you try several times and still fail, please try adding the account again. account.failed.server_response_malformed=Invalid server response, the authentication server may not be working. account.failed.ssl=An SSL error occurred while connecting to the server. Please try updating your Java. account.failed.wrong_account=You have logged in to the wrong account. -account.hmcl.hint=You need to click on "Login" and complete the process in the opened tab in your browser. -# avoid too long sequence. +account.hmcl.hint=You need to click "Login" and complete the process in the opened browser window. account.injector.add=New Auth Server -account.injector.empty=None (You can click on the plus button on the right to add one) +account.injector.empty=None (You can click "+" to add one) account.injector.http=Warning: This server uses the unsafe HTTP protocol, anyone between your connection will be able to see your credentials in cleartext. account.injector.link.homepage=Homepage account.injector.link.register=Register @@ -84,60 +83,62 @@ account.injector.server=Authentication Server account.injector.server_url=Server URL account.injector.server_name=Server Name account.login=Login -account.login.hint=We will not store your password. +account.login.hint=We never store your password. account.login.skip=Login offline account.login.retry=Retry account.login.refresh=Re-login -account.login.refresh.microsoft.hint=Because the account authorization is invalid, you need to re-add your Microsoft account +account.login.refresh.microsoft.hint=You need to re-add your Microsoft account due to the account authorization is invalid. account.logout=Logout account.register=Register account.manage=Account List -account.copy_uuid=Copy the UUID of the account. +account.copy_uuid=Copy UUID of the Account account.methods=Login Type account.methods.authlib_injector=authlib-injector -account.methods.microsoft=Microsoft Account -account.methods.microsoft.birth=How to update your account birthday +account.methods.microsoft=Microsoft +account.methods.microsoft.birth=How to Update Your Account Birthday account.methods.microsoft.close_page=Microsoft account authorization is now completed.\n\ -\n\ -There are some extra works for us, but you can safely close this tab for now. + \n\ + There are some extra works for us, but you can safely close this tab for now. account.methods.microsoft.deauthorize=Deauthorize -account.methods.microsoft.error.add_family=Since you are not yet 18 years old, an adult must add you to a family in order for you to play Minecraft. -account.methods.microsoft.error.add_family_probably=Please check if the age indicated in your account settings is at least 18 years old. If not and you believe this is an error, you can click on the above link to change it. +account.methods.microsoft.error.add_family=An adult must add you to a family in order for you to play Minecraft due to you are not yet 18 years old. +account.methods.microsoft.error.add_family_probably=Please check if the age indicated in your account settings is at least 18 years old. If not and you believe this is an error, you can click "How to Update Your Account Birthday" to learn how to change it. account.methods.microsoft.error.country_unavailable=Xbox Live is not available in your current country/region. -account.methods.microsoft.error.missing_xbox_account=Your Microsoft account does not have a linked Xbox account yet. Please create one before continuing. -account.methods.microsoft.error.no_character=Your account does not own the Minecraft Java Edition.\nThe game profile may not have been created,\nplease click the link above to create it. -account.methods.microsoft.error.unknown=Failed to log in, error: %d. -account.methods.microsoft.error.wrong_verify_method=Please log in using your account & password on the Microsoft account login page. Please do not use a verification code to log in. +account.methods.microsoft.error.missing_xbox_account=Your Microsoft account does not have a linked Xbox account yet. Please click "Create Profile / Edit Profile Name" to create one before continuing. +account.methods.microsoft.error.no_character=Your account does not own the Minecraft Java Edition.\nThe game profile may not have been created\nplease click "Create Profile / Edit Profile Name" to create it. +account.methods.microsoft.error.unknown=Failed to log in, error code: %d. +account.methods.microsoft.error.wrong_verify_method=Please log in using your password on the Microsoft account login page, and do not use a verification code to log in. account.methods.microsoft.logging_in=Logging in... -account.methods.microsoft.hint=Please click on the "login" button, and copy the code shown here later to finish the login process in the opened browser window.\n\ -\n\ -If the token used to log in to the Microsoft account is leaked, you can click on "Deauthorize" to deauthorize it.\n\ -If you encounter any problems, you can click the help button in the upper right corner for help. -account.methods.microsoft.manual=Your device code is %1$s, please click here to copy. After clicking on the "Login" button, you should finish the login process in the opened browser window. If it did not show, you can go to %2$s manually.\n\ -\n\ -If the token used to log in to the Microsoft account is leaked, you can click on "Deauthorize" to deauthorize it.\n\ -If you encounter any problems, you can click the help button in the upper right corner for help. +account.methods.microsoft.hint=Please click "Login" and copy the code displayed here to complete the login process in the browser window that opens.\n\ + \n\ + If the token used to log in to the Microsoft account is leaked, you can click "Deauthorize" to deauthorize it. +account.methods.microsoft.manual=Your device code is %1$s, please click here to copy.\n\ + \n\ + After clicking "Login", you should complete the login process in the opened browser window. If it did not show, you can navigate to %2$s manually.\n\ + \n\ + If the token used to log in to the Microsoft account is leaked, you can click "Deauthorize" to deauthorize it. account.methods.microsoft.makegameidsettings=Create Profile / Edit Profile Name account.methods.microsoft.profile=Account Profile account.methods.microsoft.purchase=Buy Minecraft account.methods.microsoft.snapshot=You are using an unofficial build of HMCL. Please download the official build for login. account.methods.microsoft.snapshot.website=Official Website account.methods.offline=Offline -account.methods.offline.name.special_characters=Recommended to use letters, numbers and underscores for naming -account.methods.offline.name.invalid=Under normal circumstances, the game username can only contain English characters, numbers and underscores, and the length cannot exceed 16 characters.\n\ - Some legitimate usernames: HuangYu, huang_Yu, Huang_Yu_123;\n\ - Some illegal usernames: Huang Yu, Huang-Yu_%%%, Huang_Yu_hello_world_hello_world.\n\ +account.methods.offline.name.special_characters=Recommended to use English letters, numbers and underscores +account.methods.offline.name.invalid=Generally, game usernames only allow English letters, numbers, and underscores, and cannot exceed 16 characters in length.\n\ + \n\ + \ · Some legitimate usernames: HuangYu, huang_Yu, Huang_Yu_123;\n\ + \ · Some illegal usernames: Huang Yu, Huang-Yu_%%%, Huang_Yu_hello_world_hello_world.\n\ + \n\ If you believe that there is a corresponding mod or plugin on the server side to remove this restriction, you can ignore this warning. account.methods.offline.uuid=UUID -account.methods.offline.uuid.hint=UUID is the unique identifier for the game character in Minecraft. The way that it is generated might vary between different game launchers. Changing it to the one generated by other launchers allows you to keep your items in your offline account inventory.\n\ -\n\ -This option is for advanced users only. We do not recommend modifying this option unless you know what you are doing. -account.methods.offline.uuid.malformed=Invalid Format +account.methods.offline.uuid.hint=UUID is a unique identifier for Minecraft players, and each launcher may generate UUIDs differently. Editing it to the one generated by other launchers allows you to keep your items in your offline account inventory.\n\ + \n\ + This option is for advanced users only. We do not recommend editing this option unless you know what you are doing. +account.methods.offline.uuid.malformed=Invalid format. account.methods.forgot_password=Forgot Password account.missing=No Accounts account.missing.add=Click here to add one. -account.move_to_global=Convert to global account -account.move_to_portable=Convert to portable account +account.move_to_global=Convert to Global Account\nThe account information will be saved in a config file of the user directory. +account.move_to_portable=Convert to Portable Account\nThe account information will be saved in a config file in the same directory as HMCL. account.not_logged_in=Not Logged in account.password=Password account.portable=Portable Account @@ -150,11 +151,11 @@ account.skin.type.csl_api=Blessing Skin account.skin.type.csl_api.location=Address account.skin.type.csl_api.location.hint=CustomSkinAPI URL account.skin.type.little_skin=LittleSkin -account.skin.type.little_skin.hint=You need to create a player with the same name as your offline account on your skin provider website. Your skin will then be your uploaded skin to that site. +account.skin.type.little_skin.hint=You need to create a player with the same player name as your offline account on your skin provider site. Your skin will now be set to the skin assigned to your player on the skin provider site. account.skin.type.local_file=Local Skin File -account.skin.upload=Upload Skin -account.skin.upload.failed=Unable to upload skin -account.skin.invalid_skin=Invalid skin file +account.skin.upload=Upload/Edit Skin +account.skin.upload.failed=Unable to upload skin. +account.skin.invalid_skin=Invalid skin file. account.username=Username archive.author=Author(s) @@ -163,8 +164,8 @@ archive.file.name=File Name archive.version=Version assets.download=Downloading Assets -assets.download_all=Validating assets integrity -assets.index.malformed=Index files of downloaded assets were corrupted. You can try using 'Update Game Assets' in its game instance settings to fix this issue. +assets.download_all=Validating Assets Integrity +assets.index.malformed=Index files of downloaded assets were corrupted. You can resolve this problem by clicking "Manage → Update Game Assets" on the "Edit Instance" page. button.cancel=Cancel button.change_source=Change Download Source @@ -191,7 +192,7 @@ chat=Join Group Chat color.recent=Recommended color.custom=Custom Color crash.NoClassDefFound=Please verify the integrity of this software, or try updating your Java. -crash.user_fault=The launcher crashed due to a corrupted Java or system environment. Please make sure your Java or operating system is installed properly. +crash.user_fault=The launcher crashed due to a corrupted Java or system environment. Please make sure your Java or OS is installed properly. curse.category.0=All @@ -224,8 +225,8 @@ curse.category.6954=Integrated Dynamics curse.category.6484=Create curse.category.6821=Bug Fixes curse.category.6145=Skyblock -curse.category.5190=QoL -curse.category.5191=Utility & QoL +curse.category.5190=QOL +curse.category.5191=Utility & QOL curse.category.5192=FancyMenu curse.category.423=Map and Information curse.category.426=Addons @@ -318,19 +319,19 @@ curse.sort.popularity=Popularity curse.sort.total_downloads=Total Downloads download=Download -download.hint=Install games and modpacks or download mods, resource packs and worlds +download.hint=Install games and modpacks or download mods, resource packs and worlds. download.code.404=File not found on the remote server: %s download.content=Addons -download.curseforge.unavailable=HMCL nightly build does not support access to CurseForge, please use release version or beta version to download. -download.existing=The file cannot be saved because it already exists. You can use 'Save As' to save the file elsewhere. -download.external_link=Open Download Website -download.failed=Failed to download %1$s, response code: %2$d +download.curseforge.unavailable=HMCL Nightly channel build does not support access to CurseForge, please use Release or Beta channel builds to download. +download.existing=The file cannot be saved due to it already exists. You can click "Save As" to save the file elsewhere. +download.external_link=Visit Download Website +download.failed=Failed to download "%1$s", response code: %2$d. download.failed.empty=No versions are available, please click here to go back. -download.failed.no_code=Failed to download %s +download.failed.no_code=Failed to download "%s". download.failed.refresh=Unable to fetch version list. Please click here to retry. -download.game=Game +download.game=New Game download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) -download.provider.mojang=Mojang (OptiFine is provided by BMCLAPI) +download.provider.mojang=Official (OptiFine is provided by BMCLAPI) download.provider.official=From Official Sources download.provider.balanced=From Fastest Available download.provider.mirror=From Mirror @@ -338,258 +339,310 @@ download.java=Downloading Java download.java.override=This Java version already exists, do you want to uninstall and reinstall it? download.javafx=Downloading dependencies for the launcher... download.javafx.notes=We are currently downloading dependencies for HMCL from the Internet.\n\ -\n\ -You can click on 'Change Download Source' to select the download source or\nclick on 'Cancel' to stop and exit.\n\ -Note: If your download speed is too slow, you can try switching to another mirror. -download.javafx.component=Downloading module %s + \n\ + You can click "Change Download Source" to choose download source or\nclick "Cancel" to stop and exit.\n\ + Note: If your download speed is too slow, you can try switching to another mirror. +download.javafx.component=Downloading module "%s" download.javafx.prepare=Preparing to download -exception.access_denied=HMCL is unable to access the file %s, it may be locked by another process.\n\ -\n\ -For Windows users, you can open up 'Resource Monitor' to check if another process is currently using it. If so, you can try again after closing that process.\n\ -If not, please check if your account has enough permissions to access it. -exception.artifact_malformed=Cannot verify the integrity of the downloaded files . -exception.ssl_handshake=Unable to establish SSL connection due to missing SSL certificates in current Java installation. You can try starting HMCL in another Java, then try again. -extension.bat=Windows Batch File(.bat) +exception.access_denied=HMCL is unable to access the file "%s", it may be locked by another process.\n\ + \n\ + For Windows users, you can open "Resource Monitor" to check if another process is currently using it. If so, you can try again after closing that process.\n\ + If not, please check if your account has enough permissions to access it. +exception.artifact_malformed=Cannot verify the integrity of the downloaded files. +exception.ssl_handshake=Unable to establish SSL connection due to missing SSL certificates in current Java installation. You can try opening HMCL in another Java, then try again. +extension.bat=Windows Batch File (.bat) extension.mod=Mod File extension.png=Image File -extension.ps1=Windows PowerShell Script(.ps1) -extension.sh=Shell Script(.sh) +extension.ps1=Windows PowerShell Script (.ps1) +extension.sh=Shell Script (.sh) fatal.javafx.incompatible=Missing JavaFX environment.\n\ -HMCL cannot automatically install JavaFX under Java versions below 11.\n\ -Please update your Java to version 11 or higher. + Hello Minecraft! Launcher cannot automatically install JavaFX on Java <11.\n\ + Please update your Java to version 11 or later. fatal.javafx.incomplete=The JavaFX environment is incomplete.\n\ -Please try replacing your Java or reinstalling OpenJFX. -fatal.javafx.missing=Missing JavaFX environment. Please launch Hello Minecraft! Launcher with a Java which includes OpenJFX. -fatal.config_change_owner_root=You are using the root account to start Hello Minecraft! Launcher, this may cause you to fail to start Hello Minecraft! Launcher with other account in the future.\n\ -Do you still want to continue? -fatal.config_in_temp_dir=You are start Hello Minecraft! Launcher in a temporary directory, your settings and game data may be lost.\n\ -It is recommended to move HMCL to another location and restart it.\n\ -Do you still want to continue? + Please try replacing your Java or reinstalling OpenJFX. +fatal.javafx.missing=Missing JavaFX environment. Please open Hello Minecraft! Launcher with a Java which includes OpenJFX. +fatal.config_change_owner_root=You are using the root account to open Hello Minecraft! Launcher, this may cause you to fail to open HMCL with other account in the future.\n\ + Do you still want to continue? +fatal.config_in_temp_dir=You are opening Hello Minecraft! Launcher in a temporary directory, your settings and game data may be lost.\n\ + It is recommended to move HMCL to another location and reopen it.\n\ + Do you still want to continue? fatal.config_loading_failure=Cannot load configuration files.\n\ -Please make sure that "Hello Minecraft! Launcher" has read and write access to "%s" and the files in it.\n\ -For macOS, try putting HMCL somewhere with permissions other than "Desktop", "Downloads" and "Documents" and try again. -fatal.config_loading_failure.unix=Hello Minecraft! Launcher could not load the profile because the profile was created by user %1$s.\n\ -Please start HMCL with root user (not recommended), or execute the following command in the terminal to change the ownership of the configuration file to the current user:\n%2$s -fatal.mac_app_translocation=Due to the security mechanism of macOS, Hello Minecraft! Launcher is quarantined by the system to the temporary folder.\n\ -Please move Hello Minecraft! Launcher to a different folder before attempting to start, otherwise your settings and game data may be lost after restarting.\n\ -Do you still want to continue? -fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher has been upgraded. Please reopen the launcher. -fatal.apply_update_failure=We are sorry, but Hello Minecraft! Launcher is unable to update autoamtically.\n\ -\n\ -You can update manually by downloading a newer version of the launcher from %s.\n\ -If the problem persists, please consider reporting this to us. + Please make sure that Hello Minecraft! Launcher has read and write access to "%s" and the files in it.\n\ + For macOS, try putting HMCL somewhere with permissions other than "Desktop", "Downloads" and "Documents" and try again. +fatal.config_loading_failure.unix=Hello Minecraft! Launcher could not load the profile due to it was created by user %1$s.\n\ + Please open HMCL as root user (not recommended), or execute the following command in the terminal to change the ownership of the configuration file to the current user:\n%2$s +fatal.mac_app_translocation=Due to macOS security mechanisms, Hello Minecraft! Launcher is isolated to a temporary directory by the OS.\n\ + Please move HMCL to a different directory before attempting to open, otherwise your settings and game data may be lost after restarting.\n\ + Do you still want to continue? +fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher has been upgraded. Please restart the launcher. +fatal.apply_update_failure=We are sorry, but Hello Minecraft! Launcher is unable to update automatically.\n\ + \n\ + You can update manually by downloading a newer launcher version from %s.\n\ + If the problem persists, please consider reporting this to us. fatal.apply_update_need_win7=Hello Minecraft! Launcher cannot automatically update on Windows XP/Vista.\n\ -\n\ -You can update manually by downloading a newer version of the launcher from %s. -fatal.samba=If you launched HMCL from a Samba network drive, some features might not be working. Please try updating your Java or copy and run the launcher in a local folder. -fatal.illegal_char=Your user path contains an illegal character '=', you will not be able to use authlib-injector or change the skin of your offline account. -fatal.unsupported_platform=Minecraft is not yet fully supported for your platform, so you may experience missing functionality,\nor even be unable to launch the game.\n\ - \n\ - If you can't start Minecraft 1.17 and above, you can try switchiong the Renderer to Software in instance settings to use CPU rendering for better compatibility. -# ' -fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher has provided support for Loongson Platform.\n\ -If you encounter problems when playing game, you can click the help button in the upper right corner for help. -fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher has provided support for Apple Silicon platform, using native ARM java to launch games to get a smoother game experience.\nIf you encounter problems in the game, starting the game with Java based on x86-64 architecture may have better compatibility. -fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher has provided native support for the Windows on ARM platform. If you encounter problems when playing game, please try starting the game with Java based on x86 architecture.\n\nIf you are using the Qualcomm platform, you may need to install the OpenGL Compatibility Pack before playing games.\nClick the link to go to the Microsoft Store and install the compatibility pack. + \n\ + You can update manually by downloading a newer launcher version from %s. +fatal.samba=If you opened Hello Minecraft! Launcher from a Samba network drive, some features might not be working. Please try updating your Java or copy and open the launcher in a local directory. +fatal.illegal_char=Your user path contains an illegal character "=", you will not be able to use authlib-injector or change the skin of your offline account. +fatal.unsupported_platform=Minecraft is not yet fully supported for your platform, so you may experience missing functionality, or even be unable to launch the game.\n\ + \n\ + If you cannot launch Minecraft 1.17 and later, you can try switching the "Renderer" to "Software" in "Global/Instance-specific Settings → Advanced Settings" to use CPU rendering for better compatibility. +fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher has provided support for Loongson platform.\n\ + If you encounter problems when playing game, you can visit https://docs.hmcl.net/groups.html for help. +fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher has provided support for Apple silicon platform, using native ARM java to launch games to get a smoother game experience.\n\ + If you encounter problems when playing game, launching the game with Java based on x86-64 architecture may have better compatibility. +fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher has provided native support for the Windows on Arm platform. If you encounter problems when playing game, please try launching the game with Java based on x86 architecture.\n\ + \n\ + If you are using the Qualcomm platform, you may need to install the OpenGL Compatibility Pack before playing games.\n\ + Click the link to navigate to Microsoft Store and install the compatibility pack. feedback=Feedback -feedback.channel=Feedback channel +feedback.channel=Feedback Channel feedback.discord=Discord feedback.discord.statement=Join our Discord community. -feedback.github=GitHub Issue -feedback.github.statement=Creating an issue on GitHub. +feedback.github=GitHub Issues +feedback.github.statement=Submit an issue on GitHub. feedback.qq_group=HMCL User Group -feedback.qq_group.statement=Join HMCL user QQ group. +feedback.qq_group.statement=Welcome to join our user group. file=File folder.config=Configs -folder.game=Game Directory +folder.game=Working Directory folder.logs=Logs folder.mod=Mods folder.resourcepacks=Resource Packs -folder.shaderpacks=Shader packs +folder.shaderpacks=Shader Packs folder.saves=Saves folder.screenshots=Screenshots -game=Game -game.crash.feedback=Please do not share screenshots of this interface with others! If you ask for help from others, please click to export the game crash information in the lower left corner and send the exported file to others for analysis. +game=Games +game.crash.feedback=Please do not share screenshots of this interface with others! If you ask for help from others, please click to export the game crash information in the lower left corner and send the exported file to others for analysis. game.crash.info=Crash Info game.crash.reason=Crash Cause game.crash.reason.analyzing=Analyzing... -game.crash.reason.multiple=Multiple reasons detected:\n\n -game.crash.reason.block=The game crashed due to a block.\n\ -\n\ -You can try removing this block using MCEdit or delete that mod that added it.\n\ -\n\ -Block Type: %1$s\n\ -Location: %2$s -game.crash.reason.bootstrap_failed=The game crashed due to mod %1$s.\n\ -\n\ -You can try deleting or updating it. -game.crash.reason.config=The game crashed because a mod %1$s cannot parse its config file %2$s. -game.crash.reason.debug_crash=The game crashed because you manually triggered it.\n\ -\n\ -So, you probably know why. -game.crash.reason.duplicated_mod=The game cannot launch due to duplicate mods: %1$s.\n\ -\n\ -%2$s\n\ -\n\ -Each mod can only be installed once, please delete the duplicate mod and try again. -game.crash.reason.entity=The game crashed due to an entity.\n\ -\n\ -You can try removing this entity using MCEdit or delete that mod that added it.\n\ -\n\ -Block Type: %1$s\n\ -Location: %2$s -game.crash.reason.modmixin_failure=The current game cannot continue to run because some Mod injection failed.\nThis generally means that the Mod has a bug or is incompatible with the current environment.\nYou can check the log to find the error mod. -game.crash.reason.file_or_content_verification_failed=The current game has a problem because some files or content verification failed.\nPlease try deleting the instance (including Mod) and download it again, or try using a proxy when downloading again. -game.crash.reason.mod_repeat_installation=Because the current game has installed duplicate Mods, each Mod can only appear once. Please delete the duplicate Mods and then restart the game. -game.crash.reason.forge_error=Forge may have provided error information.\nYou can view the log and make corresponding processing according to the log information in the error report.\nIf you do not see the error message, you can view the error report to understand how the error occurred.\n%1$s -game.crash.reason.mod_resolution0=The current game cannot continue to run because of some Mod problems.\nYou can check the log to find the error mod(s). -game.crash.reason.mixin_apply_mod_failed=The current game cannot continue to run because Mixin failed to apply the %1$s mod.\nYou can try deleting or updating the mod to resolve the issue. -game.crash.reason.mod_profile_causes_game_crash=The current game cannot continue to run because of a problem with the Mod configuration file.\nYou can check the log to find the error mod(s) and its configuration file. -game.crash.reason.fabric_reports_an_error_and_gives_a_solution=Forge may have provided error information.\nYou can view the log and make corresponding processing according to the log information in the error report.\nIf you do not see the error message, you can view the error report to understand how the error occurred. -game.crash.reason.java_version_is_too_high=The current game crashed because the Java version is too high to continue running.\nPlease use a lower version of Java in the Java Path tab of global game settings or per-instance game settings, and then start the game.\nIf not, you can download it from java.com (Java8) or BellSoft Liberica Full JRE (Java17) and other distributions to download and install one (restart the launcher after installation). -game.crash.reason.need_jdk11=The current game cannot continue to run due to an inappropriate version of the Java virtual machine. \nYou need to download and install Java 11, and set Java to a version starting with 11 in the global (per-instance) game settings. -game.crash.reason.mod_name=The current game cannot continue to run because of Mod file name problems. \nMod file names should use only English letters (Aa~Zz), numbers (0~9), hyphens (-), underscores (_), and dots (.) in half width. \nPlease go to the mods folder and add all non-compliant Mod file names with one of the above compliant characters. -game.crash.reason.incomplete_forge_installation=The current game cannot continue due to an incomplete installation of Forge / NeoForge. \nPlease reinstall Forge / NeoForge in Instance Settings - Modloaders / OptiFine. -game.crash.reason.fabric_version_0_12=Fabric 0.12 or above are incompatible with currently installed mods. You need to downgrade it to 0.11.7. -game.crash.reason.fabric_warnings=The Fabric modloader warned:\n\ -%1$s -game.crash.reason.file_already_exists=The game crashed because file %1$s already exists.\n\ -\n\ -You can try backing up and delete that file, then relaunch the game. -game.crash.reason.file_changed=The game crashed because it did not pass the integrity checks.\n\ -\n\ -If you modified the Minecraft jar, you will need to rollback the changes, or redownload the game. -game.crash.reason.gl_operation_failure=The game crashed due to some mods, shaders, and resource packs.\n\ -\n\ -Please disable the mods/shaders/resource packs you are using and then try again. -game.crash.reason.graphics_driver=The game crashed due to an issue with your graphics driver.\n\ -\n\ -Please try again after updating your graphics driver to the latest version.\n\ -\n\ -If your computer has a discrete graphics card, you need to check whether the game uses integrated/core graphics. If so, please start the launcher using your discrete graphics card. If the problem persists, you probably should consider getting a new graphics card or a new computer.\n\ -\n\ -If you are using your integrated graphics card, please notice that Minecraft 1.16.5 or older requires Java 1.8.0_51 or older for Intel(R) Core(TM) 3000 processor series or earlier.\n\ -\n\ -Turning on the "Use OpenGL software renderer" option in the instance settings can also solve this problem, but when this option is turned on, the frame rate will be significantly reduced in the case of insufficient CPU performance. So it is only recommended to turn it on for debugging purposes or in case of emergency. -game.crash.reason.macos_failed_to_find_service_port_for_display=The current game cannot continue due to a failure to initialize the OpenGL window on the Apple silicon platform.\nFor this issue, HMCL does not have direct solutions at the moment. Please try opening any browser and going fullscreen, then return to HMCL, launch the game, and quickly return to the browser page before the game window pops up, wait for the game window to appear, and then switch back to the game window. -game.crash.reason.illegal_access_error=The game crashed because of some mod(s).\n\ -\n\ -If you know: %1$s, you can update or delete the mod(s) and then try again. -game.crash.reason.install_mixinbootstrap=The current game cannot continue to run due to missing MixinBootstrap.\nYou can try installing MixinBootstrap to solve the problem. If it crashes after installation, try adding an English "!" in front of the module's filename. in front of the file name of the module to try to solve the problem. -game.crash.reason.optifine_is_not_compatible_with_forge=The current game crashes because OptiFine is incompatible with the current version of Forge.\nPlease go toOn the official website of OptiFine, check whether the Forge version is compatible with OptiFine, and reinstall the game in strict accordance with the corresponding version or change the version in the instance settings - Modloaders / OptiFine.\nAfter testing, too high or too low a Forge version may cause a crash. -game.crash.reason.mod_files_are_decompressed=The current game cannot continue to run because the Mod file has been decompressed.\nPlease put the entire Mod file directly into the Mod folder!\nIf unzipping will cause errors in the game, please delete the unzipped Mod in the Mod folder, and then start the game. -game.crash.reason.shaders_mod=The current game cannot continue to run because both OptiFine and Shaders Mod are installed. \nBecause OptiFine has built-in support for shaders, just remove Shaders Mod. -game.crash.reason.rtss_forest_sodium=The current game crashed because RivaTuner Statistics Server (RTSS) is incompatible with Sodium.\nClick here for more details. -game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=The current game cannot continue to run because you have installed too many Mods, which exceeds the ID limit of the game.\nPlease try installingJEID, or delete some large Mods. -game.crash.reason.night_config_fixes=The current game cannot continue to run due to some problems with Night Config. \nYou can try to install the Night Config Fixes mod, which may help you this problem. \nFor more information, visit the mod's GitHub repository. -game.crash.reason.optifine_causes_the_world_to_fail_to_load=The current game may not continue to run because of OptiFine.\nThis problem only occurs in a specific version of OptiFine. You can try changing the version of OptiFine in instance settings - Modloader / OptiFine. -game.crash.reason.jdk_9=The game cannot run because the Java version is too new for this instance.\n\ -\n\ -You need to download and install Java 8 and select it in the instance settings. -game.crash.reason.jvm_32bit=The game crashed because the current memory allocation exceeds the limit of the 32-bit Java VM.\n\ -\n\ -If your OS is 64-bit, please install and use a 64-bit version of Java. Otherwise, you may need to reinstall a 64-bit OS or get a moderner computer.\n\ -\n\ -Or, you can disable the "Automatically allocate" option and set the maximum memory allocation size to 1024MB or below. -game.crash.reason.loading_crashed_forge=The game crashed due to mod %1$s (%2$s).\n\ -\n\ -You can try deleting or updating it. -game.crash.reason.loading_crashed_fabric=The game crashed due to mod %1$s.\n\ -\n\ -You can try deleting or updating it. -game.crash.reason.mac_jdk_8u261=The game crashed because your current Forge or OptiFine version is not compatible with your Java installation.\n\ -\n\ -Please try updating Forge and OptiFine, or try using Java 8u251 or earlier versions. -game.crash.reason.forge_repeat_installation=The current game cannot continue to run due to a duplicate installation of Forge. This is a known issue\nIt is recommended to upload the log feedback to GitHub so that we can find more clues and fix this question. \nCurrently you can go to the automatic installation to uninstall Forge and reinstall it. -game.crash.reason.optifine_repeat_installation=The current game cannot continue to run due to repeated installation of Optifine. \nPlease delete Optifine under the Mod folder or go to Game Management-Automatic Installation to uninstall Optifine that is automatically installed. +game.crash.reason.multiple=Several reasons detected:\n\n +game.crash.reason.block=The game crashed due to a block in world.\n\ + \n\ + You can try removing this block using MCEdit or delete that mod that added it.\n\ + \n\ + Block Type: %1$s\n\ + Location: %2$s +game.crash.reason.bootstrap_failed=The game crashed due to mod "%1$s".\n\ + \n\ + You can try deleting or updating it. +game.crash.reason.config=The game crashed due to a mod "%1$s" cannot parse its config file "%2$s". +game.crash.reason.debug_crash=The game crashed due to you manually triggered it. So, you probably know why. +game.crash.reason.duplicated_mod=The game cannot continue to run due to duplicate mods "%1$s".\n\ + \n\ + %2$s\n\ + \n\ + Each mod can only be installed once, please delete the duplicate mod and try again. +game.crash.reason.entity=The game crashed due to an entity in world. + \n\ + You can try removing this entity using MCEdit or delete that mod that added it.\n\ + \n\ + Entity Type: %1$s\n\ + Location: %2$s +game.crash.reason.modmixin_failure=The game crashed due to some mod injection failed.\n\ + \n\ + This generally means that the mod has a bug or is incompatible with the current environment.\n\ + \n\ + You can check the log to find the error mod. +game.crash.reason.mod_repeat_installation=The game crashed due to duplicate mods.\n\ + \n\ + Each mod can only be installed once, please delete the duplicate mod and then relaunch the game. +game.crash.reason.forge_error=Forge/NeoForge may have provided error information.\n\ + \n\ + You can view the log and make corresponding processing according to the log information in the error report.\n\ + \n\ + If you do not see the error message, you can view the error report to understand how the error occurred.\n\ + %1$s +game.crash.reason.mod_resolution0=The game crashed due to some mod problems. You can check the log to find the error mod(s). +game.crash.reason.mixin_apply_mod_failed=The game crashed due to mixin failed to apply the "%1$s" mod.\n\ + \n\ + You can try deleting or updating the mod to resolve the problem. +game.crash.reason.java_version_is_too_high=The game crashed due to the Java version is too high to continue running.\n\ + \n\ + Please use an older Java version in "Global/Instance-specific Settings → Java", and then launch the game.\n\ + \n\ + If not, you can download it from java.com (Java 8) or BellSoft Liberica Full JRE (Java 17) and other distributions to download and install one (restart the launcher after installation). +game.crash.reason.need_jdk11=The game crashed due to an inappropriate Java VM version.\n\ + \n\ + You need to download and install Java 11, and set it in "Global/Instance-specific Settings → Java". +game.crash.reason.mod_name=The game crashed due to mod file name problems.\n\ + \n\ + Mod file names should use only English letters (Aa~Zz), numbers (0~9), hyphens (-), underscores (_), and dots (.) in half-width.\n\ + \n\ + Please navigate to the mod directory and add all non-compliant mod file names with one of the above compliant characters. +game.crash.reason.incomplete_forge_installation=The game cannot continue to run due to an incomplete installation of Forge/NeoForge.\n\ + \n\ + Please reinstall Forge/NeoForge in "Edit Instance → Loaders". +game.crash.reason.fabric_version_0_12=Fabric Loader 0.12 or later are incompatible with currently installed mods. You need to downgrade it to 0.11.7. +game.crash.reason.fabric_warnings=The Fabric warned:\n\ + \n\ + %1$s +game.crash.reason.file_already_exists=The game crashed due to file "%1$s" already exists.\n\ + \n\ + You can try backing up and delete that file, then relaunch the game. +game.crash.reason.file_changed=The game crashed due to file "%1$s" already exists.\n\ + \n\ + You can try backing up and delete that file, then relaunch the game. +game.crash.reason.gl_operation_failure=The game crashed due to some mods, shaders, or resource packs.\n\ + \n\ + Please disable the mods, shaders or resource packs you are using and then try again. +game.crash.reason.graphics_driver=The game crashed due to an problem with your graphics driver.\n\ + \n\ + Please try again after updating your graphics driver to the latest version.\n\ + \n\ + If your PC has a discrete graphics card, you need to check whether the game uses integrated/core graphics. If so, please open the launcher using your discrete graphics card. If the problem persists, you probably should consider using a new graphics card or a new PC.\n\ + \n\ + If you are using your integrated graphics card, please notice that Minecraft 1.16.5 or older requires Java 1.8.0_51 or older for Intel(R) Core(TM) 3000 processor series or earlier. +game.crash.reason.macos_failed_to_find_service_port_for_display=The current game cannot continue due to a failure to initialize the OpenGL window on the Apple silicon platform.\n\ + \n\ + For this problem, HMCL does not have direct solutions at the moment. Please try opening any browser and going fullscreen, then return to HMCL, launch the game, and quickly return to the browser page before the game window pops up, wait for the game window to appear, and then switch back to the game window. +game.crash.reason.illegal_access_error=The game crashed due to some mod(s).\n\ + \n\ + If you know this: "%1$s", you can update or delete the mod(s) and then try again. +game.crash.reason.install_mixinbootstrap=The game crashed due to missing MixinBootstrap.\n\ + \n\ + You can try installing MixinBootstrap to resolve the problem. If it crashes after installation, try adding an exclamation mark (!) in front of the file name of this mod. in front of the file name of the mod to try to resolve the problem. +game.crash.reason.optifine_is_not_compatible_with_forge=The game crashes due to OptiFine being incompatible with the currently installed Forge.\n\ + \n\ + Please navigate tothe official website of OptiFine, check whether the Forge version is compatible with OptiFine, and reinstall the instance in strict accordance with the corresponding version, or change the OptiFine version in "Edit Instance → Loaders".\n\ + \n\ + After testing, we believe that too high or too low OptiFine versions may cause crashes. +game.crash.reason.mod_files_are_decompressed=The game crashed due to the mod file has been extracted.\n\ + \n\ + Please put the entire mod file directly into the mod directory!\n\ + \n\ + If extract will cause errors in the game, please delete the extracted mod in the mod directory, and then launch the game. +game.crash.reason.shaders_mod=The game crashed due to both OptiFine and Shaders mod are installed.\n\ + \n\ + Just remove Shaders mod due to OptiFine has built-in support for shaders. +game.crash.reason.rtss_forest_sodium=The game crashed due to RivaTuner Statistics Server (RTSS) is incompatible with Sodium.\n\ + \n\ + Click here for more details. +game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=The game crashed due to you have installed too many mods, which exceeds the ID limit of the game.\n\ + \n\ + Please try installingJEID, or delete some large mods. +game.crash.reason.night_config_fixes=The game crashed due to some problems with Night Config.\n\ + \n\ + You can try to install the Night Config Fixes mod, which may help you this problem.\n\ + \n\ + For more information, visit the GitHub repository of this mod. +game.crash.reason.optifine_causes_the_world_to_fail_to_load=The game may not continue to run due to OptiFine.\n\ + \n\ + This problem only occurs in a specific OptiFine version. You can try changing OptiFine version in "Edit Instance → Loaders". +game.crash.reason.jdk_9=The game crashed due to the Java version is too new for this instance.\n\ + \n\ + You need to download and install Java 8 and choose it in "Global/Instance-specific Settings → Java". +game.crash.reason.jvm_32bit=The game crashed due to the current memory allocation exceeds the limit of the 32-bit Java VM.\n\ + \n\ + If your OS is 64-bit, please install and use a 64-bit Java version. Otherwise, you may need to reinstall a 64-bit OS or get a moderner PC.\n\ + \n\ + Or, you can disable the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory", and set the maximum memory allocation size to 1024 MB or below. +game.crash.reason.loading_crashed_forge=The game crashed due to mod "%1$s" (%2$s).\n\ + \n\ + You can try deleting or updating it. +game.crash.reason.loading_crashed_fabric=The game crashed due to mod "%1$s".\n\ + \n\ + You can try deleting or updating it. +game.crash.reason.mac_jdk_8u261=The game crashed due to your current Forge or OptiFine version is not compatible with your Java installation.\n\ + \n\ + Please try updating Forge and OptiFine, or try using Java 8u251 or earlier versions. +game.crash.reason.forge_repeat_installation=The game crashed due to a duplicate installation of Forge. This is a known problem\n\ + \n\ + It is recommended to upload the log feedback to GitHub so that we can find more clues and resolve this problem.\n\ + \n\ + Currently you can uninstall Forge and reinstall it in "Edit Instance → Loaders". +game.crash.reason.optifine_repeat_installation=The game crashed due to repeated installation of OptiFine.\n\ + \n\ + Please delete OptiFine in the mod directory or uninstall it in "Edit Instance → Loaders". game.crash.reason.memory_exceeded=The game crashed due to too much memory allocated for a small page file.\n\ -\n\ -You can try turning off the automatically allocate memory option in settings, and adjust the value till the game launches.\n\ -You can also try increasing the page file size in system settings. -game.crash.reason.mod=The game crashed due to the mod %1$s.\n\ -\n\ -You may update or delete the mod and then try again. + \n\ + You can try disable the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory", and adjust the value till the game launches.\n\ + \n\ + You can also try increasing the page file size in system settings. +game.crash.reason.mod=The game crashed due to the mod "%1$s".\n\ + \n\ + You may update or delete the mod and then try again. game.crash.reason.mod_resolution=The game crashed due to mod resolution failure.\n\ -\n\ -Fabric provided the following details:\n\ -%1$s + \n\ + Fabric provided the following details:\n\ + \n\ + %1$s game.crash.reason.forgemod_resolution=The game crashed due to mod resolution failure.\n\ -\n\ -Forge provided the following details:\n\ -%1$s -game.crash.reason.forge_found_duplicate_mods=The game cannot continue due to a duplicate mods issue. Forge provides the following information: \n%1$s -game.crash.reason.mod_resolution_collection=The game crashed because the mod version is not compatible.\n\ -\n\ -%1$s requires %2$s.\n\ -\n\ -You need to upgrade or downgrade %3$s before continuing. -game.crash.reason.mod_resolution_conflict=The game crashed because of conflicting mods.\n\ -\n\ -%1$s is incompatible with %2$s. -game.crash.reason.mod_resolution_missing=The game crashed because some dependency mods are not installed.\n\ -\n\ -%1$s requires mod: %2$s.\n\ -\n\ -This means that you have to download and install %2$s first to continue playing. -game.crash.reason.mod_resolution_missing_minecraft=The game crashed because a mod is incompatible with the current Minecraft version.\n\ -\n\ -%1$s requires Minecraft version %2$s.\n\ -\n\ -If you want to play with this version of the mod installed, you should change the instance version.\n\ -Otherwise, you should install a version that is compatible with this Minecraft version. + \n\ + Forge/NeoForge provided the following details:\n\ + %1$s +game.crash.reason.forge_found_duplicate_mods=The game crashed due to a duplicate mods problem. Forge/NeoForge provides the following information:\n\ + %1$s +game.crash.reason.mod_resolution_collection=The game crashed due to the mod version is not compatible.\n\ + \n\ + "%1$s" requires "%2$s".\n\ + \n\ + You need to upgrade or downgrade %3$s before continuing. +game.crash.reason.mod_resolution_conflict=The game crashed due to conflicting mods.\n\ + \n\ + "%1$s" is incompatible with "%2$s". +game.crash.reason.mod_resolution_missing=The game crashed due to some dependency mods are not installed.\n\ + \n\ + "%1$s" requires mod "%2$s".\n\ + \n\ + This means that you have to download and install "%2$s" first to continue playing. +game.crash.reason.mod_resolution_missing_minecraft=The game crashed due to a mod is incompatible with the current Minecraft version.\n\ + \n\ + "%1$s" requires Minecraft version %2$s.\n\ + \n\ + If you want to play with this mod version installed, you should change the game version of your instance.\n\ + \n\ + Otherwise, you should install a version that is compatible with this Minecraft version. game.crash.reason.mod_resolution_mod_version=%1$s (Version: %2$s) game.crash.reason.mod_resolution_mod_version.any=%1$s (Any Version) -game.crash.reason.modlauncher_8=The game crashed because your current Forge version is not compatible with your Java installation, please try updating Forge. -game.crash.reason.no_class_def_found_error=The game cannot run because of incomplete code.\n\ -\n\ -Your game instance is missing %1$s, this might be due to a mod missing, an incompatible mod installed, or some files might be corrupted.\n\ -\n\ -You may need to reinstall the game and all mods or ask someone for help. -game.crash.reason.no_such_method_error=The game cannot run because of incomplete code.\n\ -\n\ -Your game instance might be missing a mod, installed an incompatible mod, or some files might be corrupted.\n\ -\n\ -You may need to reinstall the game and all mods or ask someone for help. -game.crash.reason.opengl_not_supported=The game crashed because OpenGL is not supported by your graphics driver.\n\ -\n\ -If you're streaming the game over the Internet or using a remote desktop environment, please play the game on your local one.\n\ -Or, you can try updating your driver to the latest version and then try again.\n\ -\n\ -If your computer has a discrete graphics card, please make sure the game is actually using it for rendering. If the problem persists, please consider getting a new graphics card or a new computer. -# ' -game.crash.reason.openj9=The game is unable to run on an OpenJ9 VM. Please switch to a Hotspot Java VM in the game settings and relaunch the game. If do not have one, you can download one online. -game.crash.reason.out_of_memory=The game crashed because it ran out of memory.\n\ -\n\ -Maybe because there is not enough memory available, or too many mods installed. You can try fixing it by increasing the allocated memory under the game settings.\n\ -\n\ -If you still encounter these problems, you may need a better computer. -game.crash.reason.resolution_too_high=The game crashed because you are using a resource pack whose texture resolution was too high.\n\ -\n\ -You should switch to a resource pack with lower resolution, or consider buying a better graphics card with more VRAM. -game.crash.reason.processing_of_javaagent_failed=The current game crashed because processing of -javaagent failed.\nIf you add relevant parameters to the Java virtual machine parameters, please check whether they are legal and correct.\nIf you do not add relevant parameters or confirm that they are legal and correct, Please try:\nOpen the control panel -- Clock and region classification (this option is only available if the option is category display, and it will be skipped if not) -- Region -- the upper management tab -- the lower change system regional setting button -- turn off the "Use Unicode UTF-8 to provide global language support" option in the pop-up window, restart the device, and then try to start the game.\nYou can be accessed in Discard or QQ ask for help. -game.crash.reason.stacktrace=The crash reason is unknown. You can view its details by clicking the "Logs" button.\n\ -\n\ -There are some keywords that might contain some Mod Names. You can search them online to figure out the issue yourself.\n\ -\n\ -%s -game.crash.reason.too_old_java=The game crashed because you are using a historical Java VM version.\n\ -\n\ -You need to switch to a newer version (%1$s) of Java in the game settings and then relaunch the game. You can download Java from here. +game.crash.reason.modlauncher_8=The game crashed due to your current Forge version is not compatible with your Java installation, please try updating Forge. +game.crash.reason.no_class_def_found_error=The game cannot continue to run due to incomplete code.\n\ + \n\ + Your game instance is missing %1$s, this might be due to a mod missing, an incompatible mod installed, or some files might be corrupted.\n\ + \n\ + You may need to reinstall the game and all mods or ask someone for help. +game.crash.reason.no_such_method_error=The game cannot continue to run due to incomplete code.\n\ + \n\ + Your game instance might be missing a mod, installed an incompatible mod, or some files might be corrupted.\n\ + \n\ + You may need to reinstall the game and all mods or ask someone for help. +game.crash.reason.opengl_not_supported=The game crashed due to OpenGL is not supported by your graphics driver.\n\ + \n\ + If you are streaming the game over the Internet or using a remote desktop environment, please play the game on your local one.\n\ + \n\ + Or, you can try updating your driver to the latest version and then try again.\n\ + \n\ + If your PC has a discrete graphics card, please make sure the game is actually using it for rendering. If the problem persists, please consider getting a new graphics card or a new PC. +game.crash.reason.openj9=The game is unable to run on an OpenJ9 VM. Please switch to a Java that uses the Hotspot VM in "Global/Instance-specific Settings → Java" and relaunch the game. If do not have one, you can download one online. +game.crash.reason.out_of_memory=The game crashed due to it ran out of memory.\n\ + \n\ + Maybe because there is not enough memory available, or too many mods installed. You can try resolving it by increasing the allocated memory in "Global/Instance-specific Settings → Memory".\n\ + \n\ + If you still encounter these problems, you may need a better PC. +game.crash.reason.resolution_too_high=The game crashed due to the resource pack resolution being too high.\n\ + \n\ + You should switch to a resource pack with lower resolution, or consider buying a better graphics card with more VRAM. +game.crash.reason.stacktrace=The crash reason is unknown. You can view its details by clicking "Logs".\n\ + \n\ + There are some keywords that might contain some mod names. You can search them online to figure out the problem yourself.\n\ + \n\ + %s +game.crash.reason.too_old_java=The game crashed due to you are using an outdated Java VM version.\n\ + \n\ + You need to switch to a newer version (%1$s) of Java in "Global/Instance-specific Settings → Java" and then relaunch the game. You can download Java from here. game.crash.reason.unknown=We are not able to figure out why the game crashed, please refer to the game logs. game.crash.reason.unsatisfied_link_error=Unable to launch Minecraft due to missing libraries: %1$s.\n\ -\n\ -If you have modified native library settings, please make sure these libraries do exist. Or, please try launching again after reverting it back to default.\n\ -If you did not, please check if you have missing dependency mods.\n\ -Otherwise, if you believe this is caused by HMCL, please feedback to us. -game.crash.reason.failed_to_load_a_library=Failed to load a library.\n\ -\n\ -If you have modified native library settings, please make sure these libraries do exist. Or, please try launching again after reverting it back to default.\n\ -If you did not, please check if you have missing dependency mods.\n\ -Otherwise, if you believe this is caused by HMCL, please feed back to us. + \n\ + If you have edited native library path, please make sure these libraries do exist. Or, please try launching again after reverting it to default.\n\ + \n\ + If you did not, please check if you have missing dependency mods.\n\ + \n\ + Otherwise, if you believe this is caused by HMCL, please feedback to us. game.crash.title=Game Crashed game.directory=Game Path game.version=Game Version @@ -610,40 +663,40 @@ install.failed=Installation Failed install.failed.downloading=We are unable to download some required files. install.failed.downloading.detail=Unable to download file: %s install.failed.downloading.timeout=Download timeout when fetching: %s -install.failed.install_online=Unable to identify the provided file. If you are installing a mod, go to the "Manage Mods" page. -install.failed.malformed=The downloaded files are corrupted. You can try fixing this issue by switching to another download source. -install.failed.optifine_conflict=Cannot install both Fabric, OptiFine, and Forge on Minecraft 1.13 or above. -install.failed.optifine_forge_1.17=For Minecraft version 1.17.1 or lower, Forge only supports OptiFine H1 Pre2 or newer. You can install them under the snapshot versions tab. -install.failed.version_mismatch=This library requires the game version %s, but the installed one is %s. +install.failed.install_online=Unable to identify the provided file. If you are installing a mod, navigate to the "Mods" page. +install.failed.malformed=The downloaded files are corrupted. You can try resolving this problem by switching to another download source in "Settings → Download → Download Source". +install.failed.optifine_conflict=Cannot install both OptiFine and Fabric on Minecraft 1.13 or later. +install.failed.optifine_forge_1.17=For Minecraft 1.17.1, Forge only compatible with OptiFine H1 pre2 or later. You can install them by checking "Snapshots" when choosing an OptiFine version in HMCL. +install.failed.version_mismatch=This loader requires the game version %s, but the installed one is %s. install.installer.change_version=%s Incompatible install.installer.choose=Choose Your %s Version install.installer.depend=Requires %s install.installer.fabric=Fabric install.installer.fabric-api=Fabric API -install.installer.fabric-api.warning=Warning: Fabric API is a mod, and will be installed into the mods folder of the game instance. Please do not change the working directory of the game, or the Fabric API will not work. If you do want to change these settings, you should reinstall it. +install.installer.fabric-api.warning=Warning: Fabric API is a mod, and will be installed into the mod directory of the game instance. Please do not change the working directory of the game, or the Fabric API will not work. If you do want to change these settings, you should reinstall it. install.installer.forge=Forge install.installer.neoforge=NeoForge install.installer.game=Minecraft install.installer.incompatible=Incompatible with %s install.installer.install=Install %s -install.installer.install_offline=Install/Update from the Local File -install.installer.install_offline.extension=Forge/OptiFine installer -install.installer.install_offline.tooltip=We support using the local Forge/OptiFine installer. +install.installer.install_offline=Install/Update From Local File +install.installer.install_offline.extension=(Neo)Forge/OptiFine installer +install.installer.install_offline.tooltip=We support using the local (Neo)Forge/OptiFine installer. install.installer.install_online=Online Install -install.installer.install_online.tooltip=We currently support Fabric, Forge, OptiFine, and LiteLoader. +install.installer.install_online.tooltip=We currently support Forge, NeoForge, OptiFine, Fabric, Quilt and LiteLoader. install.installer.liteloader=LiteLoader -install.installer.not_installed=Not Selected +install.installer.not_installed=Do not install install.installer.optifine=OptiFine install.installer.quilt=Quilt install.installer.quilt-api=QSL/QFAPI install.installer.version=%s -install.installer.external_version=%s Installed by external process, which cannot be configured -install.modpack=Install a Modpack -install.new_game=Add a New Instance -install.new_game.already_exists=This instance already exists. Please use another name. +install.installer.external_version=%s (Installed by external process, which cannot be configured) +install.modpack=Install Modpack +install.new_game=Install Instance +install.new_game.already_exists=This instance name already exists. Please use another name. install.new_game.current_game_version=Current Instance Version -install.new_game.malformed=Invalid Name -install.select=Select an operation +install.new_game.malformed=Invalid name. +install.select=Choose operation install.success=Installed successfully. java.add=Add Java @@ -676,49 +729,43 @@ java.reveal=Reveal the Java directory java.uninstall=Uninstall Java java.uninstall.confirm=Are you sure you want to uninstall this Java? This action cannot be undone! -lang=English (US) +lang=English (United States) lang.default=Use System Locales 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 cause unable to launch the game or affect the game experience.\nDo you still want to continue to launch? -launch.advice.java.auto=The current Java Virtual Machine version does not compatible with the instance.\n\ -\n\ -Click on 'Yes' to automatically choose the most compatible Java VM version. Or, you can go to the instance settings to select one yourself. +launch.advice.java.auto=The current Java VM version does not compatible with the instance.\n\nClick "Yes" to automatically choose the most compatible Java VM 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 older versions require Java 7 or earlier. -launch.advice.corrected=We have fixed the Java VM issue. If you still want to use your choice of Java version, you can disable the compatibility checks under launcher game settings. -launch.advice.uncorrected=If you still want to use your choice of Java version, you can disable the compatibility checks under launcher game settings. -launch.advice.different_platform=The 64-bit version of Java is recommended for your device, but you have installed a 32-bit one. +launch.advice.corrected=We have resolved the Java VM problem. If you still want to use your choice of Java version, you can disable the "Do not check Java VM 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 the "Do not check Java VM 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. launch.advice.forge2760_liteloader=Forge version 2760 is not compatible with LiteLoader, please consider upgrading Forge to version 2773 or later. launch.advice.forge28_2_2_optifine=Forge version 28.2.2 or later is not compatible with OptiFine. Please consider downgrading Forge to version 28.2.1 or earlier. -launch.advice.forge37_0_60=Forge versions earlier than 37.0.60 are not compatible with Java 17. Please update Forge to 37.0.60 or higher, or launch the game with Java 16. -launch.advice.java8_1_13=Minecraft 1.13 and later can only be run on Java 8 or later. Please use Java 8 or newer versions. -launch.advice.java8_51_1_13=Minecraft 1.13 may crash on Java 8 versions earlier than 1.8.0_51. Please install the latest version of Java 8. -launch.advice.java9=You cannot launch Minecraft 1.12 or earlier with Java 9 or newer, please use Java 8 instead. -launch.advice.modded_java=Some Mods may not be compatible with higher versions of Java. It is recommended to use Java %s to start Minecraft %s. +launch.advice.forge37_0_60=Forge versions earlier than 37.0.60 are not compatible with Java 17. Please update Forge to 37.0.60 or later, or launch the game with Java 16. +launch.advice.java8_1_13=Minecraft 1.13 and later can only be run on Java 8 or later. Please use Java 8 or later versions. +launch.advice.java8_51_1_13=Minecraft 1.13 may crash on Java 8 versions earlier than 1.8.0_51. Please install the latest Java 8 version. +launch.advice.java9=You cannot launch Minecraft 1.12 or earlier with Java 9 or later, please use Java 8 instead. +launch.advice.modded_java=Some mods may not be compatible with newer versions of Java. It is recommended to use Java %s to launch Minecraft %s. launch.advice.modlauncher8=The Forge version you are using is not compatible with the current Java version, please try updating Forge. -launch.advice.newer_java=You are using the old Java to start the game. It is recommended to update to Java 8, otherwise some mods may cause the game to crash. -launch.advice.not_enough_space=You have allocated a memory size larger than the actual %d MB of memory installed on your computer. You may experience degraded performance, or even be unable to launch the game. +launch.advice.newer_java=You are using the old Java to launch the game. It is recommended to update to Java 8, otherwise some mods may cause the game to crash. +launch.advice.not_enough_space=You have allocated a memory size larger than the actual %d MB of memory installed on your PC. You may experience degraded performance, or even be unable to launch the game. launch.advice.require_newer_java_version=Current game version requires Java %s, but we could not find one. Do you want to download one now? launch.advice.too_large_memory_for_32bit=You have allocated a memory size larger than the memory limitation of the 32-bit Java installation. You may be unable to launch the game. -launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 or below only supports Java 8 for the Linux x86-64 platform, because later versions cannot load 32-bit native libraries like liblwjgl.so\n\ -\n\ -Please download it from java.com, or install OpenJDK 8. -launch.advice.vanilla_x86.translation=Minecraft is not fully supported for your platform, so you may experience missing functionality, or even be unable to launch the game.\nYou can play through the Rosetta translation environment for a full gaming experience. +launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 or before only supports Java 8 for the Linux x86-64 platform, due to the later versions cannot load 32-bit native libraries like liblwjgl.so\n\nPlease download it from java.com, or install OpenJDK 8. +launch.advice.vanilla_x86.translation=Minecraft is not fully supported for your platform, so you may experience missing functionality, or even be unable to launch the game.\nYou can download Java for the x86-64 architecture here for a full gaming experience. launch.advice.unknown=The game cannot be launched due to the following reasons: launch.failed=Failed to launch -launch.failed.cannot_create_jvm=We are unable to create a Java virtual machine. It may be caused by incorrect Java VM arguments. You can try fixing it by removing all arguments you added under instance settings. -launch.failed.creating_process=We are unable to create a new process, please check your Java path. +launch.failed.cannot_create_jvm=We are unable to create a Java VM. It may be caused by incorrect Java VM arguments. You can try resolving it by removing all arguments you added in "Global/Instance-specific Settings → Advanced Settings → Java VM Options". +launch.failed.creating_process=We are unable to create a new process, please check your Java path.\n launch.failed.command_too_long=The command length exceeds the maximum length of a bat script. Please try exporting it as a PowerShell script. -launch.failed.decompressing_natives=Unable to unzip native libraries. -launch.failed.download_library=Unable to download libraries %s. +launch.failed.decompressing_natives=Unable to extract native libraries.\n +launch.failed.download_library=Unable to download libraries "%s". launch.failed.executable_permission=Unable to make the launch script executable. launch.failed.execution_policy=Set Execution Policy launch.failed.execution_policy.failed_to_set=Unable to set execution policy -launch.failed.execution_policy.hint=The current execution policy prevents the execution of PowerShell scripts.\n\ -\n\ -Click on 'OK' to allow the current user to execute PowerShell scripts, or click on 'Cancel' to keep it as it is. +launch.failed.execution_policy.hint=The current execution policy prevents the execution of PowerShell scripts.\n\nClick "OK" to allow the current user to execute PowerShell scripts, or click "Cancel" to keep it as it is. launch.failed.exited_abnormally=Game crashed. Please refer to the crash log for more details. launch.failed.java_version_too_low=The Java version you specified is too low, please reset the Java version. -launch.failed.no_accepted_java=Unable to find a compatible Java version, do you want to start the game with the default Java?\nClick on 'Yes' to start the game with the default Java.\nOr, you can go to the instance settings to select one yourself. +launch.failed.no_accepted_java=Unable to find a compatible Java version, do you want to launch the game with the default Java?\nClick "Yes" to launch the game with the default Java.\nOr, you can navigate to "Global/Instance-specific Settings → Java" to choose one yourself. launch.failed.sigkill=Game was forcibly terminated by the user or system. launch.state.dependencies=Resolving dependencies launch.state.done=Launched @@ -734,20 +781,20 @@ launcher.agreement.accept=Accept launcher.agreement.decline=Decline launcher.agreement.hint=You must agree to the EULA to use this software. launcher.background=Background Image -launcher.background.choose=Choose a Background Image +launcher.background.choose=Choose background image launcher.background.classic=Classic -launcher.background.default=Default (or background.png/jpg/gif, or images under bg folder) +launcher.background.default=Default (Or "background.png/.jpg/.gif" and the images in the "bg" directory) launcher.background.network=From URL launcher.background.translucent=Translucent launcher.cache_directory=Cache Directory launcher.cache_directory.clean=Clear Cache -launcher.cache_directory.choose=Choose the cache directory -launcher.cache_directory.default=Default (%AppData%/.minecraft or ~/.minecraft) +launcher.cache_directory.choose=Choose cache directory +launcher.cache_directory.default=Default ("%APPDATA%/.minecraft" or "~/.minecraft") launcher.cache_directory.disabled=Disabled launcher.cache_directory.invalid=Unable to create cache directory, falling back to default. launcher.contact=Contact Us -launcher.crash=Hello Minecraft! Launcher has encountered a fatal error! Please copy the following log and ask for help on our Discord community, GitHub or Minecraft Forum. -launcher.crash.java_internal_error=Hello Minecraft! Launcher has encountered a fatal error because your Java is broken. Please uninstall your Java, and download a suitable Java here. +launcher.crash=Hello Minecraft! Launcher has encountered a fatal error! Please copy the following log and ask for help on our Discord, QQ group, GitHub or other Minecraft Forum. +launcher.crash.java_internal_error=Hello Minecraft! Launcher has encountered a fatal error due to your Java is broken. Please uninstall your Java, and download a suitable Java here. launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher has encountered a fatal error! Your launcher is outdated. Please update your launcher! launcher.update_java=Please update your Java version. @@ -757,11 +804,11 @@ login.enter_password=Please enter your password. logwindow.show_lines=Show Row Number logwindow.terminate_game=Kill Game Process logwindow.title=Log -logwindow.help=You can go to the HMCL community and find others for help +logwindow.help=You can navigate to the HMCL community and find others for help. logwindow.autoscroll=Auto-scroll logwindow.export_game_crash_logs=Export Crash Logs logwindow.export_dump=Export Game Stack Dump -logwindow.export_dump.no_dependency=Your Java does not contain the dependencies to create the stack dump. Please turn to HMCL QQ group or HMCL Discord for help. +logwindow.export_dump.no_dependency=Your Java does not contain the dependencies to create the stack dump. Please join our Discord or QQ group for help. main_page=Home @@ -778,30 +825,30 @@ message.success=Operation completed successfully message.unknown=Unknown message.warning=Warning -modpack=Modpack -modpack.choose=Select a modpack -modpack.choose.local=Import from local file -modpack.choose.local.detail=You can drag the modpack file here -modpack.choose.remote=Download from URL -modpack.choose.remote.detail=A direct download link to the remote modpack file is required -modpack.choose.repository=Download a modpack from Curseforge or Modrinth -modpack.choose.repository.detail=Remember to go back to this page and drop the modpack file here after the modpack is downloaded +modpack=Modpacks +modpack.choose=Choose Modpack +modpack.choose.local=Import From Local File +modpack.choose.local.detail=You can drag the modpack file here. +modpack.choose.remote=Download From URL +modpack.choose.remote.detail=A direct download link to the remote modpack file is required. +modpack.choose.repository=Download Modpack From CurseForge or Modrinth +modpack.choose.repository.detail=Remember to go back to this page and drop the modpack file here after the modpack is downloaded. modpack.choose.remote.tooltip=Please enter your modpack URL modpack.completion=Downloading dependencies modpack.desc=Describe your modpack, including an introduction and probably some changelog. Markdown and images from URL are currently supported. modpack.description=Modpack Description modpack.download=Download Modpacks modpack.enter_name=Enter a name for this modpack. -modpack.export=Export the Modpack +modpack.export=Export as Modpack modpack.export.as=Export Modpack As... modpack.file_api=Modpack URL Prefix modpack.files.blueprints=BuildCraft Blueprints modpack.files.config=Mod Configs modpack.files.dumps=NEI Debug Output File modpack.files.hmclversion_cfg=Launcher Configuration File -modpack.files.liteconfig=Mod Configuration File +modpack.files.liteconfig=LiteLoader Related Files modpack.files.mods=Mods -modpack.files.mods.voxelmods=VoxelMods options +modpack.files.mods.voxelmods=VoxelMods Options modpack.files.options_txt=Minecraft Options File modpack.files.optionsshaders_txt=Shaders Settings File modpack.files.resourcepacks=Resource/Texture Packs @@ -810,11 +857,11 @@ modpack.files.scripts=MineTweaker Configuration File modpack.files.servers_dat=Server List File modpack.install=Install Modpack %s modpack.installing=Installing Modpack -modpack.introduction=CurseForge, Modrinth, MultiMC, and MCBBS modpacks are currently supported. +modpack.introduction=Curse, Modrinth, MultiMC, and MCBBS modpacks are currently supported. modpack.invalid=Invalid modpack, you can try downloading it again. modpack.mismatched_type=Modpack type mismatched, the current instance is a(an) %s type, but the provided one is %s type. modpack.name=Modpack Name -modpack.not_a_valid_name=Invalid Modpack Name +modpack.not_a_valid_name=Invalid modpack name. modpack.origin=Source modpack.origin.url=Official Website modpack.origin.mcbbs=MCBBS @@ -823,35 +870,33 @@ modpack.scan=Parsing Modpack Index modpack.task.install=Import Modpack modpack.task.install.error=Unable to identify this modpack. We currently only support Curse, Modrinth, MultiMC, and MCBBS modpacks. modpack.type.curse=Curse -modpack.type.curse.tolerable_error=Unable to download dependencies, you can try continuing to download by launching this game instance. -modpack.type.curse.error=Unable to download dependencies, please try again or use a proxy connection. -modpack.type.curse.not_found=Some dependencies are no longer available, please try installing a newer version of the modpack. -modpack.type.manual.warning=The modpack is manually packaged by the publisher, which may already contain a launcher. It is recommended to try unzipping the modpack and running the game with its own launcher. HMCL can still import it, with no guarantee of its usability, still continue? -modpack.type.mcbbs=MCBBS Type +modpack.type.curse.error=Unable to download dependencies, please try again or use a proxy server. +modpack.type.curse.not_found=Some dependencies are no longer available, please try installing a newer modpack version. +modpack.type.manual.warning=The modpack is manually packaged by the publisher, which may already contain a launcher. It is recommended to try extracting the modpack and running the game with its own launcher. HMCL can still import it, with no guarantee of its usability, still continue? +modpack.type.mcbbs=MCBBS modpack.type.mcbbs.export=Can be imported by Hello Minecraft! Launcher modpack.type.modrinth=Modrinth modpack.type.multimc=MultiMC modpack.type.multimc.export=Can be imported by Hello Minecraft! Launcher and MultiMC -modpack.type.server=Auto-Update Modpack from Server +modpack.type.server=Auto-Update Modpack From Server modpack.type.server.export=Allows server owner to update the game instance remotely -modpack.type.server.malformed=Invalid modpack manifest, please refer to the modpack maker to fix this issue. +modpack.type.server.malformed=Invalid modpack manifest, please refer to the modpack maker to resolving this problem. modpack.unsupported=Unsupported modpack format modpack.update=Updating modpack modpack.wizard=Modpack Export Guide modpack.wizard.step.1=Basic Settings modpack.wizard.step.1.title=Some basic informations for the modpack. -modpack.wizard.step.2=Select Files -modpack.wizard.step.2.title=Select files you wanted to add to the modpack. +modpack.wizard.step.2=Choose Files +modpack.wizard.step.2.title=Choose files you wanted to add to the modpack. modpack.wizard.step.3=Modpack Type -modpack.wizard.step.3.title=Choose the modpack type you wanted to export as. +modpack.wizard.step.3.title=Choose modpack type you wanted to export as. modpack.wizard.step.initialization.exported_version=Game version to export -modpack.wizard.step.initialization.force_update=Force updating the modpack to the latest version (you'll need a file-hosting server) -# ' +modpack.wizard.step.initialization.force_update=Force updating the modpack to the latest version (you will need a file-hosting server) modpack.wizard.step.initialization.include_launcher=Include the launcher modpack.wizard.step.initialization.save=Export to... -modpack.wizard.step.initialization.warning=Before making a modpack, please make sure the game launches normally, and Minecraft is a release version instead of a snapshot version. The launcher will save your download settings.\n\ -\n\ -Keep in mind that you are not allowed to add mods and resource packs that are explicitly said not to be distributed or put in a modpack. +modpack.wizard.step.initialization.warning=Before making a modpack, please make sure the game launches normally, and Minecraft is a release version instead of a snapshot. The launcher will save your download settings.\n\ + \n\ + Keep in mind that you are not allowed to add mods and resource packs that are explicitly said not to be distributed or put in a modpack. modpack.wizard.step.initialization.server=Click here for more tutorials for making a server modpack that can be automatically updated. modrinth.category.adventure=Adventure @@ -924,11 +969,11 @@ modrinth.category.256x=256x modrinth.category.512x+=512x+ mods=Mods -mods.add=Add Mods +mods.add=Add Mod mods.add.failed=Failed to add mod %s. mods.add.success=%s was added successfully. mods.broken_dependency.title=Broken dependency -mods.broken_dependency.desc=This dependency existed before. However, it doesn't exist now. Try using another download source. +mods.broken_dependency.desc=This dependency existed before, but it does not exist now. Try using another download source. mods.category=Category mods.channel.alpha=Alpha mods.channel.beta=Beta @@ -941,31 +986,31 @@ mods.check_updates.file=File mods.check_updates.source=Source mods.check_updates.target_version=Target Version mods.check_updates.update=Update -mods.choose_mod=Choose a mod +mods.choose_mod=Choose mod mods.curseforge=CurseForge -mods.dependency.embedded=built-in pre-mod (already packaged in the mod file by the author, no need to download separately) -mods.dependency.optional=optional pre-mod (if the game is missing, but mod functionality may be missing) -mods.dependency.required=required pre-mod (must be downloaded separately, missing may cause the game to fail to launch) -mods.dependency.tool=precursor library (must be downloaded separately, missing may cause the game to fail to launch) -mods.dependency.include=built-in pre-mod (already packaged in the mod file by the author, no need to download separately) -mods.dependency.incompatible=incompatible mod (installing both the mod and the mod being downloaded will cause the game to fail to launch) -mods.dependency.broken=Broken pre-mod (This premod used to exist on the mod repository, but is now deleted.) Try a different download source. +mods.dependency.embedded=Built-in Pre-mod (Already packaged in the mod file by the author, no need to download separately) +mods.dependency.optional=Optional Pre-mod (If missing, the game will run normally, but the mod features may be missing) +mods.dependency.required=Required Pre-mod (Must be downloaded separately, missing may cause the game to fail to launch) +mods.dependency.tool=Required Library (Must be downloaded separately, missing may cause the game to fail to launch) +mods.dependency.include=Built-in Pre-mod (Already packaged in the mod file by the author, no need to download separately) +mods.dependency.incompatible=Incompatible Mod (Installing these mods at the same time will cause the game to fail to launch) +mods.dependency.broken=Broken Pre-mod (This mod existed before, but it does not exist now, try using another download source.) mods.disable=Disable mods.download=Mod Download mods.download.title=Mod Download - %1s mods.download.recommend=Recommended Mod Version - Minecraft %1s mods.enable=Enable -mods.manage=Manage Mods +mods.manage=Mods mods.mcbbs=MCBBS -mods.mcmod=MCMOD -mods.mcmod.page=MCMOD Page -mods.mcmod.search=Search in MCMOD +mods.mcmod=MCMod +mods.mcmod.page=MCMod Page +mods.mcmod.search=Search in MCMod mods.modrinth=Modrinth mods.name=Name -mods.not_modded=You must install a mod loader (Fabric, Forge, Quilt or LiteLoader) first to manage your mods! -mods.restore=Rollback +mods.not_modded=You must install a mod loader (Forge, NeoForge, Fabric, Quilt or LiteLoader) first to manage your mods! +mods.restore=Restore mods.url=Official Page -mods.update_modpack_mod.warning=Updating mods in a modpack can lead to irreparable results, possibly corrupting the modpack so that it cannot start. Are you sure you want to update? +mods.update_modpack_mod.warning=Updating mods in a modpack can lead to irreparable results, possibly corrupting the modpack so that it cannot launch. Are you sure you want to update? mods.install=Install mods.save_as=Save As @@ -975,32 +1020,32 @@ nbt.save.failed=Fail to save file nbt.title=View File - %s datapack=Datapacks -datapack.add=Install datapack -datapack.choose_datapack=Select a datapack to import +datapack.add=Install Datapack +datapack.choose_datapack=Choose datapack to import datapack.extension=Datapack -datapack.title=World %s - Datapacks +datapack.title=World [%s] - Datapacks web.failed=Page loading failed web.open_in_browser=Do you want to open this address in a browser:\n%s web.view_in_browser=View in browser world=Worlds -world.add=Add a World (.zip) +world.add=Add World world.datapack=Manage Datapacks world.datapack.1_13=Only Minecraft 1.13 or later supports datapacks. -world.description=%s. Last played on %s. Game Version: %s. -world.download=Download a World +world.description=%s | Last played on %s | Game Version: %s +world.download=Download World world.export=Export the World -world.export.title=Select a directory for this exported world +world.export.title=Choose directory for this exported world world.export.location=Save As -world.export.wizard=Export World %s +world.export.wizard=Export World "%s" world.extension=World Archive world.game_version=Game Version world.import.already_exists=This world already exists. -world.import.choose=Select the save archive you want to import +world.import.choose=Choose world archive you want to import world.import.failed=Failed to import this world: %s -world.import.invalid=Unable to parse the save. -world.info.title=World %s - Information +world.import.invalid=Unable to import the save. +world.info.title=World [%s] - Information world.info.basic=Basic Information world.info.allow_cheats=Allow Cheats world.info.dimension.the_nether=The Nether @@ -1029,41 +1074,41 @@ world.info.player.xp_level=Experience Level world.info.random_seed=Seed world.info.time=Game Time world.info.time.format=%s days -world.manage=Worlds / Datapacks +world.manage=Worlds world.name=World Name world.name.enter=Enter the world name world.reveal=Reveal in Explorer world.show_all=Show All -world.time=EEE, MMM d, yyyy HH\:mm\:ss +world.time=h\:mm\:ss a, EEE, MMM d yyyy profile=Game Directories profile.already_exists=This name already exists, please use a different name. -profile.default=Current Directory -profile.home=Vanilla Launcher Directory -profile.instance_directory=Instance Directory -profile.instance_directory.choose=Select an instance directory +profile.default=Current +profile.home=Minecraft Launcher +profile.instance_directory=Game Directory +profile.instance_directory.choose=Choose game directory profile.manage=Instance Directory List profile.name=Name profile.new=New Directory profile.title=Game Directories profile.selected=Selected -profile.use_relative_path=Use relative path for game path if possible +profile.use_relative_path=Use relative path for game directory if possible repositories.custom=Custom Maven Repository (%s) repositories.maven_central=Universal (Maven Central) repositories.tencentcloud_mirror=Mainland China Mirror (Tencent Cloud Maven Repository) repositories.chooser=HMCL requires JavaFX to work.\n\ -\n\ -Please click on 'OK' to download JavaFX from the specified repository, or click on 'Cancel' to exit.\n\ -\n\ -Repositories: -repositories.chooser.title=Select a download source to download JavaFX from + \n\ + Please click "OK" to download JavaFX from the specified repository, or click "Cancel" to exit.\n\ + \n\ + Repositories: +repositories.chooser.title=Choose download source for JavaFX resourcepack=Resource Packs search=Search -search.hint.chinese=Search queries support both Chinese and English -search.hint.english=Only English is supported +search.hint.chinese=Supports Chinese and English +search.hint.english=Supports English only search.enter=Enter text here search.sort=Sort By search.first_page=First @@ -1073,56 +1118,56 @@ search.last_page=Last search.page_n=%d / %s selector.choose=Choose -selector.choose_file=Select a file +selector.choose_file=Choose file selector.custom=Custom settings=Settings settings.advanced=Advanced Settings -settings.advanced.modify=Modify Advanced Settings +settings.advanced.modify=Edit Advanced Settings settings.advanced.title=Advanced Settings - %s settings.advanced.custom_commands=Custom Commands settings.advanced.custom_commands.hint=The following environment variables are provided:\n\ - - $INST_NAME: version name\n\ - - $INST_ID: version id\n\ - - $INST_DIR: absolute path of the version\n\ - - $INST_MC_DIR: absolute path of minecraft\n\ - - $INST_JAVA: java binary used for launch\n\ - - $INST_FORGE: set if Forge installed\n\ - - $INST_NEOFORGE: set if NeoForge installed\n\ - - $INST_LITELOADER: set if LiteLoader installed\n\ - - $INST_OPTIFINE: set if OptiFine installed\n\ - - $INST_FABRIC: set if Fabric installed\n\ - - $INST_QUILT: set if Quilt installed + \ · $INST_NAME: instance name.\n\ + \ · $INST_ID: instance name.\n\ + \ · $INST_DIR: absolute path of the instance working directory.\n\ + \ · $INST_MC_DIR: absolute path of the game directory.\n\ + \ · $INST_JAVA: java binary used for launch.\n\ + \ · $INST_FORGE: set if Forge installed.\n\ + \ · $INST_NEOFORGE: set if NeoForge installed.\n\ + \ · $INST_LITELOADER: set if LiteLoader installed.\n\ + \ · $INST_OPTIFINE: set if OptiFine installed.\n\ + \ · $INST_FABRIC: set if Fabric installed.\n\ + \ · $INST_QUILT: set if Quilt installed. settings.advanced.dont_check_game_completeness=Do not check game integrity -settings.advanced.dont_check_jvm_validity=Do not check JVM compatibility +settings.advanced.dont_check_jvm_validity=Do not check Java VM compatibility settings.advanced.dont_patch_natives=Do not attempt to automatically replace native libraries settings.advanced.environment_variables=Environment Variables -settings.advanced.game_dir.default=Default (.minecraft/) -settings.advanced.game_dir.independent=Isolated (.minecraft/versions//, except for assets and libraries) +settings.advanced.game_dir.default=Default (".minecraft/") +settings.advanced.game_dir.independent=Isolated (".minecraft/versions//", except for assets and libraries) settings.advanced.java_permanent_generation_space=PermGen Space settings.advanced.java_permanent_generation_space.prompt=in MB -settings.advanced.jvm=Java Virtual Machine options -settings.advanced.jvm_args=Java VM arguments -settings.advanced.jvm_args.prompt=- If the parameter entered in "Java Virtual Machine Parameters" is the same as the\ndefault parameter,it will not be added\n\ -- Enter any GC parameters in "Java Virtual Machine Parameters",\nthe G1 parameter of the\ndefault parameter will be disabled\n\ -- Click "Don't add default JVM parameters" below to start the game without adding\ndefault parameters -settings.advanced.launcher_visibility.close=Close the launcher after the game launches. -settings.advanced.launcher_visibility.hide=Hide the launcher after the game launches. -settings.advanced.launcher_visibility.hide_and_reopen=Hide the launcher and reopen it when the game closes. -settings.advanced.launcher_visibility.keep=Keep the launcher visible. +settings.advanced.jvm=Java VM Options +settings.advanced.jvm_args=Java VM Arguments +settings.advanced.jvm_args.prompt=\ · If the arguments entered in "Java VM arguments" is the same as the default arguments, it will not be added.\n\ + \ · Enter any GC arguments in "Java VM arguments", the G1 argument of the default arguments will be disabled.\n\ + \ · Enable "Do not add default Java VM arguments" to launch the game without adding default arguments. +settings.advanced.launcher_visibility.close=Close the launcher after the game launches +settings.advanced.launcher_visibility.hide=Hide the launcher after the game launches +settings.advanced.launcher_visibility.hide_and_reopen=Hide the launcher and show it when the game closes +settings.advanced.launcher_visibility.keep=Keep the launcher visible settings.advanced.launcher_visible=Launcher Visibility settings.advanced.minecraft_arguments=Launch Arguments settings.advanced.minecraft_arguments.prompt=Default settings.advanced.natives_directory=Native Library Path -settings.advanced.natives_directory.choose=Select where your desired native library is located +settings.advanced.natives_directory.choose=Choose the location of the desired native library settings.advanced.natives_directory.custom=Custom settings.advanced.natives_directory.default=Default -settings.advanced.natives_directory.hint=This option is intended only for users of Apple M1 or other not officially supported platforms. Please do not modify this option unless you know what you are doing.\n\ -\n\ -Before proceeding, please make sure all libraries (e.g. lwjgl.dll, libopenal.so) are provided in your desired directory.\n\ -Note: It is recommended to use a fully English character path for the specified local library file, otherwise it may lead to game launch failure. -settings.advanced.no_jvm_args=Do not add default JVM arguments +settings.advanced.natives_directory.hint=This option is intended only for users of Apple M1 or other not officially supported platforms. Please do not edit this option unless you know what you are doing.\n\ + \n\ + Before proceeding, please make sure all libraries (e.g. lwjgl.dll, libopenal.so) are provided in your desired directory.\n\ + Note: It is recommended to use a fully English letters path for the specified local library file, otherwise it may lead to game launch failure. +settings.advanced.no_jvm_args=Do not add default Java VM arguments settings.advanced.precall_command=Pre-launch Command settings.advanced.precall_command.prompt=Commands to execute before the game launches settings.advanced.process_priority=Process Priority @@ -1136,75 +1181,74 @@ settings.advanced.post_exit_command.prompt=Commands to execute after the game ex settings.advanced.renderer=Renderer settings.advanced.renderer.default=OpenGL (Default) settings.advanced.renderer.d3d12=DirectX 12 (Poor performance and compatibility) -settings.advanced.renderer.llvmpipe=Software (Poor efficiency and best compatibility) +settings.advanced.renderer.llvmpipe=Software (Poor performance and best compatibility) settings.advanced.renderer.zink=Vulkan (Best performance and poor compatibility) settings.advanced.server_ip=Server Address -settings.advanced.server_ip.prompt=Join automatically after launching the game. +settings.advanced.server_ip.prompt=Automatically join after launching the game settings.advanced.use_native_glfw=[Linux Only] Use system GLFW settings.advanced.use_native_openal=[Linux Only] Use system OpenAL -settings.advanced.workaround=Workarounds -settings.advanced.workaround.warning=Workaround options are intended only for expert users. Tweaking with these options may crash the game. Unless you know what you are doing, please do not modify these options. +settings.advanced.workaround=Workaround +settings.advanced.workaround.warning=Workaround options are intended only for advanced users. Tweaking with these options may crash the game. Unless you know what you are doing, please do not edit these options. settings.advanced.wrapper_launcher=Wrapper Command -settings.advanced.wrapper_launcher.prompt=Allows launching using an extra wrapper program like 'optirun' on Linux. +settings.advanced.wrapper_launcher.prompt=Allows launching using an extra wrapper program like "optirun" on Linux settings.custom=Custom -settings.game=Game Settings +settings.game=Settings settings.game.current=Game settings.game.dimension=Resolution settings.game.exploration=Explore settings.game.fullscreen=Fullscreen -settings.game.java_directory=Java Path -settings.game.java_directory.auto=Automatically Select +settings.game.java_directory=Java +settings.game.java_directory.auto=Automatically Choose settings.game.java_directory.auto.not_found=No suitable Java version was installed. settings.game.java_directory.bit=%s bit -settings.game.java_directory.choose=Select Java path. -settings.game.java_directory.invalid=Incorrect Java path. +settings.game.java_directory.choose=Choose Java +settings.game.java_directory.invalid=Incorrect Java path settings.game.java_directory.version=Specify Java Version settings.game.java_directory.template=%s (%s) settings.game.management=Manage settings.game.working_directory=Working Directory -settings.game.working_directory.choose=Select working directory -settings.game.working_directory.hint=Turn on the 'Isolated' option under 'Working Directory' to allow the current instance to store its settings, saves, and mods in a separate directory.\n\ -\n\ -It is recommended to turn this option on to avoid mod conflicts, but you'll need to move your saves manually. -# ' +settings.game.working_directory.choose=Choose working directory +settings.game.working_directory.hint=Enable the "Isolated" option in "Working Directory" to allow the current instance to store its settings, saves, and mods in a separate directory.\n\ + \n\ + It is recommended to enable this option to avoid mod conflicts, but you will need to move your saves manually. settings.icon=Icon settings.launcher=Launcher Settings settings.launcher.appearance=Appearance -settings.launcher.common_path.tooltip=This app will put all game assets and dependencies here. If there are existing libraries under the game directory, the launcher will prefer to use them first. +settings.launcher.common_path.tooltip=HMCL will put all game assets and dependencies here. If there are existing libraries in the game directory, then HMCL will prefer to use them first. settings.launcher.debug=Debug settings.launcher.download=Download settings.launcher.download.threads=Threads settings.launcher.download.threads.auto=Automatically Determine settings.launcher.download.threads.hint=Too many threads may cause your system to freeze, and your download speed may be affected by your ISP and download servers. It is not always the case that more threads increase your download speed. settings.launcher.download_source=Download Source -settings.launcher.download_source.auto=Auto Choose Download Mirror -settings.launcher.enable_game_list=Show version list in home page +settings.launcher.download_source.auto=Automatically Choose Download Sources +settings.launcher.enable_game_list=Show instance list in homepage settings.launcher.font=Font settings.launcher.general=General -settings.launcher.language=Language (applies after restart) -settings.launcher.launcher_log.export=Export launcher logs +settings.launcher.language=Language (Applies After Restart) +settings.launcher.launcher_log.export=Export Launcher Logs settings.launcher.launcher_log.reveal=Reveal Logs in Explorer -settings.launcher.launcher_log.export.failed=Unable to export logs -settings.launcher.launcher_log.export.success=Logs have been exported to %s +settings.launcher.launcher_log.export.failed=Unable to export logs. +settings.launcher.launcher_log.export.success=Logs have been exported to "%s". settings.launcher.log=Logging settings.launcher.log.font=Font settings.launcher.proxy=Proxy -settings.launcher.proxy.authentication=Requires authentication -settings.launcher.proxy.disable=Use system proxy +settings.launcher.proxy.authentication=Requires Authentication +settings.launcher.proxy.disable=Use System Proxy settings.launcher.proxy.host=Host settings.launcher.proxy.http=HTTP -settings.launcher.proxy.none=No proxy +settings.launcher.proxy.none=No Proxy settings.launcher.proxy.password=Password settings.launcher.proxy.port=Port -settings.launcher.proxy.socks=SOCKS +settings.launcher.proxy.socks=Socks settings.launcher.proxy.username=Username settings.launcher.theme=Theme -settings.launcher.title_transparent=Transparent titlebar -settings.launcher.turn_off_animations=Turn off animation (applies after restart) +settings.launcher.title_transparent=Transparent Titlebar +settings.launcher.turn_off_animations=Disable Animation (Applies After Restart) settings.launcher.version_list_source=Version List settings.memory=Memory @@ -1212,23 +1256,23 @@ settings.memory.allocate.auto=%1$.1f GB Minimum / %2$.1f GB Allocated settings.memory.allocate.auto.exceeded=%1$.1f GB Minimum / %2$.1f GB Allocated (%3$.1f GB Available) settings.memory.allocate.manual=%1$.1f GB Allocated settings.memory.allocate.manual.exceeded=%1$.1f GB Allocated (%3$.1f GB Available) -settings.memory.auto_allocate=Automatically allocate +settings.memory.auto_allocate=Automatically Allocate settings.memory.lower_bound=Minimum Memory settings.memory.used_per_total=%1$.1f GB Used / %2$.1f GB Total settings.physical_memory=Physical Memory Size settings.show_log=Show Logs -settings.skin=Skins for offline accounts are now supported. You can go to the account settings to change your skin and cape, but other players cannot see it in multiplayer. -settings.tabs.installers=Modloaders / OptiFine -settings.take_effect_after_restart=Applies after restart -settings.type=Instance Settings Type -settings.type.global=Global Instance Settings (shared among instances) -settings.type.global.manage=Global Game Settings -settings.type.global.edit=Edit Global Instance Settings -settings.type.special.enable=Enable per-instance settings +settings.skin=Skins for offline accounts are now supported. You can navigate to your account list to change your skin and cape, but other players cannot see it in multiplayer. +settings.tabs.installers=Loaders +settings.take_effect_after_restart=Applies After Restart +settings.type=Settings Type of Instance +settings.type.global=Global Settings (Shared Among Instances without the "Instance-specific Settings" enabled) +settings.type.global.manage=Global Settings +settings.type.global.edit=Edit Global Settings +settings.type.special.enable=Enable Instance-specific Settings settings.type.special.edit=Edit Current Instance Settings -settings.type.special.edit.hint=Current instance [%s] has enabled per-instance settings, all options on this page will NOT affect that instance. Click here to modify its own options. +settings.type.special.edit.hint=Current instance "%s" has enabled the "Instance-specific Settings", all options on this page will NOT affect that instance. Click here to edit its own settings. -sponsor=Donators +sponsor=Donors sponsor.bmclapi=Downloads are provided by BMCLAPI. Click here for more information. sponsor.hmcl=Hello Minecraft! Launcher is a FOSS Minecraft launcher which allows users to manage multiple Minecraft instances easily. Click here for more information. @@ -1241,17 +1285,21 @@ update=Update update.accept=Update update.changelog=Changelog update.channel.dev=Beta -update.channel.dev.hint=You are currently using a beta build of the launcher, which may include some extra features, but is also sometimes more unstable than the release versions.\n\ -\n\ -If you encounter any bug or issue, you can go to the feedback page to report it, or tell us in our Discord or QQ community.\n\ -\n\ -Click here to hide this tooltip for the current version. -update.channel.dev.title=Beta Version Notice +update.channel.dev.hint=You are currently using a Beta channel build of the launcher, which may include some extra features, but is also sometimes more unstable than the Release channel.\n\ + \n\ + If you encounter any bugs or problems, please navigate to "Settings → Feedback" or submit your feedback through the following channels.\n\ + \n\ + GitHub Discord QQ Group\n\ + \n\ + Click Here to Hide This Tooltip for the Current Channel +update.channel.dev.title=Beta Channel Notice update.channel.nightly=Nightly -update.channel.nightly.hint=You are currently using a nightly build of the launcher, which may include some extra features, but is also always more unstable than the other versions.\n\ -\n\ -If you encounter any bug or issue, you can go to the feedback page to report it, or tell us in our Discord or QQ community. -update.channel.nightly.title=Nightly Version Notice +update.channel.nightly.hint=You are currently using a Nightly channel build of the launcher, which may include some extra features, but is also always more unstable than the other channels.\n\ + \n\ + If you encounter any bugs or problems, please navigate to "Settings → Feedback" or submit your feedback through the following channels.\n\ + \n\ + GitHub Discord QQ Group +update.channel.nightly.title=Nightly Channel Notice update.channel.stable=Release update.checking=Checking for Updates update.failed=Unable to update @@ -1259,17 +1307,17 @@ update.found=Update Available! update.newest_version=Latest version: %s update.bubble.title=Update Available: %s update.bubble.subtitle=Click here to update -update.note=Warning: Beta versions and nightly versions may have more features or fixes, but they also come with more potential issues. -update.latest=This is the latest version. -update.no_browser=Cannot open in the system browser. But, we copied the link to your clipboard and you can open it manually. +update.note=Beta & Nightly channels may have more features or fixes, but is also come with more potential problems. +update.latest=This is the latest version +update.no_browser=Cannot open in system browser. But we copied the link to your clipboard and you can open it manually. update.tooltip=Update version=Games version.name=Instance Name -version.cannot_read=Unable to parse the game version, automatic installation cannot continue. +version.cannot_read=Unable to parse the game instance, installation cannot continue. version.empty=No Instances -version.empty.add=Add an Instance -version.empty.launch=No instances, you can install one on the 'Download' tab. +version.empty.add=Add new instance +version.empty.launch=No instances, you can install one in "Download → New Game". version.empty.hint=There are no Minecraft instances here. You can try switching to another game directory or click here to download one. version.game.old=Historical version.game.release=Release @@ -1278,29 +1326,29 @@ version.game.snapshot=Snapshot version.game.snapshots=Snapshots version.launch=Launch Game version.launch.test=Test Launch -version.switch=Switch version +version.switch=Switch Instance version.launch_script=Export Launch Script version.launch_script.failed=Unable to export launch script. version.launch_script.save=Export Launch Script version.launch_script.success=Exported launch script as %s. version.manage=All Instances version.manage.clean=Delete Log Files -version.manage.clean.tooltip=Remove logs and crash reports. +version.manage.clean.tooltip=Delete the files in "logs" and "crash-reports" directories. version.manage.duplicate=Duplicate Instance -version.manage.duplicate.duplicate_save=Duplicate Save -version.manage.duplicate.prompt=Enter instance name -version.manage.duplicate.confirm=The duplicated instance will have a copy of all the files of this instance, with an isolated game directory and settings. -version.manage.manage=Manage Instances -version.manage.manage.title=Manage Instance - %1s +version.manage.duplicate.duplicate_save=Duplicate Saves +version.manage.duplicate.prompt=Enter New Instance Name +version.manage.duplicate.confirm=The duplicated instance will have a copy of all files in the instance directory (".minecraft/versions/"), with an isolated working directory and settings. +version.manage.manage=Edit Instance +version.manage.manage.title=Edit Instance - %1s version.manage.redownload_assets_index=Update Game Assets version.manage.remove=Delete Instance -version.manage.remove.confirm=Are you sure you want to permanently remove the version %s? This action cannot be undone! -version.manage.remove.confirm.trash=Are you sure you want to remove the version %s? You can still find its files in your recycle bin by the name of %s. -version.manage.remove.confirm.independent=Since this instance is stored in an isolated directory, deleting it will also delete its saves and other data. Do you still want to delete instance %s? +version.manage.remove.confirm=Are you sure you want to permanently remove the instance "%s"? This operation cannot be undone!!! +version.manage.remove.confirm.trash=Are you sure you want to remove the instance "%s"? You can still find its files in your recycle bin by the name of "%s". +version.manage.remove.confirm.independent=Since this instance is stored in an isolated directory, deleting it will also delete its saves and other data. Do you still want to delete the instance "%s"? version.manage.remove_assets=Delete All Assets version.manage.remove_libraries=Delete All Libraries version.manage.rename=Rename Instance -version.manage.rename.message=Please enter the new name for this instance +version.manage.rename.message=Enter New Instance Name version.manage.rename.fail=Unable to rename the instance, some files might be in use or the name contains an invalid character. version.settings=Settings version.update=Update Modpack From b2dc4b45c28b047eeddc90b8c3a8c51ae31bdaf0 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Fri, 25 Oct 2024 01:47:22 +0800 Subject: [PATCH 057/169] Revise zh_TW part 2 (#3357) * Revise zh_TW part 2 * Update * fix typo * fix * fix * fix * fix When choosing a download source, the commas in the BMCLAPI item are changed to half-width. --- .../resources/assets/lang/I18N_zh.properties | 161 +++++++++--------- 1 file changed, 77 insertions(+), 84 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index fe57454e06..3ffd65a017 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -151,7 +151,7 @@ account.skin.type.csl_api=Blessing Skin 伺服器 account.skin.type.csl_api.location=伺服器位址 account.skin.type.csl_api.location.hint=CustomSkinAPI 位址 account.skin.type.little_skin=LittleSkin 皮膚站 -account.skin.type.little_skin.hint=你需要在皮膚站中建立並使用和該離線帳戶同名角色,此時離線帳戶外觀將為皮膚站上角色所設定的外觀。 +account.skin.type.little_skin.hint=你需要在皮膚站中加入並使用和該離線帳戶同名角色,此時離線帳戶外觀將為皮膚站上對應角色所設定的外觀。 account.skin.type.local_file=本機外觀圖片檔案 account.skin.upload=上傳/編輯外觀 account.skin.upload.failed=外觀上傳失敗 @@ -165,7 +165,7 @@ archive.version=版本 assets.download=下載資源 assets.download_all=驗證資源檔案完整性 -assets.index.malformed=資源檔案的索引檔案損壞,你可以在相應實例的「實例設定」頁面中,點擊設定頁面左下角的「設定」按鈕並選取「更新遊戲資源檔案」,以修復該問題。 +assets.index.malformed=資源檔案的索引檔案損壞,你可以在相應實例的「實例管理」頁面中,點擊頁面左下角的「設定 → 更新遊戲資源檔案」以修復該問題。 button.cancel=取消 button.change_source=切換下載源 @@ -322,7 +322,7 @@ download=下載 download.hint=安裝遊戲和模組包或下載模組、資源包和地圖 download.code.404=遠端伺服器沒有需要下載的檔案:%s download.content=遊戲內容 -download.curseforge.unavailable=HMCL 快照版暫不支援訪問 CurseForge,請使用穩定版或測試版進行下載。 +download.curseforge.unavailable=HMCL 預覽版暫不支援訪問 CurseForge,請使用穩定版或開發版進行下載。 download.existing=檔案已存在,無法儲存。你可以將檔案儲存至其他地方。 download.external_link=打開下載網站 download.failed=下載失敗:%1$s\n錯誤碼:%2$d @@ -330,7 +330,7 @@ download.failed.empty=沒有可供安裝的版本,按一下此處返回。 download.failed.no_code=下載失敗:%s download.failed.refresh=載入版本清單失敗,按一下此處重試。 download.game=新遊戲 -download.provider.bmclapi=BMCLAPI (bangbang93,https://bmclapi2.bangbang93.com/) +download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) download.provider.mojang=官方伺服器 (OptiFine 由 BMCLAPI 提供) download.provider.official=盡量使用官方源 (最新,但可能載入慢) download.provider.balanced=選取載入速度快的下載源 (平衡,但可能不是最新) @@ -346,7 +346,7 @@ exception.access_denied=無法存取檔案「%s」,因為 HMCL 沒有對該檔 請你檢查目前作業系統帳戶是否能訪存取檔案,比如非管理員使用者可能不能訪問其他帳戶的個人目錄內的檔案。\n\ 對於 Windows 使用者,你還可以嘗試透過資源監視器查看是否有程式占用了該檔案,如果是,你可以關閉占用此檔案的程式,或者重啟電腦再試。 exception.artifact_malformed=下載的檔案正確,但無法透過校驗。 -exception.ssl_handshake=無法建立 SSL 連線,因為目前 Java 虛擬機缺少相關的 SSL 證書。你可以嘗試使用其他的 Java 虛擬機或關閉網路代理啟動 HMCL 再試。 +exception.ssl_handshake=無法建立 SSL 連線,因為目前 Java 虛擬機缺少相關的 SSL 證書。你可以嘗試使用其他的 Java 虛擬機或關閉網路代理開啟 HMCL 再試。 extension.bat=Windows 批次檔 extension.mod=模組檔案 @@ -356,21 +356,21 @@ extension.sh=Bash 指令碼 fatal.javafx.incompatible=缺少 JavaFX 執行環境。\nHMCL 無法在低於 Java 11 的 Java 環境上自行補全 JavaFX 執行環境,請更新到 Java 11 或更高版本。 fatal.javafx.incomplete=JavaFX 執行環境不完整,請嘗試更換你的 Java 或者重新安裝 OpenJFX。 -fatal.javafx.missing=缺少 JavaFX 執行環境,請使用包含 OpenJFX 的 Java 執行環境啟動 Hello Minecraft! Launcher。 -fatal.config_change_owner_root=你正在使用 root 帳戶啟動 Hello Minecraft! Launcher,這可能導致你未來無法使用其他帳戶正常啟動 Hello Minecraft! Launcher。\n是否繼續啟動? -fatal.config_in_temp_dir=你正在暫存目錄中啟動 Hello Minecraft! Launcher,你的設定和遊戲資料可能會遺失,建議將 Hello Minecraft! Launcher 移動至其他位置再啟動。\n是否繼續啟動? -fatal.config_loading_failure=Hello Minecraft! Launcher 無法載入設定檔案。\n請確保 Hello Minecraft! Launcher 對「%s」目錄及該目錄下的檔案擁有讀寫權限。 -fatal.config_loading_failure.unix=Hello Minecraft! Launcher 無法載入設定檔案,因為設定檔案是由使用者「%1$s」建立的。\n請使用 root 帳戶啟動 HMCL (不推薦),或在終端中執行以下指令將設定檔案的所有權變更為目前使用者:\n%2$s -fatal.mac_app_translocation=由於 macOS 的安全機制,Hello Minecraft! Launcher 被系統隔離至暫存目錄中。\n請將 Hello Minecraft! Launcher 移動到其他目錄後再嘗試啟動,否則你的設定和遊戲資料可能會在重啟後遺失。\n是否繼續啟動? -fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher 即將升級完成,請重新開啟 Hello Minecraft! Launcher。 -fatal.apply_update_failure=我們很抱歉 Hello Minecraft! Launcher 無法自動完成升級程式,因為出現了一些問題。\n但你依然可以從 %s 處手動下載 Hello Minecraft! Launcher 來完成升級。 -fatal.apply_update_need_win7=Hello Minecraft! Launcher 無法在 Windows XP/Vista 上進行自動更新,請從 %s 處手動下載 Hello Minecraft! Launcher 來完成升級。 -fatal.samba=如果您正在透過 Samba 共亯的目錄中執行 Hello Minecraft! Launcher,啟動器可能無法正常工作,請嘗試更新您的 Java 或在本機目錄內執行 HMCL。 +fatal.javafx.missing=缺少 JavaFX 執行環境,請使用包含 OpenJFX 的 Java 執行環境開啟 Hello Minecraft! Launcher。 +fatal.config_change_owner_root=你正在使用 root 帳戶開啟 Hello Minecraft! Launcher,這可能導致你未來無法使用其他帳戶正常開啟 HMCL。\n是否繼續開啟? +fatal.config_in_temp_dir=你正在暫存目錄中開啟 Hello Minecraft! Launcher,你的設定和遊戲資料可能會遺失,建議將 HMCL 移動至其他位置再開啟。\n是否繼續開啟? +fatal.config_loading_failure=Hello Minecraft! Launcher 無法載入設定檔案。\n請確保 HMCL 對「%s」目錄及該目錄下的檔案擁有讀寫權限。 +fatal.config_loading_failure.unix=Hello Minecraft! Launcher 無法載入設定檔案,因為設定檔案是由使用者「%1$s」建立的。\n請使用 root 帳戶開啟 HMCL (不推薦),或在終端中執行以下指令將設定檔案的所有權變更為目前使用者:\n%2$s +fatal.mac_app_translocation=由於 macOS 的安全機制,Hello Minecraft! Launcher 被系統隔離至暫存目錄中。\n請將 HMCL 移動到其他目錄後再嘗試開啟,否則你的設定和遊戲資料可能會在重啟後遺失。\n是否繼續開啟? +fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher 即將升級完成,請重新開啟 HMCL。 +fatal.apply_update_failure=我們很抱歉 Hello Minecraft! Launcher 無法自動完成升級程式,因為出現了一些問題。\n但你依然可以從 %s 處手動下載 HMCL 來完成升級。 +fatal.apply_update_need_win7=Hello Minecraft! Launcher 無法在 Windows XP/Vista 上進行自動更新,請從 %s 處手動下載 HMCL 來完成升級。 +fatal.samba=如果您正在透過 Samba 共亯的目錄中開啟 Hello Minecraft! Launcher,啟動器可能無法正常工作,請嘗試更新您的 Java 或在本機目錄內開啟 HMCL。 fatal.illegal_char=由於您的使用者目錄路徑中存在無效字元『=』,您將無法使用外部登入帳戶以及離線登入更換外觀功能。 fatal.unsupported_platform=Minecraft 尚未你您的平臺提供完善支援,所以可能影響遊戲體驗或無法啟動遊戲。\n若無法啟動 Minecraft 1.17 及更高版本,可以嘗試在「(全域/實例特定) 遊戲設定 → 進階設定 → 除錯選項」中將「繪製器」切換為「軟繪製器」,以獲得更好的相容性。 fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher 已為龍芯提供支援。\n如果遇到問題,你可以點擊右上角幫助按鈕進行求助。 fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher 已為 Apple Silicon 平臺提供支援,使用 ARM 原生 Java 啟動遊戲以獲得更流暢的遊戲體驗。\n如果你在遊戲中遭遇問題,使用 x86-64 架構的 Java 啟動遊戲可能有更好的相容性。 -fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已為 Windows on ARM 平臺提供原生支援。如果你在遊戲中遭遇問題,請嘗試使用 x86 架構的 Java 啟動遊戲。\n\n如果你正在使用高通平臺,你可能需要安裝 OpenGL 相容包後才能進行遊戲。點擊連結前往 Microsoft Store 安裝相容包。 +fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已為 Windows on Arm 平臺提供原生支援。如果你在遊戲中遭遇問題,請嘗試使用 x86 架構的 Java 啟動遊戲。\n\n如果你正在使用高通平臺,你可能需要安裝 OpenGL 相容包後才能進行遊戲。點擊連結前往 Microsoft Store 安裝相容包。 feedback=回報 feedback.channel=回報管道 @@ -393,82 +393,75 @@ folder.saves=遊戲存檔目錄 folder.screenshots=截圖目錄 game=遊戲 -game.crash.feedback=請不要將本界面截圖給他人! 如果你要求助他人,請你點擊左下角 導出遊戲崩潰信息 後將導出的文件發送給他人以供分析。\n你可以點擊下方的 幫助 前往社區尋求幫助。 +game.crash.feedback=請不要將本介面截圖給他人!如果你要求助他人,請你點擊左下角「匯出遊戲崩潰資訊」後將匯出的檔案發送給他人以供分析。\n你可以點擊下方的「幫助」前往社群尋求幫助。 game.crash.info=遊戲訊息 game.crash.reason=崩潰原因 -game.crash.reason.analyzing=分析中... +game.crash.reason.analyzing=分析中…… game.crash.reason.multiple=檢測到多個原因:\n\n -game.crash.reason.block=當前遊戲因為某個方塊不能正常工作,無法繼續運行。\n你可以嘗試通過 MCEdit 工具編輯存檔刪除該方塊,或者直接刪除相應的 Mod。\n方塊類型:%1$s\n方塊坐標:%2$s -game.crash.reason.bootstrap_failed=當前遊戲因為模組 %1$s 錯誤,無法繼續運行。\n你可以嘗試刪除或更新該模組以解決問題。 -game.crash.reason.mixin_apply_mod_failed=當前遊戲因為 Mixin 無法應用 %1$s 模組,無法繼續運行。\n你可以嘗試刪除或更新該 Mod 以解決問題。 -game.crash.reason.config=當前遊戲因為無法解析模組配置文件,無法繼續運行\n模組 %1$s 的配置文件 %2$s 無法被解析。 -game.crash.reason.debug_crash=當前遊戲因為手動觸發崩潰,無法繼續運行。\n事實上遊戲並沒有問題,問題都是你造成的。 -game.crash.reason.duplicated_mod=當前遊戲因為 Mod 重複安裝,無法繼續運行。\n%s\n每種 Mod 只能安裝一個,請你刪除多餘的 Mod 再試。 -game.crash.reason.entity=當前遊戲因為某個實體不能正常工作,無法繼續運行。\n你可以嘗試通過 MCEdit 工具編輯存檔刪除該實體,或者直接刪除相應的 Mod。\n實體類型:%1$s\n實體坐標:%2$s -game.crash.reason.fabric_version_0_12=Fabric 0.12 及以上版本與當前已經安裝的 Mod 可能不相容,你需要將 Fabric 降級至 0.11.7。 +game.crash.reason.block=目前遊戲由於某個方塊不能正常工作,無法繼續執行。\n你可以嘗試透過 MCEdit 工具編輯存檔刪除該方塊,或者直接刪除相應的模組。\n方塊類型:%1$s\n方塊坐標:%2$s +game.crash.reason.bootstrap_failed=目前遊戲由於模組「%1$s」出現問題,無法繼續執行。\n你可以嘗試刪除或更新該模組以解決問題。 +game.crash.reason.mixin_apply_mod_failed=目前遊戲由於 Mixin 無法應用於「%1$s」模組,無法繼續執行。\n你可以嘗試刪除或更新該模組以解決問題。 +game.crash.reason.config=目前遊戲由於無法解析模組配置檔案,無法繼續執行\n模組「%1$s」的配置檔案「%2$s」無法被解析。 +game.crash.reason.debug_crash=目前遊戲由於手動觸發崩潰,無法繼續執行。\n事實上遊戲並沒有問題,問題都是你造成的! +game.crash.reason.duplicated_mod=目前遊戲由於模組重複安裝,無法繼續執行。\n%s\n每種模組只能安裝一個,請你刪除多餘的模組再試。 +game.crash.reason.entity=目前遊戲由於某個實體不能正常工作,無法繼續執行。\n你可以嘗試透過 MCEdit 工具編輯存檔刪除該實體,或者直接刪除相應的模組。\n實體類型:%1$s\n實體坐標:%2$s +game.crash.reason.fabric_version_0_12=Fabric Loader 0.12 及更高版本與目前已經安裝的模組可能不相容,你需要將 Fabric Loader 降級至 0.11.7。 game.crash.reason.fabric_warnings=Fabric 提供了一些警告訊息:\n%1$s -game.crash.reason.modmixin_failure=當前遊戲因為某些 Mod 注入失敗,無法繼續運行。\n這一般代表著該 Mod 存在 Bug,或與當前環境不兼容。\n你可以查看日誌尋找出錯模組。 -game.crash.reason.file_or_content_verification_failed=當前遊戲因為部分文件或內容校驗失敗,導致遊戲出現了問題。\n請嘗試刪除該版本(包括 Mod)並重新下載,或嘗試在重新下載時使用代理等。 -game.crash.reason.mod_repeat_installation=當前遊戲因為重複安裝了多個相同的 Mod,每個 Mod 只能出現一次,請刪除重複的 Mod,然後再啟動遊戲。 -game.crash.reason.forge_error=Forge 可能已經提供了錯誤信息。\n你可以查看日誌,並根據錯誤報告中的日誌信息進行對應處。\n如果沒有看到報錯信息,可以查看錯誤報告了解錯誤具體是如何發生的。\n%1$s -game.crash.reason.mod_resolution0=當前遊戲因為一些 Mod 出現問題,無法繼續運行。\n你可以查看日誌尋找出錯模組。 -game.crash.reason.need_jdk11=當前遊戲因為 Java 虛擬機版本不合適,無法繼續運行。\n你需要下載安裝 Java 11,並在全局(特定)遊戲設置中將 Java 設置為 11 開頭的版本。 -game.crash.reason.mod_profile_causes_game_crash=當前遊戲因為 Mod 配置文件出現問題,無法繼續運行。\n你可以查看日誌尋找出錯模組及其配置文件。 -game.crash.reason.fabric_reports_an_error_and_gives_a_solution=Forge 可能已經提供了錯誤信息。\n你可以查看日誌,並根據錯誤報告中的日誌信息進行對應處。\n如果沒有看到報錯信息,可以查看錯誤報告了解錯誤具體是如何發生的。 -game.crash.reason.java_version_is_too_high=當前遊戲因為使用的 Java 版本過高而崩潰了,無法繼續運行。\n請在 全局遊戲設置 或 遊戲特定設置 的 Java 路徑選項卡中改用較低版本的 Java,然後再啟動遊戲。\n如果沒有,可以從 java.com(Java8)BellSoft Liberica Full JRE(Java17) 等平台下載、安裝一個(安裝完後需重啟啟動器)。 -game.crash.reason.mod_name=當前遊戲因為 Mod 檔案名稱問題,無法繼續運行。\nMod 檔案名稱應只使用英文全半型的大小寫字母(Aa~Zz)、數位(0~9)、橫線(-)、底線(_)和點(.)。\n請到Mod資料夾中將所有不合規的Mod檔案名稱添加一個上述的合規的字元。 -game.crash.reason.incomplete_forge_installation=當前遊戲因為 Forge / NeoForge 安裝不完整,無法繼續運行。\n請在 版本設置 - 自動安裝 中移除 Forge / NeoForge 並重新安裝。 -game.crash.reason.file_already_exists=當前遊戲因為文件 %1$s 已經存在,無法繼續運行。\n如果你認為這個文件可以刪除,你可以在備份這個文件後嘗試刪除它,並重新啟動遊戲。 -game.crash.reason.file_changed=當前遊戲因為檔案校驗失敗,無法繼續運行。\n如果你手動修改了 Minecraft.jar 檔案,你需要回退修改,或者重新下載遊戲。 -game.crash.reason.gl_operation_failure=當前遊戲因為你使用的某些 Mod、光影包、材質包,無法繼續運行。\n請先嘗試禁用你所使用的Mod/光影包/材質包再試。 -game.crash.reason.graphics_driver=當前遊戲因為你的顯示卡驅動存在問題崩潰了,請嘗試升級你的顯示卡驅動到最新版本後再嘗試啟動遊戲。\n\ - 如果你的電腦存在獨立顯示卡,你需要檢查遊戲是否使用集成/核芯顯示卡啟動。如果是,請嘗試使用獨立顯示卡啟動 HMCL 與遊戲。如果仍有問題,你可能需要考慮換一個新顯示卡或新電腦。\n\ - 如果你確實需要使用核芯顯示卡,請檢查你的電腦的 CPU 是否是 Intel(R) Core(TM) 3000 系列或更舊的處理器,如果是,對於 Minecraft 1.16.5 及更舊版本,請你將遊戲所使用的 Java 版本降級至 1.8.0_51 及以下版本,否則你需要更換獨立顯示卡或新電腦。\n\ - 在版本設定中打開“使用 OpenGL 軟渲染器”選項也可以解决此問題,但打開此選項後在 CPU 效能不足的情况下幀數會顯著降低,僅推薦以調試為目的或應急時開啟。 -game.crash.reason.macos_failed_to_find_service_port_for_display=當前遊戲因為 apple silicon 平台下初始化 opengl 窗口失敗,無法繼續運行。\n對於該問題,HMCL 暫無直接性的解決方案。請您嘗試任意打開一個瀏覽器並全屏,然後再回到 HMCL 啟動遊戲,在彈出遊戲窗口前迅速切回瀏覽器頁面,等待遊戲窗口出現後再切回遊戲窗口。 -game.crash.reason.illegal_access_error=當前遊戲因為某些 Mod 的問題,無法繼續運行。\n如果你認識:%1$s,你可以更新或刪除對應 Mod 再試。 -game.crash.reason.install_mixinbootstrap=當前遊戲因為缺失 MixinBootstrap,無法繼續運行。\n你可以嘗試安裝 MixinBootstrap 解決該問題。若安裝後崩潰,嘗試在該模組的文件名前加入英文“!”嘗試解決。 -game.crash.reason.jdk_9=當前遊戲因為 Java 版本過高,無法繼續運行。\n你需要下載安裝 Java 8,並在遊戲設置中將 Java 設置為 1.8 的版本。 -game.crash.reason.jvm_32bit=當前遊戲因為記憶體分配過大,超過了 32 位 Java 記憶體限制,無法繼續運行。\n如果你的電腦是 64 位系統,請下載安裝並更換 64 位 Java。如果你的電腦室 32 位系統,你或許可以重新安裝 64 位系統,或換一台新電腦。\n或者,你可以關閉遊戲記憶體的自動分配,並且把記憶體限制調節為 1024 MB 或以下。 -game.crash.reason.loading_crashed_forge=當前遊戲因為模組 %1$s (%2$s) 錯誤,無法繼續運行。\n你可以嘗試刪除或更新該模組以解決問題。 -game.crash.reason.loading_crashed_fabric=當前遊戲因為模組 %1$s 錯誤,無法繼續運行。\n你可以嘗試刪除或更新該模組以解決問題。 -game.crash.reason.mac_jdk_8u261=當前遊戲因為你所使用的 Forge 或 OptiFine 與 Java 衝突崩潰。\n請嘗試更新 Forge 和 OptiFine,或使用 Java 8u251 及更早版本啟動。 -game.crash.reason.memory_exceeded=當前遊戲因為分配的記憶體過大,無法繼續運行。\n該問題是由於系統頁面文件太小導致的。\n你需要在遊戲設置中關閉遊戲記憶體的自動分配,並將遊戲記憶體調低至遊戲能正常啟動為止。\n你還可以嘗試調大系統的頁面大小。 -game.crash.reason.mod=當前遊戲因為 %1$s 的問題,無法繼續運行。\n你可以更新或刪除已經安裝的 %1$s 再試。 -game.crash.reason.mod_resolution=當前遊戲因為 Mod 依賴問題,無法繼續運行。Fabric 提供了如下訊息:\n%1$s -game.crash.reason.forgemod_resolution=當前遊戲因為 Mod 依賴問題,無法繼續運行。Forge 提供了如下訊息:\n%1$s -game.crash.reason.forge_found_duplicate_mods=遊戲崩潰原因模組重複的問題,無法繼續運行。Forge 提供了以下信息:\n%1$s -game.crash.reason.mod_resolution_collection=當前遊戲因為前置 Mod 版本不匹配,無法繼續運行。\n%1$s 需要前置 Mod:%2$s 才能繼續運行。\n這表示你需要更新或降級前置。你可以到下載頁的模組下載,或到網路上下載 %3$s。 -game.crash.reason.mod_resolution_conflict=當前遊戲因為 Mod 衝突,無法繼續運行。\n%1$s 與 %2$s 不能相容。 -game.crash.reason.mod_resolution_missing=當前遊戲因為缺少 Mod 前置,無法繼續運行。\n%1$s 需要前置 Mod:%2$s 才能繼續運行。\n這表示你少安裝了 Mod,或該 Mod 版本不夠。你可以到下載頁的模組下載,或到網路上下載 %2$s。 -game.crash.reason.mod_resolution_missing_minecraft=當前遊戲因為 Mod 和 Minecraft 遊戲版本不匹配,無法繼續運行。\n%1$s 需要 Minecraft %2$s 才能運行。\n如果你要繼續使用你已經安裝的 Mod,你可以選擇安裝對應的 Minecraft 版本;如果你要繼續使用當前 Minecraft 版本,你需要安裝對應版本的 Mod。 +game.crash.reason.modmixin_failure=目前遊戲由於某些模組注入失敗,無法繼續執行。\n這一般代表著該模組存在問題,或與目前環境不相容。\n你可以查看日誌尋找出錯模組。 +game.crash.reason.mod_repeat_installation=目前遊戲由於重複安裝了多個相同的模組,無法繼續執行。\n每個模組只能出現一次,請刪除重複的模組,然後再啟動遊戲。 +game.crash.reason.forge_error=Forge/NeoForge 可能已經提供了錯誤資訊。\n你可以查看日誌,並根據錯誤報告中的日誌資訊進行對應處。\n如果沒有看到報錯資訊,可以查看錯誤報告了解錯誤具體是如何發生的。\n%1$s +game.crash.reason.mod_resolution0=目前遊戲由於一些模組出現問題,無法繼續執行。\n你可以查看日誌尋找出錯模組。 +game.crash.reason.need_jdk11=目前遊戲由於 Java 虛擬機版本不合適,無法繼續執行。\n你需要下載安裝 Java 11,並在「(全域/實例特定) 遊戲設定 → 遊戲 Java」中將 Java 設定為 11 開頭的版本。 +game.crash.reason.java_version_is_too_high=目前遊戲由於使用的 Java 版本過高而崩潰了,無法繼續執行。\n請在「(全域/實例特定) 遊戲設定 → 遊戲 Java」中改用較低版本的 Java,然後再啟動遊戲。\n如果沒有,可以從 java.com (Java 8)BellSoft Liberica Full JRE (Java 17) 等平台下載、安裝一個 (安裝完後需重啟啟動器)。 +game.crash.reason.mod_name=目前遊戲由於模組檔案名稱問題,無法繼續執行。\n模組檔案名稱應只使用半型的大小寫字母 (Aa~Zz)、數位 (0~9)、橫線 (-)、底線 (_)和點 (.)。\n請到模組目錄中將所有不合規的模組檔案名稱修正為上述合規字元。 +game.crash.reason.incomplete_forge_installation=目前遊戲由於 Forge 安裝不完整,無法繼續執行。\n請在「實例管理 - 自動安裝」中移除 Forge 並重新安裝。 +game.crash.reason.file_already_exists=目前遊戲由於檔案「%1$s」已經存在,無法繼續執行。\n如果你認為這個檔案可以刪除,你可以在備份這個檔案後嘗試刪除它,並重新啟動遊戲。 +game.crash.reason.file_changed=目前遊戲由於檔案校驗失敗,無法繼續執行。\n如果你手動修改了 Minecraft.jar 檔案,你需要回退修改,或者重新下載遊戲。 +game.crash.reason.gl_operation_failure=目前遊戲由於你使用的某些模組/光影包/資源包出現問題,無法繼續執行。\n請先嘗試禁用你所使用的模組/光影包/資源包再試。 +game.crash.reason.graphics_driver=目前遊戲由於你的顯示卡驅動存在問題崩潰了,請嘗試升級你的顯示卡驅動到最新版本後再嘗試啟動遊戲。\n\ + 如果你的電腦存在獨立顯示卡,你需要檢查遊戲是否使用整合/核芯顯示卡啟動。如果是,請嘗試使用獨立顯示卡開啟 HMCL 與遊戲。如果仍有問題,你可能需要考慮換一個新顯示卡或新電腦。\n\ + 如果你確實需要使用核芯顯示卡,請檢查你電腦的 CPU 是否為 Intel(R) Core(TM) 3000 系列或更舊的處理器,如果是,對於 Minecraft 1.16.5 及更低版本,請你將遊戲所使用的 Java 版本降級至 1.8.0_51 及更低版本,否則你需要更換獨立顯示卡或新電腦。 +game.crash.reason.macos_failed_to_find_service_port_for_display=目前遊戲由於 Apple Silicon 平台下初始化 OpenGL 視窗失敗,無法繼續執行。\n對於該問題,HMCL 暫無直接性的解決方案。請你嘗試任意打開一個瀏覽器並切換為全螢幕,然後再回到 HMCL 啟動遊戲,在彈出遊戲視窗前迅速切回瀏覽器頁面,等待遊戲視窗出現後再切回遊戲視窗。 +game.crash.reason.illegal_access_error=目前遊戲由於某些模組的問題,無法繼續執行。\n如果你認識「%1$s」,你可以更新或刪除對應模組再試。 +game.crash.reason.install_mixinbootstrap=目前遊戲由於缺失 MixinBootstrap,無法繼續執行。\n你可以嘗試安裝 MixinBootstrap 解決該問題。若安裝後崩潰,嘗試在該模組的檔案名前加入半形驚嘆號 (!) 嘗試解決。 +game.crash.reason.jdk_9=目前遊戲由於 Java 版本過高,無法繼續執行。\n你需要下載安裝 Java 8,並在「(全域/實例特定) 遊戲設定 → 遊戲 Java」中將 Java 設定為 1.8 的版本。 +game.crash.reason.jvm_32bit=目前遊戲由於記憶體分配過大,超過了 32 位 Java 記憶體限制,無法繼續執行。\n如果你的電腦是 64 位系統,請下載安裝並更換 64 位 Java。\n如果你的電腦是 32 位系統,你或許可以重新安裝 64 位系統,或換一台新電腦。\n或者,你可以關閉「(全域/實例特定) 遊戲設定 → 遊戲記憶體」中的「自動分配」,並且把記憶體限制調節為 1024 MB 或以下。 +game.crash.reason.loading_crashed_forge=目前遊戲由於模組「%1$s (%2$s)」錯誤,無法繼續執行。\n你可以嘗試刪除或更新該模組以解決問題。 +game.crash.reason.loading_crashed_fabric=目前遊戲由於模組「%1$s」錯誤,無法繼續執行。\n你可以嘗試刪除或更新該模組以解決問題。 +game.crash.reason.mac_jdk_8u261=目前遊戲由於你所使用的 Forge 或 OptiFine 與 Java 衝突而崩潰。\n請嘗試更新 Forge 和 OptiFine,或使用 Java 8u251 及更早版本啟動。 +game.crash.reason.memory_exceeded=目前遊戲由於分配的記憶體過大,無法繼續執行。\n該問題是由於系統頁面檔案太小導致的。\n你需要在「(全域/實例特定) 遊戲設定 → 遊戲記憶體」中關閉「自動分配」,並將遊戲記憶體調低至遊戲能正常啟動為止。\n你還可以嘗試調大系統的頁面大小。 +game.crash.reason.mod=目前遊戲由於 %1$s 的問題,無法繼續執行。\n你可以更新或刪除已經安裝的「%1$s」再試。 +game.crash.reason.mod_resolution=目前遊戲由於相依模組問題,無法繼續執行。Fabric 提供了如下訊息:\n%1$s +game.crash.reason.forgemod_resolution=目前遊戲由於模組相依元件問題,無法繼續執行。Forge/NeoForge 提供了以下資訊:\n%1$s +game.crash.reason.forge_found_duplicate_mods=目前遊戲由於模組重複的問題,無法繼續執行。Forge/NeoForge 提供了以下資訊:\n%1$s +game.crash.reason.mod_resolution_collection=目前遊戲由於相依模組版本不匹配,無法繼續執行。\n「%1$s」需要相依模組「%2$s」才能繼續執行。\n這表示你需要更新或降級相依模組。你可以到「下載 → 模組」頁面下載,或到網路上下載「%3$s」。 +game.crash.reason.mod_resolution_conflict=目前遊戲由於模組衝突,無法繼續執行。\n「%1$s」與「%2$s」不能相容。 +game.crash.reason.mod_resolution_missing=目前遊戲由於缺少相依模組,無法繼續執行。\n「%1$s」需要相依模組「%2$s」才能繼續執行。\n這表示你少安裝了模組,或該模組版本不夠。你可以到「下載 → 模組」頁面下載,或到網路上下載「%2$s」。 +game.crash.reason.mod_resolution_missing_minecraft=目前遊戲由於模組和 Minecraft 遊戲版本不匹配,無法繼續執行。\n「%1$s」需要 Minecraft %2$s 才能執行。\n如果你要繼續使用你已經安裝的模組,你可以選取安裝對應的 Minecraft 版本;如果你要繼續使用目前的 Minecraft 版本,你需要安裝對應版本的模組。 game.crash.reason.mod_resolution_mod_version=%1$s (版本號 %2$s) game.crash.reason.mod_resolution_mod_version.any=%1$s (任意版本) -game.crash.reason.forge_repeat_installation=當前遊戲因為 Forge 重複安裝,無法繼續運行。此為已知問題\n建議將日誌上傳反饋至 GitHub ,以便我們找到更多線索並修復此問題。\n目前你可以到 自動安裝 裡頭移除 Forge 並重新安裝。 -game.crash.reason.optifine_repeat_installation=當前遊戲因為重複安裝 OptiFine,無法繼續運行。 \n請刪除 Mod 文件夾下的 OptiFine 或前往 遊戲管理-自動安裝 移除自動安裝的 OptiFine。 -game.crash.reason.optifine_is_not_compatible_with_forge=當前遊戲因為OptiFine與當前版本的Forge不相容,導致了遊戲崩潰。\n請前往 OptiFine 官網查看 OptiFine 所相容的 Forge 版本,並嚴格按照對應版本重新安裝遊戲或在版本設定-自動安裝中更換版本。\n經測試,Forge版本過高或過低都可能導致崩潰。 -game.crash.reason.night_config_fixes=當前遊戲因為 Night Config 庫的一些問題,無法繼續運行。\n你可以嘗試安裝 Night Config Fixes 模組,這或許能幫助你解決這個問題。\n了解更多,可訪問該模組的 GitHub 倉庫。 -game.crash.reason.mod_files_are_decompressed=當前遊戲因為 Mod 檔案被解壓了,無法繼續運行。\n請直接把整個 Mod 檔案放進 Mod 資料夾中即可。\n若解壓就會導致遊戲出錯,請删除Mod資料夾中已被解壓的Mod,然後再啟動遊戲。 -game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=當前遊戲因為您所安裝的 Mod 過多,超出了遊戲的ID限制,無法繼續運行。\n請嘗試安裝JEID等修復Mod,或删除部分大型Mod。 -game.crash.reason.optifine_causes_the_world_to_fail_to_load=當前遊戲因為 Mod 檔案被解壓了,無法繼續運行。\n請直接把整個Mod檔案放進Mod資料夾中即可!\n若解壓就會導致遊戲出錯,請删除Mod資料夾中已被解壓的Mod,然後再啟動遊戲。 -game.crash.reason.modlauncher_8=當前遊戲因為你所使用的 Forge 版本與當前使用的 Java 衝突崩潰,請嘗試更新 Forge。 -game.crash.reason.cannot_find_launch_target_fmlclient=當前遊戲因為 Forge 安裝不完整,無法繼續運行。 \n你可嘗試前往 遊戲管理 - 自動安裝 中選擇 Forge 並重新安裝。 -game.crash.reason.shaders_mod=當前遊戲因為同時安裝了 OptiFine 和 Shaders Mod,無法繼續運行。 \n因為 OptiFine 已集成 Shaders Mod 的功能,只需刪除 Shaders Mod 即可。 -game.crash.reason.rtss_forest_sodium=當前遊戲因為 RivaTuner Statistics Server (RTSS) 與 Sodium 不相容,導致遊戲崩潰。\n點擊 此處 查看詳情。 -game.crash.reason.no_class_def_found_error=當前遊戲因為代碼不完整,無法繼續運行。\n你的遊戲可能缺失了某個 Mod,或者某些 Mod 檔案不完整,或者 Mod 與遊戲的版本不匹配。\n你可能需要重新安裝遊戲和 Mod,或請求他人幫助。\n缺失:%1$s -game.crash.reason.no_such_method_error=當前遊戲因為代碼不完整,無法繼續運行。\n你的遊戲可能缺失了某個 Mod,或者某些 Mod 檔案不完整,或者 Mod 與遊戲的版本不匹配。\n你可能需要重新安裝遊戲和 Mod,或請求他人幫助。 -game.crash.reason.opengl_not_supported=當前遊戲因為你的顯示卡驅動存在問題,無法繼續運行。\n原因是 OpenGL 不受支援,你現在是否在遠程桌面或者串流模式下?如果是,請直接使用原電腦啟動遊戲。\n或者嘗試升級你的顯示卡驅動到最新版本後再嘗試啟動遊戲。如果你的電腦存在獨立顯示卡,你需要檢查遊戲是否使用集成/核心顯示卡啟動,如果是,請嘗試使用獨立顯示卡啟動 HMCL 與遊戲。如果仍有問題,你可能需要考慮換一個新顯示卡或新電腦。 -game.crash.reason.openj9=當前遊戲無法運行在 OpenJ9 虛擬機上,請你在遊戲設置中更換 Hotspot Java 虛擬機,並重新啟動遊戲。如果沒有下載安裝,你可以在網路上自行下載。 -game.crash.reason.out_of_memory=當前遊戲因為記憶體不足,無法繼續運行。\n這可能是記憶體分配太小,或者 Mod 數量過多導致的。\n你可以在遊戲設置中調大遊戲記憶體分配值以允許遊戲在更大的記憶體下運行。\n如果仍然出現該錯誤,你可能需要換一台更好的電腦。 -game.crash.reason.processing_of_javaagent_failed=當前遊戲因為加載 -javaagent 參數失敗,無法繼續運行。\n如果你在 Java 虛擬機參數 中添加了相關參數,請檢查是否正確。\n如果你沒有添加相關參數或參數確認正確, 請嘗試:\n打開 控制面板 -- 時鐘和區域 分類(選項為類別顯示才有此選項,沒有就跳過)-- 區域 -- 上方的 管理 選項卡 -- 下方的 更改系統區域設置 按鈕 -- 在彈出的視窗中將 “使用Unicode UTF-8提供全球語言支持” 選項關閉,重啓設備後再嘗試啟動遊戲。\n可在 DiscordQQ 群尋求幫助 -game.crash.reason.resolution_too_high=當前遊戲因為材質包解析度過高,無法繼續運行\n你可以更換一個解析度更低的材質,或者更換一個視訊記憶體更大的顯示卡。 -game.crash.reason.stacktrace=原因未知,請點擊日誌按鈕查看詳細訊息。\n下面是一些關鍵字,其中可能包含 Mod 名稱,你可以透過搜索的方式查找有關訊息。\n%s -game.crash.reason.too_old_java=當前遊戲因為 Java 虛擬機版本過低,無法繼續運行。\n你需要在遊戲設置中更換 %1$s 或更新版本的 Java 虛擬機,並重新啟動遊戲。如果沒有下載安裝,你可以點擊 此處 下載微軟 JDK。 +game.crash.reason.forge_repeat_installation=目前遊戲由於 Forge 重複安裝,無法繼續執行。此為已知問題\n建議將日誌上傳並回報至 GitHub,以便我們找到更多線索並修復此問題。\n目前你可以在「實例管理 → 自動安裝」中移除 Forge 並重新安裝。 +game.crash.reason.optifine_repeat_installation=目前遊戲由於重複安裝 OptiFine,無法繼續執行。\n請刪除模組目錄下的 OptiFine 或前往「實例管理 → 自動安裝」移除安裝的 OptiFine。 +game.crash.reason.optifine_is_not_compatible_with_forge=目前遊戲由於 OptiFine 與目前版本的 Forge 不相容,導致了遊戲崩潰。\n請前往 OptiFine 官網查看 OptiFine 所相容的 Forge 版本,並嚴格按照對應版本重新安裝遊戲,或在「實例管理 → 自動安裝」中更換版本。\n經測試,Forge 版本過高或過低都可能導致崩潰。 +game.crash.reason.night_config_fixes=目前遊戲由於 Night Config 庫的一些問題,無法繼續執行。\n你可以嘗試安裝 Night Config Fixes 模組,這或許能幫助你解決這個問題。\n了解更多,可訪問該模組的 GitHub 倉庫。 +game.crash.reason.mod_files_are_decompressed=目前遊戲由於模組檔案被解壓了,無法繼續執行。\n請直接把整個模組檔案放進模組目錄中即可。\n若解壓就會導致遊戲出錯,請刪除模組目錄中已被解壓的模組,然後再啟動遊戲。 +game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=目前遊戲由於你所安裝的模組過多,超出了遊戲的 ID 限制,無法繼續執行。\n請嘗試安裝JEID等修正模組,或刪除部分大型模組。 +game.crash.reason.optifine_causes_the_world_to_fail_to_load=目前遊戲可能由於 OptiFine 而無法繼續執行。\n該問題只在特定 OptiFine 版本中出現,你可以嘗試在「實例管理 → 自動安裝」中更換 OptiFine 的版本。 +game.crash.reason.modlauncher_8=目前遊戲由於你所使用的 Forge 版本與目前使用的 Java 衝突崩潰,請嘗試更新 Forge。 +game.crash.reason.shaders_mod=目前遊戲由於同時安裝了 OptiFine 和 Shaders 模組,無法繼續執行。 \n由於 OptiFine 已整合 Shaders 模組的功能,只需刪除 Shaders 模組即可。 +game.crash.reason.rtss_forest_sodium=目前遊戲由於 RivaTuner Statistics Server (RTSS) 與 Sodium 不相容,導致遊戲崩潰。\n點擊 此處 查看詳情。 +game.crash.reason.no_class_def_found_error=目前遊戲由於程式碼不完整,無法繼續執行。\n你的遊戲可能缺失了某個模組,或者某些模組檔案不完整,或者模組與遊戲的版本不匹配。\n你可能需要重新安裝遊戲和模組,或請求他人幫助。\n缺失:%1$s +game.crash.reason.no_such_method_error=目前遊戲由於程式碼不完整,無法繼續執行。\n你的遊戲可能缺失了某個模組,或者某些模組檔案不完整,或者模組與遊戲的版本不匹配。\n你可能需要重新安裝遊戲和模組,或請求他人幫助。 +game.crash.reason.opengl_not_supported=目前遊戲由於你的顯示卡驅動存在問題,無法繼續執行。\n原因是 OpenGL 不受支援,你現在是否在遠端桌面或者串流模式下?如果是,請直接使用原電腦啟動遊戲。\n或者嘗試升級你的顯示卡驅動到最新版本後再嘗試啟動遊戲。如果你的電腦存在獨立顯示卡,你需要檢查遊戲是否使用整合/核心顯示卡啟動,如果是,請嘗試使用獨立顯示卡開啟 HMCL 與遊戲。如果仍有問題,你可能需要考慮換一個新顯示卡或新電腦。 +game.crash.reason.openj9=目前遊戲無法執行在 OpenJ9 虛擬機上,請你在「(全域/實例特定) 遊戲設定 → 遊戲 Java」中更換 Hotspot Java 虛擬機,並重新啟動遊戲。如果沒有下載安裝,你可以在網路上自行下載。 +game.crash.reason.out_of_memory=目前遊戲由於記憶體不足,無法繼續執行。\n這可能是記憶體分配太小,或者模組數量過多導致的。\n你可以在「(全域/實例特定) 遊戲設定 → 遊戲記憶體」中調大遊戲記憶體分配值以允許遊戲在更大的記憶體下執行。\n如果仍然出現該錯誤,你可能需要換一台更好的電腦。 +game.crash.reason.resolution_too_high=目前遊戲由於資源包解析度過高,無法繼續執行。\n你可以更換一個解析度更低的資源包,或者更換一個視訊記憶體更大的顯示卡。 +game.crash.reason.stacktrace=原因未知,請點擊日誌按鈕查看詳細訊息。\n下面是一些關鍵字,其中可能包含模組名稱,你可以透過搜尋的方式尋找有關訊息。\n%s +game.crash.reason.too_old_java=目前遊戲由於 Java 虛擬機版本過低,無法繼續執行。\n你需要在「(全域/實例特定) 遊戲設定 → 遊戲 Java」中更換 %1$s 或更高版本的 Java 虛擬機,並重新啟動遊戲。如果沒有下載安裝,你可以點擊 此處 下載 Microsoft JDK。 game.crash.reason.unknown=原因未知,請點擊日誌按鈕查看詳細訊息。 -game.crash.reason.unsatisfied_link_error=當前遊戲因為缺少本地庫,無法繼續運行。\n這些本地庫缺失:%1$s。\n如果你在全局(特定)遊戲設置中修改了本地庫路徑選項,請你修改回預設模式。\n如果已經在預設模式下,請檢查本地庫缺失是否是 Mod 引起的,或由 HMCL 引起的。如果你確定是 HMCL 引起的,建議你向我們反饋。\n或將游戲路徑中的所有非英文字符的名稱修改為英文字符(例如中文,空格等)\n如果你確實需要自定義本地庫路徑,你需要保證其中包含缺失的本地庫! -game.crash.reason.failed_to_load_a_library=當前遊戲因為加載本地庫失敗,無法繼續運行。\n如果你在全局(特定)遊戲設置中修改了本地庫路徑選項,請你修改回預設模式。\n如果已經在預設模式下,請檢查本地庫缺失是否是 Mod 引起的,或由 HMCL 引起的。如果你確定是 HMCL 引起的,建議你向我們反饋。\n或將游戲路徑中的所有非英文字符的名稱修改為英文字符(例如中文,空格等)\n如果你確實需要自定義本地庫路徑,你需要保證其中包含缺失的本地庫! +game.crash.reason.unsatisfied_link_error=目前遊戲由於缺少本機庫,無法繼續執行。\n這些本機庫缺失:%1$s。\n如果你在「(全域/實例特定) 遊戲設定 → 進階設定」中修改了本機庫路徑選項,請你修改回預設模式。\n如果你正在使用預設模式,請檢查遊戲目錄路徑是否只包含英文字母、數字和底線,\n如果是,那麼請檢查是否為模組或 HMCL 導致了本機庫缺失的問題。如果你確定是 HMCL 引起的,建議你向我們回報。\n對於 Windows 使用者,你還可以嘗試在「控制台 → 時鐘和區域 → 地區 → 系統管理 → 變更系統區域設定」中,關閉「Beta:使用 Unicode UTF-8 提供全球語言支援」選項;\n或將遊戲目錄路徑中的所有非英文字母的名稱 (例如中文、空格等) 修改為英文字母。\n如果你確實需要自訂本機庫路徑,你需要保證其中包含缺失的本機庫! game.crash.title=遊戲意外退出 -game.directory=遊戲路徑 +game.directory=遊戲目錄路徑 game.version=遊戲版本 help=說明 From dcfcd1d8b20f371d38dbb2ef44590714ebbf8b3d Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Fri, 25 Oct 2024 02:25:26 +0800 Subject: [PATCH 058/169] Revise zh_TW part 3 (#3358) * Revise zh_TW part 3 * Update * Update * fix typo * fix * fix * oops... * fix * fix main page hint * Update HMCL/src/main/resources/assets/lang/I18N_zh.properties --------- Co-authored-by: Glavo --- .../resources/assets/lang/I18N_zh.properties | 243 +++++++++--------- 1 file changed, 119 insertions(+), 124 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 3ffd65a017..9e6edc6c13 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -465,55 +465,55 @@ game.directory=遊戲目錄路徑 game.version=遊戲版本 help=說明 -help.doc=Hello Minecraft! Launcher 說明檔案 -help.detail=可查閱資料包、模組包製作指南等內容。 +help.doc=Hello Minecraft! Launcher 說明文件 +help.detail=可查閱資料包、模組包製作教學等內容 input.email=[使用者名稱] 必須是電子信箱格式 input.number=必須是數字 input.not_empty=必填 input.url=必須是有效連結 -install=新增遊戲 +install=新增實例 install.change_version=變更版本 -install.change_version.confirm=你確定要 %s 從 %s 更新到 %s 嗎? +install.change_version.confirm=你確定要將 %s 從 %s 更新到 %s 嗎? install.failed=安裝失敗 install.failed.downloading=安裝失敗,部分檔案未能完成下載 install.failed.downloading.detail=未能下載檔案: %s install.failed.downloading.timeout=下載逾時: %s -install.failed.install_online=無法識別要安裝的軟體。如果你要安裝 Mod,你需要在模組管理頁面安裝模組。 -install.failed.malformed=剛才下載的檔案格式損壞。您可以切換到其他下載來源以解決此問題。 -install.failed.optifine_conflict=暫不支援 OptiFine 與 Forge 同時安裝在 Minecraft 1.13 上 -install.failed.optifine_forge_1.17=Minecraft 1.17.1 下,僅 OptiFine H1 Pre2 及以上版本能相容 Forge。你可以從 OptiFine 測試版中選擇最新版本。 -install.failed.version_mismatch=該軟體需要的遊戲版本為 %s,但實際的遊戲版本為 %s。 -install.installer.change_version=%s 與當前遊戲不相容,請更換版本 -install.installer.choose=選擇 %s 版本 +install.failed.install_online=無法識別要安裝的載入器。如果你要安裝模組,你需要在模組管理頁面安裝模組。 +install.failed.malformed=剛才下載的檔案已損壞。你可以在「設定 → 下載 → 下載來源」中切換其他下載來源以解決此問題。 +install.failed.optifine_conflict=暫不支援 OptiFine 與 Fabric 同時安裝在 Minecraft 1.13 上。 +install.failed.optifine_forge_1.17=對於 Minecraft 1.17.1 版本,僅 OptiFine H1 pre2 及更高版本與 Forge 相容。你可以從 OptiFine 預覽版 (Preview versions) 中選取最新版本。 +install.failed.version_mismatch=該載入器需要的遊戲版本為 %s,但實際的遊戲版本為 %s。 +install.installer.change_version=%s 與目前遊戲不相容,請更換版本 +install.installer.choose=選取 %s 版本 install.installer.depend=需要先安裝 %s install.installer.fabric=Fabric install.installer.fabric-api=Fabric API -install.installer.fabric-api.warning=警告:Fabric API 是 Mod,將會被安裝到新遊戲的 Mod 資料夾,請你在安裝遊戲後不要修改當前遊戲的版本隔離/遊戲運行路徑設置,如果你在之後修改了相關設置,Fabric API 需要被重新安裝。 +install.installer.fabric-api.warning=警告:Fabric API 是模組,將會被安裝到新遊戲的模組目錄,請你在安裝遊戲後不要修改目前遊戲的「執行路徑」設定,如果你在之後修改了相關設定,則需要重新安裝 Fabric API。 install.installer.forge=Forge install.installer.neoforge=NeoForge install.installer.game=Minecraft install.installer.incompatible=與 %s 不相容 install.installer.install=安裝 %s install.installer.install_offline=從本機檔案安裝或升級 -install.installer.install_offline.extension=Forge/OptiFine 安裝器 -install.installer.install_offline.tooltip=支援匯入已經下載好的 Forge/OptiFine 安裝器 +install.installer.install_offline.extension=(Neo)Forge/OptiFine 安裝器 +install.installer.install_offline.tooltip=支援匯入已經下載好的 (Neo)Forge/OptiFine 安裝器 install.installer.install_online=線上安裝 -install.installer.install_online.tooltip=支援安裝 Fabric、Forge、OptiFine、LiteLoader +install.installer.install_online.tooltip=支援安裝 Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine install.installer.liteloader=LiteLoader install.installer.not_installed=不安裝 install.installer.optifine=OptiFine install.installer.quilt=Quilt install.installer.quilt-api=QSL/QFAPI install.installer.version=%s -install.installer.external_version=%s 由外部安裝的版本,無法解除安裝或更換 +install.installer.external_version=%s [由外部安裝的版本,無法解除安裝或更換] install.modpack=安裝模組包 -install.new_game=安裝新遊戲版本 -install.new_game.already_exists=此版本已經存在,請重新命名 +install.new_game=安裝新實例 +install.new_game.already_exists=此實例已經存在,請重新命名 install.new_game.current_game_version=目前遊戲版本 install.new_game.malformed=名稱無效 -install.select=請選擇安裝方式 +install.select=請選取安裝方式 install.success=安裝成功 java.add=添加 Java @@ -539,160 +539,159 @@ java.install=安裝 Java java.install.archive=源路徑 java.install.failed.exists=該名稱已被使用 java.install.failed.invalid=該檔案不是合法的 Java 安裝包,無法繼續安裝。 -java.install.failed.unsupported_platform=此 Java 與當前平臺不相容,無法安裝。 +java.install.failed.unsupported_platform=此 Java 與目前平臺不相容,無法安裝。 java.install.name=名稱 -java.install.warning.invalid_character=名稱中包含非法字元 +java.install.warning.invalid_character=名稱中包含無效字元 java.reveal=瀏覽 Java 目錄 java.uninstall=移除此 Java java.uninstall.confirm=你確定要移除此 Java 嗎?此操作無法復原! -lang=正體中文 +lang=繁體中文 lang.default=使用系統語言 -launch.advice=%s是否繼續啟動? +launch.advice=%s 是否繼續啟動? launch.advice.multi=檢測到以下問題:\n\n%s\n\n這些問題可能導致遊戲無法正常啟動或影響遊戲體驗,是否繼續啟動? -launch.advice.java.auto=當前選擇的 Java 虛擬機版本不滿足遊戲要求,是否自動選擇合適的 Java 虛擬機版本?或者你可以到遊戲設置中選擇一個合適的 Java 虛擬機版本。 -launch.advice.java.modded_java_7=Minecraft 1.7.2 及以下版本需要 Java 7 及以下版本。 -launch.advice.corrected=我們已經修正了問題。如果確實希望使用你自訂的 Java 虛擬機,你可以在遊戲設定中關閉 Java 虛擬機相容性檢查。 -launch.advice.uncorrected=如果你確實希望使用你自訂的 Java 虛擬機,你可以在遊戲設定中關閉 Java 虛擬機相容性檢查。 +launch.advice.java.auto=目前選取的 Java 虛擬機版本不滿足遊戲要求,是否自動選取合適的 Java 虛擬機版本?\n或者你可以到「(全域/實例特定) 遊戲設定 → 遊戲 Java」中選取一個合適的 Java 虛擬機版本。 +launch.advice.java.modded_java_7=Minecraft 1.7.2 及更低版本需要 Java 7 及更低版本。 +launch.advice.corrected=我們已經修正了問題。如果你確實希望使用你自訂的 Java 虛擬機,你可以在「(全域/實例特定) 遊戲設定 → 進階設定」中往下滑,開啟「不檢查 JVM 與遊戲的相容性」。 +launch.advice.uncorrected=如果你確實希望使用你自訂的 Java 虛擬機,你可以在「(全域/實例特定) 遊戲設定 → 進階設定」中往下滑,開啟「不檢查 JVM 與遊戲的相容性」。 launch.advice.different_platform=你正在使用 32 位元 Java 啟動遊戲,建議更換至 64 位元 Java。 -launch.advice.forge2760_liteloader=Forge 2760 與 LiteLoader 不相容,請更新 Forge 到 2773 或更新的版本。 -launch.advice.forge28_2_2_optifine=Forge 28.2.2 或更高版本與 OptiFine 不相容,請将 Forge 降級至 28.2.1 或更低版本。 -launch.advice.forge37_0_60=Forge 低於 37.0.60 的版本不相容 Java 17。請更新 Forge 到 37.0.60 或更高版本,或者使用 Java 16 啟動遊戲。 -launch.advice.java8_1_13=Minecraft 1.13 只支援 Java 8 或更高版本,請使用 Java 8 或最新版本。 +launch.advice.forge2760_liteloader=Forge 14.23.5.2760 與 LiteLoader 不相容,請更新 Forge 至 14.23.5.2773 或更高版本。 +launch.advice.forge28_2_2_optifine=Forge 28.2.2 及更高版本與 OptiFine 不相容,請降級 Forge 至 28.2.1 或更低版本。 +launch.advice.forge37_0_60=Forge 37.0.59 及更低版本與 Java 17 不相容。請更新 Forge 到 37.0.60 或更高版本,或者使用 Java 16 啟動遊戲。 +launch.advice.java8_1_13=Minecraft 1.13 及更高版本僅支援 Java 8 或更高版本,請使用 Java 8 或最新版本。 launch.advice.java8_51_1_13=低於 1.8.0_51 的 Java 版本可能會導致 Minecraft 1.13 崩潰。建議你到 https://java.com 安裝最新版的 Java 8。 -launch.advice.java9=低於 (包含) 1.13 的有安裝 Mod 的 Minecraft 版本不支援 Java 9 或更高版本,請使用 Java 8。 -launch.advice.modded_java=部分 Mod 可能與高版本 Java 不相容,建議使用 Java %s 啟動 Minecraft %s。 -launch.advice.modlauncher8=你所使用的 Forge 版本與當前使用的 Java 不相容,請更新 Forge。 -launch.advice.newer_java=偵測到你正在使用舊版本 Java 啟動遊戲,這可能導致部分 Mod 引發遊戲崩潰,建議更新至 Java 8 後再次啟動。 -launch.advice.not_enough_space=你設定的記憶體大小過大,由於超過了系統記憶體大小 %dMB,所以可能影響遊戲體驗或無法啟動遊戲。 -launch.advice.require_newer_java_version=當前遊戲版本需要 Java %s,但 HMCL 未能找到該 Java 版本,你可以點擊“是”,HMCL 會自動下載他,是否下載? -launch.advice.too_large_memory_for_32bit=你設定的記憶體大小過大,由於可能超過了 32 位元 Java 的記憶體分配限制,所以可能無法啟動遊戲,請將記憶體調至低於 1024MB 的值。 -launch.advice.vanilla_linux_java_8=對於 Linux x86-64 平台,Minecraft 1.12.2 及以下版本與 Java 9+ 不相容,請使用 Java 8 啟動遊戲。 -launch.advice.vanilla_x86.translation=Minecraft 尚未為你的平臺提供完善支持,所以可能影響遊戲體驗或無法啟動遊戲。\n你可以在 這裡 下載 X86-64 架構的 Java 以獲得更完整的體驗。\n是否繼續啟動? +launch.advice.java9=低於 (包含) 1.13 的有安裝模組的 Minecraft 版本不支援 Java 9 或更高版本,請使用 Java 8。 +launch.advice.modded_java=部分模組可能與高版本 Java 不相容,建議使用 Java %s 啟動 Minecraft %s。 +launch.advice.modlauncher8=你所使用的 Forge 版本與目前使用的 Java 不相容。請更新 Forge。 +launch.advice.newer_java=偵測到你正在使用舊版本 Java 啟動遊戲,這可能導致部分模組引發遊戲崩潰,建議更新至 Java 8 後再次啟動。 +launch.advice.not_enough_space=你設定的記憶體大小過大,由於超過了系統記憶體大小 %d MB,所以可能影響遊戲體驗或無法啟動遊戲。 +launch.advice.require_newer_java_version=目前遊戲版本需要 Java %s,但 HMCL 未能找到該 Java 版本,你可以點擊「是」,HMCL 會自動下載他,是否下載? +launch.advice.too_large_memory_for_32bit=你設定的記憶體大小過大,由於可能超過了 32 位元 Java 的記憶體分配限制,所以可能無法啟動遊戲,請將記憶體調至低於 1024 MB 的值。 +launch.advice.vanilla_linux_java_8=對於 Linux x86-64 平台,Minecraft 1.12.2 及更低版本與 Java 9+ 不相容,請使用 Java 8 啟動遊戲。 +launch.advice.vanilla_x86.translation=Minecraft 尚未為你的平臺提供完善支援,所以可能影響遊戲體驗或無法啟動遊戲。\n你可以在 這裡 下載 x86-64 架構的 Java 以獲得更完整的體驗。\n是否繼續啟動? launch.advice.unknown=由於以下原因,無法繼續啟動遊戲: launch.failed=啟動失敗 -launch.failed.cannot_create_jvm=偵測到無法建立 Java 虛擬機,可能是 Java 參數有問題。可以在設定中開啟無參數模式啟動。 +launch.failed.cannot_create_jvm=無法建立 Java 虛擬機,可能是 Java 參數有問題。可以在「(全域/實例特定) 遊戲設定 → 進階設定 → Java 虛擬機設定」中移除所有 Java 虛擬機參數後,嘗試再次啟動遊戲。 launch.failed.creating_process=啟動失敗,在建立新處理程式時發生錯誤。可能是 Java 路徑錯誤。 -launch.failed.command_too_long=命令長度超過限制,無法創建 bat 腳本,請匯出為 PowerShell 腳本。 -launch.failed.decompressing_natives=無法解壓縮遊戲資源庫。 -launch.failed.download_library=無法下載遊戲相依元件 %s。 +launch.failed.command_too_long=指令長度超過限制,無法建立批次檔指令碼,請匯出為 PowerShell 指令碼。 +launch.failed.decompressing_natives=無法解壓縮遊戲本機庫。 +launch.failed.download_library=無法下載遊戲相依元件「%s」。 launch.failed.executable_permission=無法為啟動檔案新增執行權限。 launch.failed.execution_policy=設定執行策略 launch.failed.execution_policy.failed_to_set=設定執行策略失敗 -launch.failed.execution_policy.hint=當前執行策略封锁你執行 PowerShell 腳本。\n點擊“確定”允許當前用戶執行本地 PowerShell 腳本,或點擊“取消”保持現狀。 -launch.failed.exited_abnormally=遊戲非正常退出,請查看記錄檔案,或聯絡他人尋求幫助。 +launch.failed.execution_policy.hint=目前執行策略封鎖你執行 PowerShell 指令碼。\n點擊「確定」允許目前使用者執行本機 PowerShell 指令碼,或點擊「取消」保持現狀。 +launch.failed.exited_abnormally=遊戲非正常退出,請查看日誌檔案,或聯絡他人尋求幫助。 launch.failed.java_version_too_low=你所指定的 Java 版本過低,請重新設定 Java 版本。 -launch.failed.no_accepted_java=找不到適合當前遊戲使用的 Java,是否使用默認 Java 啟動遊戲?點擊“是”使用默認 Java 繼續啟動遊戲,\n或者請到遊戲設定中選擇一個合適的Java虛擬機器版本。 -launch.failed.sigkill=遊戲被用戶或系統強制終止。 +launch.failed.no_accepted_java=找不到適合目前遊戲使用的 Java,是否使用預設 Java 啟動遊戲?點擊「是」使用預設 Java 繼續啟動遊戲,\n或者請到「(全域/實例特定) 遊戲設定 → 遊戲 Java」中選取一個合適的 Java 虛擬機版本。 +launch.failed.sigkill=遊戲被使用者或系統強制終止。 launch.state.dependencies=處理遊戲相依元件 launch.state.done=啟動完成 launch.state.java=檢測 Java 版本 launch.state.logging_in=登入 launch.state.modpack=下載必要檔案 launch.state.waiting_launching=等待遊戲啟動 -launch.invalid_java=當前設定的 Java 路徑無效,請重新設定 Java 路徑。 +launch.invalid_java=目前設定的 Java 路徑無效,請重新設定 Java 路徑。 launcher=啟動器 -launcher.agreement=用戶協議與免責聲明 +launcher.agreement=使用者協議與免責宣告 launcher.agreement.accept=同意 launcher.agreement.decline=拒絕 -launcher.agreement.hint=同意本軟體的用戶協議與免責聲明以使用本軟體。 -launcher.background=背景位址 -launcher.background.choose=選擇背景路徑 +launcher.agreement.hint=同意本軟體的使用者協議與免責宣告以使用本軟體。 +launcher.background=背景圖片 +launcher.background.choose=選取背景圖片 launcher.background.classic=經典 -launcher.background.default=預設(自動尋找啟動器同目錄下的 background.png/jpg/gif 及 bg 資料夾內的圖片) +launcher.background.default=預設 (自動尋找啟動器同目錄下的「background.png/.jpg/.gif」及「bg」目錄內的圖片) launcher.background.network=網路 launcher.background.translucent=半透明 launcher.cache_directory=檔案下載快取目錄 launcher.cache_directory.clean=清理 -launcher.cache_directory.choose=選擇檔案下載快取目錄 -launcher.cache_directory.default=預設 +launcher.cache_directory.choose=選取檔案下載快取目錄 +launcher.cache_directory.default=預設 ("%AppData%/.minecraft" 或 "~/.minecraft") launcher.cache_directory.disabled=停用 launcher.cache_directory.invalid=無法建立自訂的快取目錄,還原至預設設定 launcher.contact=聯絡我們 -launcher.crash=Hello Minecraft! Launcher 遇到了無法處理的錯誤,請複製下列內容並透過 MCBBS、貼吧、GitHub 或 Minecraft Forum 回報 bug。 -launcher.crash.java_internal_error=HHello Minecraft! Launcher 由於當前 Java 損壞而無法繼續運行,請移除當前 Java,點擊 此處 安裝合適的 Java 版本。 -launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher 遇到了無法處理的錯誤,已偵測到您的啟動器不是最新版本,請更新後重試! +launcher.crash=Hello Minecraft! Launcher 遇到了無法處理的錯誤,請複製下列內容並透過 GitHub、Discord 或 HMCL QQ 群回報問題。 +launcher.crash.java_internal_error=Hello Minecraft! Launcher 由於目前 Java 損壞而無法繼續執行,請移除目前 Java,點擊 此處 安裝合適的 Java 版本。 +launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher 遇到了無法處理的錯誤,已偵測到你的啟動器不是最新版本,請更新後重試! launcher.update_java=請更新你的 Java -login.empty_username=你還未設定使用者名稱! -login.enter_password=請輸入您的密碼 +login.empty_username=你還未設定使用者名稱! +login.enter_password=請輸入你的密碼 logwindow.show_lines=顯示行數 logwindow.terminate_game=結束遊戲處理程式 -logwindow.title=記錄 -logwindow.help=你可以前往 HMCL 社區,尋找他人幫助 +logwindow.title=日誌 +logwindow.help=你可以前往 HMCL 社群,向他人尋求幫助 logwindow.autoscroll=自動滾動 -logwindow.export_game_crash_logs=導出遊戲崩潰訊息 -logwindow.export_dump=導出遊戲運行棧 -logwindow.export_dump.no_dependency=你的 Java 不包含用於創建遊戲運行棧的依賴。請前往 HMCL QQ 群或 Discord 频道尋求幫助。 +logwindow.export_game_crash_logs=匯出遊戲崩潰訊息 +logwindow.export_dump=匯出遊戲執行堆疊 +logwindow.export_dump.no_dependency=你的 Java 不包含用於建立遊戲執行堆疊的相依元件。請前往 Discord 或 HMCL QQ 群尋求幫助。 main_page=首頁 message.cancelled=操作被取消 message.confirm=提示 -message.copied=已複製到剪貼板 +message.copied=已複製到剪貼簿 message.default=預設 message.doing=請耐心等待 -message.downloading=正在下載… +message.downloading=正在下載…… message.error=錯誤 message.failed=操作失敗 -message.info=資訊 +message.info=提示 message.success=完成 message.unknown=未知 message.warning=警告 modpack=模組包 -modpack.choose=選擇要安裝的遊戲模組包檔案 +modpack.choose=選取要安裝的遊戲模組包檔案 modpack.choose.local=匯入本機模組包檔案 modpack.choose.local.detail=你可以直接將模組包檔案拖入本頁面以安裝 modpack.choose.remote=從網路下載模組包 modpack.choose.remote.detail=需要提供模組包的下載連結 -modpack.choose.repository= 從 Curseforge / Modrinth 下載整合包 -modpack.choose.repository.detail=下載后記得回到這個界面,把整合包拖進來哦 +modpack.choose.repository=從 CurseForge/Modrinth 下載模組包 +modpack.choose.repository.detail=下載後記得回到這個介面,把模組包拖進來哦 modpack.choose.remote.tooltip=要下載的模組包的連結 modpack.completion=下載模組包相關檔案 -modpack.desc=描述你要製作的模組包,比如模組包注意事項和更新記錄,支援 Markdown(圖片請上傳至網路)。 +modpack.desc=描述你要製作的模組包,比如模組包注意事項和更新紀錄,支援 Markdown (圖片請上傳至網路)。 modpack.description=模組包描述 modpack.download=下載模組包 modpack.enter_name=給遊戲取個你喜歡的名稱 modpack.export=匯出模組包 -modpack.export.as=請選擇模組包類型。若你無法決定,請選擇 HMCL 類型。 +modpack.export.as=請選取模組包類型。若你無法決定,請選取 MCBBS 類型。 modpack.file_api=模組包下載連結前綴 modpack.files.blueprints=BuildCraft 藍圖 -modpack.files.config=Mod 模組設定檔案 +modpack.files.config=模組設定檔案 modpack.files.dumps=NEI 調校輸出 modpack.files.hmclversion_cfg=啟動器設定檔案 -modpack.files.liteconfig=Mod 模組設定檔案 -modpack.files.mods=Mod 模組 +modpack.files.liteconfig=LiteLoader 相關檔案 +modpack.files.mods=模組 modpack.files.mods.voxelmods=VoxelMods 設定,如小地圖 modpack.files.options_txt=遊戲設定 modpack.files.optionsshaders_txt=光影設定 -modpack.files.resourcepacks=資源包 (材質包) +modpack.files.resourcepacks=資源包 (紋理包) modpack.files.saves=遊戲存檔 modpack.files.scripts=MineTweaker 設定 -modpack.files.servers_dat=多人遊戲伺服器列表 +modpack.files.servers_dat=多人遊戲伺服器清單 modpack.install=安裝 %s 模組包 modpack.installing=正在安裝模組包 modpack.introduction=支援 Curse、Modrinth、MultiMC、MCBBS 模組包。 modpack.invalid=無效的模組包升級檔案,可能是下載時出現問題。 -modpack.mismatched_type=模組包類型不符,目前遊戲是 %s 模組包,但是提供的模組包更新檔案是 %s 模組包。 +modpack.mismatched_type=模組包類型不符,目前遊戲是「%s」模組包,但是提供的模組包更新檔案是「%s」模組包。 modpack.name=模組包名稱 modpack.not_a_valid_name=模組包名稱無效 modpack.origin=來源 modpack.origin.url=官方網站 modpack.origin.mcbbs=MCBBS -modpack.origin.mcbbs.prompt=貼子 id +modpack.origin.mcbbs.prompt=帖子 ID modpack.scan=解析模組包 modpack.task.install=匯入模組包 -modpack.task.install.error=無法識別該模組包,目前僅支援匯入 Curse、Modrinth、MultiMC、MCBBS 模組包。 +modpack.task.install.error=無法識別該模組包,目前僅支援匯入 Curse、Modrinth、MultiMC 和 MCBBS 模組包。 modpack.type.curse=Curse -modpack.type.curse.tolerable_error=但未能完成該模組包檔案的下載,您可以在啟動該遊戲版本時繼續該模組包檔案的下載。由於網路問題,您可能需要重試多次…… -modpack.type.curse.error=無法完成該模組包所需的依賴下載,請多次重試或設定代理…… +modpack.type.curse.error=無法完成該模組包所需的相依元件下載,請多次重試或設定代理…… modpack.type.curse.not_found=部分必需檔案已經從網路中被刪除並且再也無法下載,請嘗試該模組包的最新版本或者安裝其他模組包。 -modpack.type.manual.warning=該模組包由發佈者手動打包,其中可能已經包含啟動器,建議嘗試解壓後使用其自帶的啟動器運行遊戲。\nHMCL 可以嘗試導入該模組包,但不保證可用性,是否繼續? -modpack.type.mcbbs=我的世界中文論壇模組包標準 +modpack.type.manual.warning=該模組包由發佈者手動打包,其中可能已經包含啟動器,建議嘗試解壓後使用其內建的啟動器執行遊戲。\nHMCL 可以嘗試匯入該模組包,但不保證可用性,是否繼續? +modpack.type.mcbbs=MCBBS modpack.type.mcbbs.export=可以被 Hello Minecraft! Launcher 匯入 modpack.type.modrinth=Modrinth modpack.type.multimc=MultiMC @@ -700,20 +699,20 @@ modpack.type.multimc.export=可以被 Hello Minecraft! Launcher 和 MultiMC 匯 modpack.type.server=伺服器自動更新模組包 modpack.type.server.export=允許伺服器管理員遠端更新遊戲用戶端 modpack.type.server.malformed=伺服器模組包配置格式錯誤,請聯絡伺服器管理員解決此問題 -modpack.unsupported=Hello Minecraft! Launcher 不支持該綜合包格式 +modpack.unsupported=Hello Minecraft! Launcher 不支援該模組包格式 modpack.update=正在升級模組包 modpack.wizard=匯出模組包引導 modpack.wizard.step.1=基本設定 modpack.wizard.step.1.title=設定模組包的主要訊息 -modpack.wizard.step.2=檔案選擇 -modpack.wizard.step.2.title=選中你想加到模組包中的檔案或資料夾 +modpack.wizard.step.2=選取檔案 +modpack.wizard.step.2.title=選中你想加到模組包中的檔案或目錄 modpack.wizard.step.3=模組包類型 -modpack.wizard.step.3.title=選擇模組包匯出類型 +modpack.wizard.step.3.title=選取模組包匯出類型 modpack.wizard.step.initialization.exported_version=要匯出的遊戲版本 -modpack.wizard.step.initialization.force_update=強制升級模組包至最新版本(需要自建伺服器) +modpack.wizard.step.initialization.force_update=強制升級模組包至最新版本 (需要自建伺服器) modpack.wizard.step.initialization.include_launcher=包含啟動器 -modpack.wizard.step.initialization.save=選擇要匯出到的遊戲模組包位置 -modpack.wizard.step.initialization.warning=在製作模組包前,請您確認您選擇的版本可以正常啟動,\n並保證您的 Minecraft 是正式版而非快照,\n而且不應將不允許非官方途徑傳播的 Mod 模組、材質包等納入模組包。\n模組包會儲存您目前的下載來源設定 +modpack.wizard.step.initialization.save=選取要匯出到的遊戲模組包位置 +modpack.wizard.step.initialization.warning=在製作模組包前,請你確認你選取的實例可以正常啟動,\n並保證你的 Minecraft 是正式版而非快照,\n而且不應將不允許非官方途徑傳播的模組、資源 (紋理) 包等納入模組包。\n模組包會儲存你目前的下載來源設定。 modpack.wizard.step.initialization.server=點選此處查看有關伺服器自動更新模組包的製作教學 modrinth.category.adventure=冒險 @@ -722,7 +721,7 @@ modrinth.category.blocks=方塊 modrinth.category.bukkit=Bukkit modrinth.category.bungeecord=BungeeCord modrinth.category.challenging=高難度 -modrinth.category.core-shaders=覈心著色器 +modrinth.category.core-shaders=核心著色器 modrinth.category.combat=戰鬥 modrinth.category.cursed=Cursed modrinth.category.decoration=裝飾 @@ -738,7 +737,7 @@ modrinth.category.game-mechanics=遊戲機制 modrinth.category.gui=GUI modrinth.category.items=物品 modrinth.category.kitchen-sink=大雜燴 -modrinth.category.library=支持庫 +modrinth.category.library=支援庫 modrinth.category.lightweight=輕量 modrinth.category.liteloader=LiteLoader modrinth.category.locale=在地化 @@ -750,7 +749,7 @@ modrinth.category.misc=其他 modrinth.category.mobs=生物 modrinth.category.modded=Modded modrinth.category.models=模型 -modrinth.category.modloader=Modloader +modrinth.category.modloader=ModLoader modrinth.category.multiplayer=多人 modrinth.category.neoforge=NeoForge modrinth.category.optimization=最佳化 @@ -768,13 +767,13 @@ modrinth.category.storage=儲存 modrinth.category.technology=科技 modrinth.category.themed=主題 modrinth.category.transportation=運輸 -modrinth.category.tweaks=優化 +modrinth.category.tweaks=最佳化 modrinth.category.utility=實用 modrinth.category.vanilla-like=類原生 modrinth.category.velocity=Velocity modrinth.category.waterfall=Waterfall modrinth.category.worldgen=世界生成 -modrinth.category.datapack=數據包 +modrinth.category.datapack=資料包 modrinth.category.folia=Folia mods=模組 @@ -782,7 +781,7 @@ mods.add=新增模組 mods.add.failed=新增模組「%s」失敗。 mods.add.success=成功新增模組「%s」。 mods.broken_dependency.title=損壞的相依模組 -mods.broken_dependency.desc=該相依模組曾經在該平臺上存在過,但現在被刪除了,換個下載源試試吧。 +mods.broken_dependency.desc=該相依模組曾經存在於模組倉庫中,但現在已被刪除,請嘗試其他下載源。 mods.category=類別 mods.channel.alpha=Alpha mods.channel.beta=Beta @@ -803,7 +802,7 @@ mods.dependency.required=必需相依模組 (必須單獨下載,缺少可能 mods.dependency.tool=相依庫 (必須單獨下載,缺少可能會導致遊戲無法啟動) mods.dependency.include=內建相依模組 (作者已經打包在模組檔中,無需單獨下載) mods.dependency.incompatible=不相容模組 (同時安裝此模組和正在下載的模組會導致遊戲無法啟動) -mods.dependency.broken=損壞的相依模組 (這個模組曾經存在於平臺中,但現在已被刪除,請嘗試其他下載源) +mods.dependency.broken=損壞的相依模組 (該模組曾經存在於模組倉庫中,但現在已被刪除,請嘗試其他下載源) mods.disable=停用 mods.download=模組下載 mods.download.title=模組下載 - %1s @@ -888,7 +887,7 @@ world.name=世界名稱 world.name.enter=輸入世界名稱 world.reveal=開啟目錄 world.show_all=全部顯示 -world.time=yyyy/M/d HH:mm:ss +world.time=yyyy 年 M 月 d 日, HH:mm:ss profile=遊戲目錄 profile.already_exists=該名稱已存在 @@ -906,7 +905,7 @@ profile.use_relative_path=如可行,則對於遊戲目錄使用相對路徑 repositories.custom=自訂 Maven 倉庫 (%s) repositories.maven_central=全球 (Maven Central) repositories.tencentcloud_mirror=中國大陸 (騰訊雲 Maven 倉庫) -repositories.chooser=缺少 JavaFX 執行環境,HMCL 需要 JavaFX 才能正常執行。\n點擊「確認」從指定下載源下載 JavaFX 執行時元件並啟動 HMCL,點擊「取消」退出程式。\n選取下載源: +repositories.chooser=缺少 JavaFX 執行環境,HMCL 需要 JavaFX 才能正常執行。\n點擊「確認」從指定下載源下載 JavaFX 執行時元件並開啟 HMCL,點擊「取消」退出程式。\n選取下載源: repositories.chooser.title=選取 JavaFX 下載源 resourcepack=資源包 @@ -956,7 +955,7 @@ settings.advanced.jvm=Java 虛擬機設定 settings.advanced.jvm_args=Java 虛擬機參數 settings.advanced.jvm_args.prompt=\ · 若在「Java 虛擬機參數」中輸入的參數與預設參數相同,則不會加入;\n\ \ · 在「Java 虛擬機參數」輸入任何 GC 參數,預設參數的 G1 參數會禁用;\n\ - \ · 點擊下方「不使用預設的 JVM 參數」可在啟動遊戲時不加入預設參數。 + \ · 點擊下方「不加入預設的 JVM 參數」可在啟動遊戲時不加入預設參數。 settings.advanced.launcher_visibility.close=遊戲啟動後結束啟動器 settings.advanced.launcher_visibility.hide=遊戲啟動後隱藏啟動器 settings.advanced.launcher_visibility.hide_and_reopen=隱藏啟動器並在遊戲結束後重新開啟 @@ -969,7 +968,7 @@ settings.advanced.natives_directory.choose=選取本機庫路徑 settings.advanced.natives_directory.custom=自訂 (由你提供遊戲需要的本機庫) settings.advanced.natives_directory.default=預設 (由啟動器提供遊戲本機庫) settings.advanced.natives_directory.hint=本選項提供給 Apple M1 等未受遊戲官方支援的平台來自訂遊戲本機庫,如果你不知道本選項的含義,請你不要修改本選項,否則會導致遊戲無法啟動。\n如果你要修改本選項,你需要保證自訂目錄下有遊戲所需的本機庫檔案,如 lwjgl.dll (liblwjgl.so), openal.dll (libopenal.so) 等檔案。啟動器不會幫你補全缺少的本機庫檔案。\n注意:建議指定的本機庫檔案路徑使用全英文字元,否則可能導致遊戲啟動失敗。 -settings.advanced.no_jvm_args=不使用預設的 JVM 參數 +settings.advanced.no_jvm_args=不加入預設的 JVM 參數 settings.advanced.precall_command=遊戲啟動前執行指令 settings.advanced.precall_command.prompt=將在遊戲啟動前呼叫使用 settings.advanced.process_priority=處理程序優先度 @@ -1010,7 +1009,7 @@ settings.game.java_directory.invalid=Java 路徑不正確 settings.game.java_directory.version=指定 Java 版本 settings.game.java_directory.template=%s (%s) settings.game.management=管理 -settings.game.working_directory=執行路徑 (修改後請自行移動相關遊戲檔案,如存檔、模組設定等) +settings.game.working_directory=執行路徑 (建議使用模組時選取「各實例獨立」,修改後請自行移動相關遊戲檔案,如存檔、模組設定等) settings.game.working_directory.choose=選取執行目錄 settings.game.working_directory.hint=在「執行路徑」選項中選取「各實例獨立」使目前實例獨立存放設定、存檔、模組等資料,使用模組時建議開啟此選項以避免不同版本模組衝突。修改此選項後需自行移動存檔等檔案。 @@ -1070,11 +1069,11 @@ settings.type.global.manage=全域遊戲設定 settings.type.global.edit=編輯全域遊戲設定 settings.type.special.enable=啟用實例特定遊戲設定 (不影響其他實例) settings.type.special.edit=編輯實例特定遊戲設定 -settings.type.special.edit.hint=目前實例「%s」啟用了「實例特定遊戲設定」設定,本頁面選項不對目前實例生效。點擊連結以修改目前實例設定。 +settings.type.special.edit.hint=目前實例「%s」啟用了「實例特定遊戲設定」,本頁面選項不對目前實例生效。點擊連結以修改目前實例設定。 sponsor=贊助 sponsor.bmclapi=中國大陸下載源由 BMCLAPI 提供高速下載服務。 -sponsor.hmcl=Hello Minecraft! Launcher 是一個自由、開源的 Minecraft 啟動器,允許玩家方便快捷地安裝、管理、執行遊戲。點選此處查閱更多詳細訊息。 +sponsor.hmcl=Hello Minecraft! Launcher 是一個免費、自由、開源的 Minecraft 啟動器,允許玩家方便快捷地安裝、管理、執行遊戲。點選此處查閱更多詳細訊息。 system.architecture=架構 system.operating_system=作業系統 @@ -1084,30 +1083,26 @@ unofficial.hint=你正在使用第三方提供的 HMCL,我們無法保證其 update=啟動器更新 update.accept=更新 update.changelog=更新日誌 -update.channel.dev=測試版 -update.channel.dev.hint=你正在使用 HMCL 測試版。測試版包含一些未在正式版中包含的測試性功能,僅用於體驗新功能。測試版功能未受充分驗證,使用起來可能不穩定!\n\ - \n\ - 如果你遇到了使用問題,可以透過「設定 → 回報」頁面或下方提供的管道進行回報。\n\ - \n\ - Discord QQ 群 GitHub\n\ +update.channel.dev=開發版 +update.channel.dev.hint=你正在使用 HMCL 開發版。開發版包含一些未在穩定版中包含的測試性功能,僅用於體驗新功能。\n\ + 開發版功能未受充分驗證,使用起來可能不穩定!\n\ + 如果你遇到了使用問題,可以透過設定中 回報頁面 提供的管道進行回報。\n\ \n\ 為目前版本隱藏該提示。 -update.channel.dev.title=測試版提示 +update.channel.dev.title=開發版提示 update.channel.nightly=預覽版 -update.channel.nightly.hint=你正在使用 HMCL 預覽版。預覽版更新較為頻繁,包含一些未在正式版和測試版中包含的測試性功能,僅用於體驗新功能。預覽版功能未受充分驗證,使用起來可能不穩定!\n\ - \n\ - 如果你遇到了使用問題,可以透過「設定 → 回報」頁面或下方提供的管道進行回報。\n\ - \n\ - Discord QQ 群 GitHub +update.channel.nightly.hint=你正在使用 HMCL 預覽版。預覽版更新較為頻繁,包含一些未在穩定版和開發版中包含的測試性功能,僅用於體驗新功能。\n\ + 預覽版功能未受充分驗證,使用起來可能不穩定!\n\ + 如果你遇到了使用問題,可以透過設定中 回報頁面 提供的管道進行回報。 update.channel.nightly.title=預覽版提示 -update.channel.stable=建議版本 +update.channel.stable=穩定版 update.checking=正在檢查更新 update.failed=更新失敗 update.found=發現到更新 update.newest_version=最新版本為:%s update.bubble.title=發現更新:%s update.bubble.subtitle=點選此處進行升級 -update.note=測試版與預覽版包含更多的功能以及錯誤修復,但也可能會包含其他的問題。 +update.note=開發版與預覽版包含更多的功能以及錯誤修復,但也可能會包含其他的問題。 update.latest=目前版本為最新版本 update.no_browser=無法開啟瀏覽器,網址已經複製到剪貼簿了,你可以手動複製網址開啟頁面。 update.tooltip=更新 @@ -1119,7 +1114,7 @@ version.empty=沒有遊戲版本 version.empty.add=進入下載頁安裝遊戲 version.empty.launch=沒有可啟動的遊戲,你可以點擊左側邊欄內的下載按鈕安裝遊戲 version.empty.hint=沒有已安裝的遊戲,你可以切換其他遊戲目錄,或者點擊此處進入遊戲下載頁面 -version.game.old=歷史版本 +version.game.old=遠古版 version.game.release=正式版 version.game.releases=正式版 version.game.snapshot=快照 @@ -1138,8 +1133,8 @@ version.manage.duplicate=複製遊戲實例 version.manage.duplicate.duplicate_save=複製存檔 version.manage.duplicate.prompt=請輸入新遊戲實例名稱 version.manage.duplicate.confirm=新的遊戲將複製該實例目錄 (".minecraft/versions/<實例名>") 下的檔案,並帶有獨立的執行目錄和設定。 -version.manage.manage=實例設定 -version.manage.manage.title=實例設定 - %1s +version.manage.manage=實例管理 +version.manage.manage.title=實例管理 - %1s version.manage.redownload_assets_index=更新遊戲資源檔案 version.manage.remove=刪除該版本 version.manage.remove.confirm=真的要刪除實例「%s」嗎? 你將無法找回被刪除的檔案!!! From 9e56b5cd15bf00ebc481c0f9ab742eb14edff0c3 Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 25 Oct 2024 04:08:40 +0800 Subject: [PATCH 059/169] =?UTF-8?q?=E6=B8=85=E7=90=86=E5=AF=B9=20setOnMous?= =?UTF-8?q?eClicked=20=E7=9A=84=E8=AF=AF=E7=94=A8=20(#3379)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/jackhuang/hmcl/ui/CrashWindow.java | 2 +- .../java/org/jackhuang/hmcl/ui/GameCrashWindow.java | 4 ++-- .../main/java/org/jackhuang/hmcl/ui/ListPageSkin.java | 4 ++-- .../org/jackhuang/hmcl/ui/ToolbarListPageSkin.java | 6 +++--- .../jackhuang/hmcl/ui/account/AccountListItemSkin.java | 10 +++++----- .../java/org/jackhuang/hmcl/ui/construct/FileItem.java | 2 +- .../org/jackhuang/hmcl/ui/download/InstallersPage.java | 2 +- .../org/jackhuang/hmcl/ui/export/ModpackInfoPage.java | 4 +--- .../main/java/org/jackhuang/hmcl/ui/main/MainPage.java | 4 ++-- .../java/org/jackhuang/hmcl/ui/main/SettingsView.java | 8 ++++---- .../jackhuang/hmcl/ui/profile/ProfileListItemSkin.java | 2 +- .../jackhuang/hmcl/ui/versions/GameListItemSkin.java | 6 +++--- .../jackhuang/hmcl/ui/versions/ModListPageSkin.java | 10 +++------- .../hmcl/ui/versions/WorldExportPageSkin.java | 2 +- .../jackhuang/hmcl/ui/versions/WorldListItemSkin.java | 4 +--- 15 files changed, 31 insertions(+), 39 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java index c1f7158d44..5af27b6a60 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java @@ -53,7 +53,7 @@ else if (UpdateChecker.isOutdated()) Button btnContact = new Button(); btnContact.setText(i18n("launcher.contact")); - btnContact.setOnMouseClicked(event -> FXUtils.openLink(Metadata.CONTACT_URL)); + btnContact.setOnAction(event -> FXUtils.openLink(Metadata.CONTACT_URL)); HBox box = new HBox(); box.setStyle("-fx-padding: 8px;"); box.getChildren().add(btnContact); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java index a93e073e9a..6515422389 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java @@ -417,10 +417,10 @@ private final class View extends VBox { HBox toolBar = new HBox(); { JFXButton exportGameCrashInfoButton = FXUtils.newRaisedButton(i18n("logwindow.export_game_crash_logs")); - exportGameCrashInfoButton.setOnMouseClicked(e -> exportGameCrashInfo()); + exportGameCrashInfoButton.setOnAction(e -> exportGameCrashInfo()); JFXButton logButton = FXUtils.newRaisedButton(i18n("logwindow.title")); - logButton.setOnMouseClicked(e -> showLogWindow()); + logButton.setOnAction(e -> showLogWindow()); JFXButton helpButton = FXUtils.newRaisedButton(i18n("help")); helpButton.setOnAction(e -> FXUtils.openLink("https://docs.hmcl.net/help.html")); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java index ffbe90d466..89fe706518 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ListPageSkin.java @@ -70,7 +70,7 @@ public ListPageSkin(ListPage skinnable) { btnAdd.getStyleClass().add("jfx-button-raised-round"); btnAdd.setButtonType(JFXButton.ButtonType.RAISED); btnAdd.setGraphic(SVG.PLUS.createIcon(Theme.whiteFill(), -1, -1)); - btnAdd.setOnMouseClicked(e -> skinnable.add()); + btnAdd.setOnAction(e -> skinnable.add()); JFXButton btnRefresh = new JFXButton(); FXUtils.setLimitWidth(btnRefresh, 40); @@ -78,7 +78,7 @@ public ListPageSkin(ListPage skinnable) { btnRefresh.getStyleClass().add("jfx-button-raised-round"); btnRefresh.setButtonType(JFXButton.ButtonType.RAISED); btnRefresh.setGraphic(SVG.REFRESH.createIcon(Theme.whiteFill(), -1, -1)); - btnRefresh.setOnMouseClicked(e -> skinnable.refresh()); + btnRefresh.setOnAction(e -> skinnable.refresh()); vBox.getChildren().setAll(btnAdd); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ToolbarListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ToolbarListPageSkin.java index 518ceb2f0e..ba4d42c814 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ToolbarListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ToolbarListPageSkin.java @@ -91,7 +91,7 @@ public static JFXButton createToolbarButton(String text, SVG svg, Runnable onCli ret.textFillProperty().bind(Theme.foregroundFillBinding()); ret.setGraphic(wrap(svg.createIcon(Theme.foregroundFillBinding(), -1, -1))); ret.setText(text); - ret.setOnMouseClicked(e -> onClick.run()); + ret.setOnAction(e -> onClick.run()); return ret; } @@ -100,7 +100,7 @@ public static JFXButton createToolbarButton2(String text, SVG svg, Runnable onCl ret.getStyleClass().add("jfx-tool-bar-button"); ret.setGraphic(wrap(svg.createIcon(Theme.blackFill(), -1, -1))); ret.setText(text); - ret.setOnMouseClicked(e -> onClick.run()); + ret.setOnAction(e -> onClick.run()); return ret; } @@ -110,7 +110,7 @@ public static JFXButton createDecoratorButton(String tooltip, SVG svg, Runnable ret.textFillProperty().bind(Theme.foregroundFillBinding()); ret.setGraphic(wrap(svg.createIcon(Theme.foregroundFillBinding(), -1, -1))); FXUtils.installFastTooltip(ret, tooltip); - ret.setOnMouseClicked(e -> onClick.run()); + ret.setOnAction(e -> onClick.run()); return ret; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index bb99d8af4d..52fceb890c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -94,7 +94,7 @@ public void fire() { JFXButton btnMove = new JFXButton(); SpinnerPane spinnerMove = new SpinnerPane(); spinnerMove.getStyleClass().add("small-spinner-pane"); - btnMove.setOnMouseClicked(e -> { + btnMove.setOnAction(e -> { Account account = skinnable.getAccount(); Accounts.getAccounts().remove(account); if (account.isPortable()) { @@ -129,7 +129,7 @@ public void fire() { JFXButton btnRefresh = new JFXButton(); SpinnerPane spinnerRefresh = new SpinnerPane(); spinnerRefresh.getStyleClass().setAll("small-spinner-pane"); - btnRefresh.setOnMouseClicked(e -> { + btnRefresh.setOnAction(e -> { spinnerRefresh.showSpinner(); skinnable.refreshAsync() .whenComplete(Schedulers.javafx(), ex -> { @@ -149,7 +149,7 @@ public void fire() { JFXButton btnUpload = new JFXButton(); SpinnerPane spinnerUpload = new SpinnerPane(); - btnUpload.setOnMouseClicked(e -> { + btnUpload.setOnAction(e -> { Task uploadTask = skinnable.uploadSkin(); if (uploadTask != null) { spinnerUpload.showSpinner(); @@ -170,14 +170,14 @@ public void fire() { JFXButton btnCopyUUID = new JFXButton(); SpinnerPane spinnerCopyUUID = new SpinnerPane(); spinnerCopyUUID.getStyleClass().add("small-spinner-pane"); - btnCopyUUID.setOnMouseClicked(e -> FXUtils.copyText(skinnable.getAccount().getUUID().toString())); + btnCopyUUID.setOnAction(e -> FXUtils.copyText(skinnable.getAccount().getUUID().toString())); btnCopyUUID.setGraphic(SVG.COPY.createIcon(Theme.blackFill(), -1, -1)); runInFX(() -> FXUtils.installFastTooltip(btnCopyUUID, i18n("account.copy_uuid"))); spinnerCopyUUID.setContent(btnCopyUUID); right.getChildren().add(spinnerCopyUUID); JFXButton btnRemove = new JFXButton(); - btnRemove.setOnMouseClicked(e -> Controllers.confirm(i18n("button.remove.confirm"), i18n("button.remove"), skinnable::remove, null)); + btnRemove.setOnAction(e -> Controllers.confirm(i18n("button.remove.confirm"), i18n("button.remove"), skinnable::remove, null)); btnRemove.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnRemove, Pos.CENTER); btnRemove.setGraphic(SVG.DELETE.createIcon(Theme.blackFill(), -1, -1)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java index 7a636c58ad..1df0657605 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java @@ -60,7 +60,7 @@ public FileItem() { JFXButton right = new JFXButton(); right.setGraphic(SVG.PENCIL.createIcon(Theme.blackFill(), 15, 15)); right.getStyleClass().add("toggle-icon4"); - right.setOnMouseClicked(e -> onExplore()); + right.setOnAction(e -> onExplore()); FXUtils.installFastTooltip(right, i18n("button.edit")); setRight(right); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index 1e0bc2d8dc..575f9a98f4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -222,7 +222,7 @@ protected InstallersPageSkin(InstallersPage control) { installButton.disableProperty().bind(control.installable.not()); installButton.setPrefWidth(100); installButton.setPrefHeight(40); - installButton.setOnMouseClicked(e -> control.onInstall()); + installButton.setOnAction(e -> control.onInstall()); BorderPane.setAlignment(installButton, Pos.CENTER_RIGHT); root.setBottom(installButton); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java index e3908c5b91..8a99ee276b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java @@ -178,9 +178,7 @@ public ModpackInfoPageSkin(ModpackInfoPage skinnable) { if (skinnable.controller.getSettings().get(MODPACK_TYPE) == MODPACK_TYPE_SERVER) { Hyperlink hyperlink = new Hyperlink(i18n("modpack.wizard.step.initialization.server")); - hyperlink.setOnMouseClicked(e -> { - FXUtils.openLink("https://docs.hmcl.net/modpack/serverpack.html"); - }); + hyperlink.setOnAction(e -> FXUtils.openLink("https://docs.hmcl.net/modpack/serverpack.html")); borderPane.setTop(hyperlink); } else { HintPane pane = new HintPane(MessageDialogPane.MessageType.INFO); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java index d97a0a9aa4..7f401b0a03 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java @@ -144,7 +144,7 @@ public final class MainPage extends StackPane implements DecoratorPage { StackPane.setAlignment(closeUpdateButton, Pos.TOP_RIGHT); closeUpdateButton.getStyleClass().add("toggle-icon-tiny"); StackPane.setMargin(closeUpdateButton, new Insets(5)); - closeUpdateButton.setOnMouseClicked(e -> closeUpdateBubble()); + closeUpdateButton.setOnAction(e -> closeUpdateBubble()); updatePane.getChildren().setAll(hBox, closeUpdateButton); } @@ -206,7 +206,7 @@ public final class MainPage extends StackPane implements DecoratorPage { menuButton.setPrefWidth(230); //menuButton.setButtonType(JFXButton.ButtonType.RAISED); menuButton.setStyle("-fx-font-size: 15px;"); - menuButton.setOnMouseClicked(e -> onMenu()); + menuButton.setOnAction(e -> onMenu()); menuButton.setClip(new Rectangle(211, -100, 100, 200)); StackPane graphic = new StackPane(); Node svg = SVG.TRIANGLE.createIcon(Theme.foregroundFillBinding(), 10, 10); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java index 8995e19498..a2366cc33c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java @@ -121,7 +121,7 @@ public SettingsView() { { btnUpdate = new JFXButton(); - btnUpdate.setOnMouseClicked(e -> onUpdate()); + btnUpdate.setOnAction(e -> onUpdate()); btnUpdate.getStyleClass().add("toggle-icon4"); btnUpdate.setGraphic(SVG.UPDATE.createIcon(Theme.blackFill(), 20, 20)); @@ -161,7 +161,7 @@ public SettingsView() { { JFXButton cleanButton = new JFXButton(i18n("launcher.cache_directory.clean")); - cleanButton.setOnMouseClicked(e -> clearCacheDirectory()); + cleanButton.setOnAction(e -> clearCacheDirectory()); cleanButton.getStyleClass().add("jfx-button-border"); fileCommonLocationSublist.setHeaderRight(cleanButton); @@ -193,11 +193,11 @@ public SettingsView() { debugPane.setLeft(left); JFXButton openLogFolderButton = new JFXButton(i18n("settings.launcher.launcher_log.reveal")); - openLogFolderButton.setOnMouseClicked(e -> openLogFolder()); + openLogFolderButton.setOnAction(e -> openLogFolder()); openLogFolderButton.getStyleClass().add("jfx-button-border"); JFXButton logButton = new JFXButton(i18n("settings.launcher.launcher_log.export")); - logButton.setOnMouseClicked(e -> onExportLogs()); + logButton.setOnAction(e -> onExportLogs()); logButton.getStyleClass().add("jfx-button-border"); HBox buttonBox = new HBox(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java index 83b5ed3367..8acbe86200 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java @@ -64,7 +64,7 @@ public ProfileListItemSkin(ProfileListItem skinnable) { right.setAlignment(Pos.CENTER_RIGHT); JFXButton btnRemove = new JFXButton(); - btnRemove.setOnMouseClicked(e -> skinnable.remove()); + btnRemove.setOnAction(e -> skinnable.remove()); btnRemove.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnRemove, Pos.CENTER); btnRemove.setGraphic(SVG.CLOSE.createIcon(Theme.blackFill(), 14, 14)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java index e4e767214f..d2aebb8907 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java @@ -79,7 +79,7 @@ public GameListItemSkin(GameListItem skinnable) { right.setAlignment(Pos.CENTER_RIGHT); if (skinnable.canUpdate()) { JFXButton btnUpgrade = new JFXButton(); - btnUpgrade.setOnMouseClicked(e -> skinnable.update()); + btnUpgrade.setOnAction(e -> skinnable.update()); btnUpgrade.getStyleClass().add("toggle-icon4"); btnUpgrade.setGraphic(FXUtils.limitingSize(SVG.UPDATE.createIcon(Theme.blackFill(), 24, 24), 24, 24)); runInFX(() -> FXUtils.installFastTooltip(btnUpgrade, i18n("version.update"))); @@ -88,7 +88,7 @@ public GameListItemSkin(GameListItem skinnable) { { JFXButton btnLaunch = new JFXButton(); - btnLaunch.setOnMouseClicked(e -> skinnable.launch()); + btnLaunch.setOnAction(e -> skinnable.launch()); btnLaunch.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnLaunch, Pos.CENTER); btnLaunch.setGraphic(FXUtils.limitingSize(SVG.ROCKET_LAUNCH_OUTLINE.createIcon(Theme.blackFill(), 24, 24), 24, 24)); @@ -98,7 +98,7 @@ public GameListItemSkin(GameListItem skinnable) { { JFXButton btnManage = new JFXButton(); - btnManage.setOnMouseClicked(e -> { + btnManage.setOnAction(e -> { currentSkinnable = skinnable; popup.get().show(root, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, 0, root.getHeight()); }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index 5cfaa1f1e6..7da53efe96 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -539,7 +539,7 @@ protected void updateControl(ModInfoObject dataItem, boolean empty) { } checkBox.selectedProperty().bindBidirectional(booleanProperty = dataItem.active); restoreButton.setVisible(!dataItem.getModInfo().getMod().getOldFiles().isEmpty()); - restoreButton.setOnMouseClicked(e -> { + restoreButton.setOnAction(e -> { menu.get().getContent().setAll(dataItem.getModInfo().getMod().getOldFiles().stream() .map(localModFile -> new IconedMenuItem(null, localModFile.getVersion(), () -> getSkinnable().rollback(dataItem.getModInfo(), localModFile), @@ -549,12 +549,8 @@ protected void updateControl(ModInfoObject dataItem, boolean empty) { popup.get().show(restoreButton, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, 0, restoreButton.getHeight()); }); - revealButton.setOnMouseClicked(e -> { - FXUtils.showFileInExplorer(dataItem.getModInfo().getFile()); - }); - infoButton.setOnMouseClicked(e -> { - Controllers.dialog(new ModInfoDialog(dataItem)); - }); + revealButton.setOnAction(e -> FXUtils.showFileInExplorer(dataItem.getModInfo().getFile())); + infoButton.setOnAction(e -> Controllers.dialog(new ModInfoDialog(dataItem))); } } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldExportPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldExportPageSkin.java index 38af59549b..98226cbb28 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldExportPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldExportPageSkin.java @@ -83,7 +83,7 @@ public WorldExportPageSkin(WorldExportPage skinnable) { JFXButton btnExport = FXUtils.newRaisedButton(i18n("button.export")); btnExport.disableProperty().bind(Bindings.createBooleanBinding(() -> txtWorldName.getText().isEmpty() || Files.exists(Paths.get(fileItem.getPath())), txtWorldName.textProperty().isEmpty(), fileItem.pathProperty())); - btnExport.setOnMouseClicked(e -> skinnable.export()); + btnExport.setOnAction(e -> skinnable.export()); HBox bottom = new HBox(); bottom.setAlignment(Pos.CENTER_RIGHT); bottom.getChildren().setAll(btnExport); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItemSkin.java index e83c7f962f..27a8f3dbd1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItemSkin.java @@ -76,9 +76,7 @@ public WorldListItemSkin(WorldListItem skinnable) { right.setAlignment(Pos.CENTER_RIGHT); JFXButton btnManage = new JFXButton(); - btnManage.setOnMouseClicked(e -> { - popup.show(root, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, 0, root.getHeight()); - }); + btnManage.setOnAction(e -> popup.show(root, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, 0, root.getHeight())); btnManage.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnManage, Pos.CENTER); btnManage.setGraphic(SVG.DOTS_VERTICAL.createIcon(Theme.blackFill(), -1, -1)); From 7645a600ef01b47f291c429e1c096667cbd70d7a Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 25 Oct 2024 12:24:57 +0800 Subject: [PATCH 060/169] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=8E=A7=E4=BB=B6=E5=93=8D=E5=BA=94=E4=BB=BB=E6=84=8F=E9=BC=A0?= =?UTF-8?q?=E6=A0=87=E6=8C=89=E9=94=AE=E7=82=B9=E5=87=BB=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=20(#3380)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update * update * update * update * update * update * update * update --- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 11 +++- .../org/jackhuang/hmcl/ui/HTMLRenderer.java | 4 +- .../org/jackhuang/hmcl/ui/InstallerItem.java | 58 ++++++++++++++----- .../java/org/jackhuang/hmcl/ui/LogWindow.java | 6 ++ .../hmcl/ui/account/CreateAccountPane.java | 4 +- .../ui/account/OAuthAccountLoginDialog.java | 2 +- .../hmcl/ui/construct/AdvancedListItem.java | 3 +- .../hmcl/ui/construct/ComponentListCell.java | 9 +-- .../hmcl/ui/construct/FontComboBox.java | 3 +- .../hmcl/ui/construct/IconedMenuItem.java | 4 +- .../hmcl/ui/construct/ImagePickerItem.java | 22 +++---- .../hmcl/ui/construct/OptionToggleButton.java | 4 +- .../hmcl/ui/construct/SpinnerPane.java | 22 ++++--- .../hmcl/ui/construct/TabHeader.java | 9 +-- .../ui/download/AdditionalInstallersPage.java | 2 +- .../hmcl/ui/download/InstallersPage.java | 4 +- .../hmcl/ui/download/VersionsPage.java | 8 +-- .../hmcl/ui/export/ModpackInfoPage.java | 7 +-- .../org/jackhuang/hmcl/ui/main/MainPage.java | 6 +- .../jackhuang/hmcl/ui/main/SettingsView.java | 2 +- .../hmcl/ui/profile/ProfileListItemSkin.java | 5 +- .../hmcl/ui/versions/DownloadListPage.java | 2 +- .../hmcl/ui/versions/DownloadPage.java | 8 +-- .../hmcl/ui/versions/InstallerListPage.java | 6 +- .../hmcl/ui/versions/VersionIconDialog.java | 6 +- .../hmcl/ui/versions/WorldListItem.java | 2 +- 26 files changed, 121 insertions(+), 98 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index 35705f3678..141ac78a27 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -957,6 +957,15 @@ public static void onEscPressed(Node node, Runnable action) { }); } + public static void onClicked(Node node, Runnable action) { + node.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> { + if (e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 1) { + action.run(); + e.consume(); + } + }); + } + public static void copyText(String text) { ClipboardContent content = new ClipboardContent(); content.putString(text); @@ -987,7 +996,7 @@ public static List parseSegment(String segment, Consumer hyperlink if ("a".equals(element.getTagName())) { String href = element.getAttribute("href"); Text text = new Text(element.getTextContent()); - text.setOnMouseClicked(e -> { + onClicked(text, () -> { String link = href; try { link = new URI(href).toASCIIString(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java index d311996a9e..dccedf77f2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/HTMLRenderer.java @@ -123,7 +123,7 @@ private void applyStyle(Text text) { if (hyperlink != null) { URI target = resolveLink(hyperlink); if (target != null) { - text.setOnMouseClicked(event -> onClickHyperlink.accept(target)); + FXUtils.onClicked(text, () -> onClickHyperlink.accept(target)); text.setCursor(Cursor.HAND); } text.getStyleClass().add("html-hyperlink"); @@ -192,7 +192,7 @@ private void appendImage(Node node) { if (hyperlink != null) { URI target = resolveLink(hyperlink); if (target != null) { - imageView.setOnMouseClicked(event -> onClickHyperlink.accept(target)); + FXUtils.onClicked(imageView, () -> onClickHyperlink.accept(target)); imageView.setCursor(Cursor.HAND); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java index d622fe9c0b..17224a8823 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -23,7 +23,6 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.css.PseudoClass; -import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Cursor; @@ -33,7 +32,7 @@ import javafx.scene.control.Skin; import javafx.scene.control.SkinBase; import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; +import javafx.scene.input.MouseButton; import javafx.scene.layout.*; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.setting.Theme; @@ -60,8 +59,8 @@ public class InstallerItem extends Control { private final ObjectProperty versionProperty = new SimpleObjectProperty<>(this, "version", null); private final ObjectProperty resolvedStateProperty = new SimpleObjectProperty<>(this, "resolvedState", InstallableState.INSTANCE); - private final ObjectProperty> installActionProperty = new SimpleObjectProperty<>(this, "installAction"); - private final ObjectProperty> removeActionProperty = new SimpleObjectProperty<>(this, "removeAction"); + private final ObjectProperty onInstall = new SimpleObjectProperty<>(this, "onInstall"); + private final ObjectProperty onRemove = new SimpleObjectProperty<>(this, "onRemove"); public interface State { } @@ -170,12 +169,28 @@ public ObjectProperty resolvedStateProperty() { return resolvedStateProperty; } - public ObjectProperty> installActionProperty() { - return installActionProperty; + public ObjectProperty onInstallProperty() { + return onInstall; } - public ObjectProperty> removeActionProperty() { - return removeActionProperty; + public Runnable getOnInstall() { + return onInstall.get(); + } + + public void setOnInstall(Runnable onInstall) { + this.onInstall.set(onInstall); + } + + public ObjectProperty onRemoveProperty() { + return onRemove; + } + + public Runnable getOnRemove() { + return onRemove.get(); + } + + public void setOnRemove(Runnable onRemove) { + this.onRemove.set(onRemove); } @Override @@ -371,7 +386,11 @@ private static final class InstallerItemSkin extends SkinBase { removeButton.visibleProperty().bind(Bindings.createBooleanBinding(() -> control.resolvedStateProperty.get() instanceof InstalledState, control.resolvedStateProperty)); } removeButton.managedProperty().bind(removeButton.visibleProperty()); - removeButton.onMouseClickedProperty().bind(control.removeActionProperty); + removeButton.setOnAction(e -> { + Runnable onRemove = control.getOnRemove(); + if (onRemove != null) + onRemove.run(); + }); buttonsContainer.getChildren().add(removeButton); JFXButton installButton = new JFXButton(); @@ -383,7 +402,7 @@ private static final class InstallerItemSkin extends SkinBase { )); installButton.getStyleClass().add("toggle-icon4"); installButton.visibleProperty().bind(Bindings.createBooleanBinding(() -> { - if (control.installActionProperty.get() == null) { + if (control.getOnInstall() == null) { return false; } @@ -396,18 +415,27 @@ private static final class InstallerItemSkin extends SkinBase { } return false; - }, control.resolvedStateProperty, control.installActionProperty)); + }, control.resolvedStateProperty, control.onInstall)); installButton.managedProperty().bind(installButton.visibleProperty()); - installButton.onMouseClickedProperty().bind(control.installActionProperty); + installButton.setOnAction(e -> { + Runnable onInstall = control.getOnInstall(); + if (onInstall != null) + onInstall.run(); + }); buttonsContainer.getChildren().add(installButton); FXUtils.onChangeAndOperate(installButton.visibleProperty(), clickable -> { if (clickable) { - container.onMouseClickedProperty().bind(control.installActionProperty); + container.setOnMouseClicked(event -> { + Runnable onInstall = control.getOnInstall(); + if (onInstall != null && event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 1) { + onInstall.run(); + event.consume(); + } + }); pane.setCursor(Cursor.HAND); } else { - container.onMouseClickedProperty().unbind(); - container.onMouseClickedProperty().set(null); + container.setOnMouseClicked(null); pane.setCursor(Cursor.DEFAULT); } }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java index 7e28b6d7d9..bcefd16e04 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java @@ -34,6 +34,7 @@ import javafx.scene.control.Label; import javafx.scene.control.*; import javafx.scene.input.KeyCode; +import javafx.scene.input.MouseButton; import javafx.scene.layout.*; import javafx.stage.Stage; import org.jackhuang.hmcl.game.GameDumpGenerator; @@ -322,6 +323,9 @@ private static final class LogWindowSkin extends SkinBase { setGraphic(null); setOnMouseClicked(event -> { + if (event.getButton() != MouseButton.PRIMARY) + return; + if (!event.isControlDown()) { for (ListCell logListCell : selected) { if (logListCell != this) { @@ -340,6 +344,8 @@ private static final class LogWindowSkin extends SkinBase { if (getItem() != null) { getItem().setSelected(true); } + + event.consume(); }); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java index 28d1df6d0d..51fb48ceb7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java @@ -297,7 +297,7 @@ private void initDetailsPane() { hintPane.setSegment(i18n("account.methods.microsoft.hint")); } }); - hintPane.setOnMouseClicked(e -> { + FXUtils.onClicked(hintPane, () -> { if (deviceCode.get() != null) { FXUtils.copyText(deviceCode.get().getUserCode()); } @@ -658,7 +658,7 @@ public GameProfile select(YggdrasilService service, List profiles) TexturesLoader.bindAvatar(portraitCanvas, service, profile.getId()); IconedItem accountItem = new IconedItem(portraitCanvas, profile.getName()); - accountItem.setOnMouseClicked(e -> { + FXUtils.onClicked(accountItem, () -> { selectedProfile = profile; latch.countDown(); }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/OAuthAccountLoginDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/OAuthAccountLoginDialog.java index bf9f98bce4..36780c3d47 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/OAuthAccountLoginDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/OAuthAccountLoginDialog.java @@ -58,7 +58,7 @@ public OAuthAccountLoginDialog(OAuthAccount account, Consumer success, ); } }); - hintPane.setOnMouseClicked(e -> { + FXUtils.onClicked(hintPane, () -> { if (deviceCode.get() != null) { FXUtils.copyText(deviceCode.get().getUserCode()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AdvancedListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AdvancedListItem.java index 8464699081..cdbedba2f3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AdvancedListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AdvancedListItem.java @@ -25,7 +25,6 @@ import javafx.scene.control.Skin; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.util.Pair; @@ -42,7 +41,7 @@ public class AdvancedListItem extends Control { public AdvancedListItem() { getStyleClass().add("advanced-list-item"); - addEventHandler(MouseEvent.MOUSE_CLICKED, e -> fireEvent(new ActionEvent())); + FXUtils.onClicked(this, () -> fireEvent(new ActionEvent())); } public Node getLeftGraphic() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java index d6f2a5f5c0..bd97fba095 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java @@ -25,9 +25,6 @@ import javafx.application.Platform; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; -import javafx.event.ActionEvent; -import javafx.event.Event; -import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; @@ -139,7 +136,7 @@ private void updateLayout() { container.getChildren().setAll(content); groupNode.getChildren().add(container); - EventHandler onExpand = e -> { + Runnable onExpand = () -> { if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) { expandAnimation.stop(); } @@ -182,8 +179,8 @@ private void updateLayout() { }); }; - headerRippler.setOnMouseClicked(onExpand); - expandButton.setOnAction((EventHandler) (Object) onExpand); + FXUtils.onClicked(headerRippler, onExpand); + expandButton.setOnAction(e -> onExpand.run()); expandedProperty().addListener((a, b, newValue) -> expandIcon.setRotate(newValue ? 180 : 0)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java index 58b0923beb..ae50156606 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java @@ -21,6 +21,7 @@ import static javafx.collections.FXCollections.observableList; import static javafx.collections.FXCollections.singletonObservableList; +import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.util.javafx.BindingMapping; import com.jfoenix.controls.JFXComboBox; @@ -51,7 +52,7 @@ public void updateItem(String item, boolean empty) { itemsProperty().bind(BindingMapping.of(valueProperty()) .map(value -> value == null ? emptyObservableList() : singletonObservableList(value))); - setOnMouseClicked(e -> { + FXUtils.onClicked(this, () -> { if (loaded) return; itemsProperty().unbind(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedMenuItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedMenuItem.java index b54c6f70b3..dcc1d86aa8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedMenuItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedMenuItem.java @@ -30,9 +30,9 @@ public IconedMenuItem(SVG icon, String text, Runnable action, JFXPopup popup) { getStyleClass().setAll("iconed-menu-item"); if (popup == null) { - setOnMouseClicked(e -> action.run()); + FXUtils.onClicked(this, action); } else { - setOnMouseClicked(e -> { + FXUtils.onClicked(this, () -> { action.run(); popup.hide(); }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java index e7a0a6d00d..810256c7c5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java @@ -23,12 +23,12 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; @@ -44,8 +44,8 @@ public final class ImagePickerItem extends BorderPane { private final ImageView imageView; private final StringProperty title = new SimpleStringProperty(this, "title"); - private final ObjectProperty> onSelectButtonClicked = new SimpleObjectProperty<>(this, "onSelectButtonClicked"); - private final ObjectProperty> onDeleteButtonClicked = new SimpleObjectProperty<>(this, "onDeleteButtonClicked"); + private final ObjectProperty> onSelectButtonClicked = new SimpleObjectProperty<>(this, "onSelectButtonClicked"); + private final ObjectProperty> onDeleteButtonClicked = new SimpleObjectProperty<>(this, "onDeleteButtonClicked"); private final ObjectProperty image = new SimpleObjectProperty<>(this, "image"); public ImagePickerItem() { @@ -55,12 +55,12 @@ public ImagePickerItem() { JFXButton selectButton = new JFXButton(); selectButton.setGraphic(SVG.PENCIL.createIcon(Theme.blackFill(), 20, 20)); - selectButton.onMouseClickedProperty().bind(onSelectButtonClicked); + selectButton.onActionProperty().bind(onSelectButtonClicked); selectButton.getStyleClass().add("toggle-icon4"); JFXButton deleteButton = new JFXButton(); deleteButton.setGraphic(SVG.CLOSE.createIcon(Theme.blackFill(), 20, 20)); - deleteButton.onMouseClickedProperty().bind(onDeleteButtonClicked); + deleteButton.onActionProperty().bind(onDeleteButtonClicked); deleteButton.getStyleClass().add("toggle-icon4"); FXUtils.installFastTooltip(selectButton, i18n("button.edit")); @@ -93,27 +93,27 @@ public void setTitle(String title) { this.title.set(title); } - public EventHandler getOnSelectButtonClicked() { + public EventHandler getOnSelectButtonClicked() { return onSelectButtonClicked.get(); } - public ObjectProperty> onSelectButtonClickedProperty() { + public ObjectProperty> onSelectButtonClickedProperty() { return onSelectButtonClicked; } - public void setOnSelectButtonClicked(EventHandler onSelectButtonClicked) { + public void setOnSelectButtonClicked(EventHandler onSelectButtonClicked) { this.onSelectButtonClicked.set(onSelectButtonClicked); } - public EventHandler getOnDeleteButtonClicked() { + public EventHandler getOnDeleteButtonClicked() { return onDeleteButtonClicked.get(); } - public ObjectProperty> onDeleteButtonClickedProperty() { + public ObjectProperty> onDeleteButtonClickedProperty() { return onDeleteButtonClicked; } - public void setOnDeleteButtonClicked(EventHandler onDeleteButtonClicked) { + public void setOnDeleteButtonClicked(EventHandler onDeleteButtonClicked) { this.onDeleteButtonClicked.set(onDeleteButtonClicked); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/OptionToggleButton.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/OptionToggleButton.java index fd9a6359dc..7883bb37c2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/OptionToggleButton.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/OptionToggleButton.java @@ -61,9 +61,7 @@ public OptionToggleButton() { toggleButton.setSize(8); FXUtils.setLimitHeight(toggleButton, 30); - container.setOnMouseClicked(e -> { - toggleButton.setSelected(!toggleButton.isSelected()); - }); + FXUtils.onClicked(container, () -> toggleButton.setSelected(!toggleButton.isSelected())); FXUtils.onChangeAndOperate(subtitleProperty(), subtitle -> { if (StringUtils.isNotBlank(subtitle)) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/SpinnerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/SpinnerPane.java index 8035df0894..8686011c2f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/SpinnerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/SpinnerPane.java @@ -32,7 +32,6 @@ import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; import org.jackhuang.hmcl.ui.animation.TransitionPane; -import org.jackhuang.hmcl.util.javafx.BindingMapping; @DefaultProperty("content") public class SpinnerPane extends Control { @@ -101,18 +100,19 @@ public final EventHandler getOnFailedAction() { return onFailedActionProperty().get(); } - private ObjectProperty> onFailedAction = new SimpleObjectProperty>(this, "onFailedAction") { + private final ObjectProperty> onFailedAction = new SimpleObjectProperty>(this, "onFailedAction") { @Override protected void invalidated() { setEventHandler(FAILED_ACTION, get()); } }; + @Override - protected Skin createDefaultSkin() { + protected SkinBase createDefaultSkin() { return new Skin(this); } - private static class Skin extends SkinBase { + private static final class Skin extends SkinBase { private final JFXSpinner spinner = new JFXSpinner(); private final StackPane contentPane = new StackPane(); private final StackPane topPane = new StackPane(); @@ -122,20 +122,18 @@ private static class Skin extends SkinBase { @SuppressWarnings("FieldCanBeLocal") // prevent from gc. private final InvalidationListener observer; - protected Skin(SpinnerPane control) { + Skin(SpinnerPane control) { super(control); topPane.getChildren().setAll(spinner); topPane.getStyleClass().add("notice-pane"); failedPane.getStyleClass().add("notice-pane"); failedPane.getChildren().setAll(failedReasonLabel); - failedPane.onMouseClickedProperty().bind( - BindingMapping.of(control.onFailedAction) - .map(actionHandler -> (e -> { - if (actionHandler != null) { - actionHandler.handle(new Event(FAILED_ACTION)); - } - }))); + FXUtils.onClicked(failedPane, () -> { + EventHandler action = control.getOnFailedAction(); + if (action != null) + action.handle(new Event(FAILED_ACTION)); + }); FXUtils.onChangeAndOperate(getSkinnable().content, newValue -> { if (newValue == null) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TabHeader.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TabHeader.java index 8f11574995..c91ac1c82f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TabHeader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TabHeader.java @@ -30,7 +30,6 @@ import javafx.geometry.Side; import javafx.scene.Node; import javafx.scene.control.*; -import javafx.scene.input.MouseButton; import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.scene.transform.Rotate; @@ -594,11 +593,9 @@ public TabHeaderContainer(Tab tab) { FXUtils.onChangeAndOperate(tab.selectedProperty(), selected -> inner.pseudoClassStateChanged(SELECTED_PSEUDOCLASS_STATE, selected)); - this.setOnMouseClicked(event -> { - if (event.getButton() == MouseButton.PRIMARY) { - this.setOpacity(1); - getSkinnable().getSelectionModel().select(tab); - } + FXUtils.onClicked(this, () -> { + this.setOpacity(1); + getSkinnable().getSelectionModel().select(tab); }); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java index e2b14a5986..0e7d1ce649 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java @@ -59,7 +59,7 @@ public AdditionalInstallersPage(String gameVersion, Version version, WizardContr for (InstallerItem library : group.getLibraries()) { String libraryId = library.getLibraryId(); if (libraryId.equals("game")) continue; - library.removeActionProperty().set(e -> { + library.setOnRemove(() -> { controller.getSettings().put(libraryId, new UpdateInstallerWizardProvider.RemoveVersionAction(libraryId)); reload(); }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index 575f9a98f4..e5e935eb1a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -69,7 +69,7 @@ public InstallersPage(WizardController controller, HMCLGameRepository repository for (InstallerItem library : group.getLibraries()) { String libraryId = library.getLibraryId(); if (libraryId.equals(LibraryAnalyzer.LibraryType.MINECRAFT.getPatchId())) continue; - library.installActionProperty().set(e -> { + library.setOnInstall(() -> { if (LibraryAnalyzer.LibraryType.FABRIC_API.getPatchId().equals(libraryId)) { Controllers.dialog(i18n("install.installer.fabric-api.warning"), i18n("message.warning"), MessageDialogPane.MessageType.WARNING); } @@ -77,7 +77,7 @@ public InstallersPage(WizardController controller, HMCLGameRepository repository if (!(library.resolvedStateProperty().get() instanceof InstallerItem.IncompatibleState)) controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false))); }); - library.removeActionProperty().set(e -> { + library.setOnRemove(() -> { controller.getSettings().remove(libraryId); reload(); }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index e919424ed3..f419810301 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -95,7 +95,7 @@ public VersionsPage(Navigation navigation, String title, String gameVersion, Dow HintPane hintPane = new HintPane(); hintPane.setText(i18n("sponsor.bmclapi")); hintPane.getStyleClass().add("sponsor-pane"); - hintPane.setOnMouseClicked(e -> onSponsor()); + FXUtils.onClicked(hintPane, this::onSponsor); BorderPane.setMargin(hintPane, new Insets(10, 10, 0, 10)); this.setTop(hintPane); @@ -146,7 +146,7 @@ public VersionsPage(Navigation navigation, String title, String gameVersion, Dow failedPane.getStyleClass().add("notice-pane"); { Label label = new Label(i18n("download.failed.refresh")); - label.setOnMouseClicked(e -> onRefresh()); + FXUtils.onClicked(label, this::onRefresh); failedPane.getChildren().setAll(label); } @@ -155,7 +155,7 @@ public VersionsPage(Navigation navigation, String title, String gameVersion, Dow emptyPane.getStyleClass().add("notice-pane"); { Label label = new Label(i18n("download.failed.empty")); - label.setOnMouseClicked(e -> onBack()); + FXUtils.onClicked(label, this::onBack); emptyPane.getChildren().setAll(label); } @@ -180,7 +180,7 @@ public VersionsPage(Navigation navigation, String title, String gameVersion, Dow Holder lastCell = new Holder<>(); list.setCellFactory(listView -> new RemoteVersionListCell(lastCell)); - list.setOnMouseClicked(e -> { + FXUtils.onClicked(list, () -> { if (list.getSelectionModel().getSelectedIndex() < 0) return; navigation.getSettings().put(libraryId, list.getSelectionModel().getSelectedItem()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java index 8a99ee276b..024c0f40b9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java @@ -21,12 +21,10 @@ import javafx.beans.binding.Bindings; import javafx.beans.property.*; import javafx.collections.ObservableList; -import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.*; -import javafx.scene.input.MouseEvent; import javafx.scene.layout.*; import javafx.stage.FileChooser; import org.jackhuang.hmcl.auth.Account; @@ -78,7 +76,6 @@ public final class ModpackInfoPage extends Control implements WizardPage { private final SimpleStringProperty authlibInjectorServer = new SimpleStringProperty(); private final SimpleStringProperty launchArguments = new SimpleStringProperty(""); private final SimpleStringProperty javaArguments = new SimpleStringProperty(""); - private final ObjectProperty> next = new SimpleObjectProperty<>(); private final SimpleStringProperty mcbbsThreadId = new SimpleStringProperty(""); public ModpackInfoPage(WizardController controller, HMCLGameRepository gameRepository, String version) { @@ -97,8 +94,6 @@ public ModpackInfoPage(WizardController controller, HMCLGameRepository gameRepos javaArguments.set(versionSetting.getJavaArgs()); canIncludeLauncher = JarUtils.thisJarPath() != null; - - next.set(e -> onNext()); } private void onNext() { @@ -376,7 +371,7 @@ public ModpackInfoPageSkin(ModpackInfoPage skinnable) { borderPane.setBottom(hbox); JFXButton nextButton = FXUtils.newRaisedButton(i18n("wizard.next")); - nextButton.onMouseClickedProperty().bind(skinnable.next); + nextButton.setOnAction(e -> skinnable.onNext()); nextButton.setPrefWidth(100); nextButton.setPrefHeight(40); nextButton.disableProperty().bind( diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java index 7f401b0a03..f33272555e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java @@ -117,7 +117,7 @@ public final class MainPage extends StackPane implements DecoratorPage { FXUtils.setLimitWidth(updatePane, 230); FXUtils.setLimitHeight(updatePane, 55); StackPane.setAlignment(updatePane, Pos.TOP_RIGHT); - updatePane.setOnMouseClicked(e -> onUpgrade()); + FXUtils.onClicked(updatePane, this::onUpgrade); FXUtils.onChange(showUpdateProperty(), this::showUpdate); { @@ -224,10 +224,10 @@ public final class MainPage extends StackPane implements DecoratorPage { menu.setMaxHeight(365); menu.setMaxWidth(545); menu.setAlwaysShowingVBar(true); - menu.setOnMouseClicked(e -> popup.hide()); + FXUtils.onClicked(menu, popup::hide); versionNodes = MappedObservableList.create(versions, version -> { Node node = PopupMenu.wrapPopupMenuItem(new GameItem(profile, version.getId())); - node.setOnMouseClicked(e -> profile.setSelectedVersion(version.getId())); + FXUtils.onClicked(node, () -> profile.setSelectedVersion(version.getId())); return node; }); Bindings.bindContent(menu.getContent(), versionNodes); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java index a2366cc33c..0bfc1ba6a6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsView.java @@ -73,7 +73,7 @@ public SettingsView() { { StackPane sponsorPane = new StackPane(); sponsorPane.setCursor(Cursor.HAND); - sponsorPane.setOnMouseClicked(e -> onSponsor()); + FXUtils.onClicked(sponsorPane, this::onSponsor); sponsorPane.setPadding(new Insets(8, 0, 8, 0)); GridPane gridPane = new GridPane(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java index 8acbe86200..e17047341c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/profile/ProfileListItemSkin.java @@ -22,7 +22,6 @@ import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.SkinBase; -import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import org.jackhuang.hmcl.setting.Theme; @@ -47,9 +46,7 @@ public ProfileListItemSkin(ProfileListItem skinnable) { skinnable.pseudoClassStateChanged(SELECTED, active); }); - getSkinnable().addEventHandler(MouseEvent.MOUSE_CLICKED, e -> { - getSkinnable().setSelected(true); - }); + FXUtils.onClicked(getSkinnable(), () -> getSkinnable().setSelected(true)); Node left = VersionPage.wrap(SVG.FOLDER_OUTLINE); root.setLeft(left); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java index ceb0c9ed3c..ead2698201 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java @@ -488,7 +488,7 @@ protected ModDownloadListPageSkin(DownloadListPage control) { JFXListView listView = new JFXListView<>(); spinnerPane.setContent(listView); Bindings.bindContent(listView.getItems(), getSkinnable().items); - listView.setOnMouseClicked(e -> { + FXUtils.onClicked(listView, () -> { if (listView.getSelectionModel().getSelectedIndex() < 0) return; RemoteMod selectedItem = listView.getSelectionModel().getSelectedItem(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java index f7fbc807c8..f11880540f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java @@ -346,7 +346,7 @@ private static final class DependencyModItem extends StackPane { pane.getChildren().setAll(FXUtils.limitingSize(imageView, 40, 40), content); RipplerContainer container = new RipplerContainer(pane); - container.setOnMouseClicked(e -> Controllers.navigate(new DownloadPage(page, addon, version, callback))); + FXUtils.onClicked(container, () -> Controllers.navigate(new DownloadPage(page, addon, version, callback))); getChildren().setAll(container); if (addon != RemoteMod.BROKEN) { @@ -428,7 +428,7 @@ private static final class ModItem extends StackPane { } RipplerContainer container = new RipplerContainer(pane); - container.setOnMouseClicked(e -> Controllers.dialog(new ModVersion(dataItem, selfPage))); + FXUtils.onClicked(container, () -> Controllers.dialog(new ModVersion(dataItem, selfPage))); getChildren().setAll(container); // Workaround for https://github.com/HMCL-dev/HMCL/issues/2129 @@ -443,7 +443,7 @@ public ModVersion(RemoteMod.Version version, DownloadPage selfPage) { VBox box = new VBox(8); box.setPadding(new Insets(8)); ModItem modItem = new ModItem(version, selfPage); - modItem.setOnMouseClicked(e -> fireEvent(new DialogCloseEvent())); + FXUtils.onClicked(modItem, () -> fireEvent(new DialogCloseEvent())); box.getChildren().setAll(modItem); SpinnerPane spinnerPane = new SpinnerPane(); ScrollPane scrollPane = new ScrollPane(); @@ -505,7 +505,7 @@ private void loadDependencies(RemoteMod.Version version, DownloadPage selfPage, dependencies.put(dependency.getType(), list); } DependencyModItem dependencyModItem = new DependencyModItem(selfPage.page, dependency.load(), selfPage.version, selfPage.callback); - dependencyModItem.setOnMouseClicked(e -> fireEvent(new DialogCloseEvent())); + FXUtils.onClicked(dependencyModItem, () -> fireEvent(new DialogCloseEvent())); dependencies.get(dependency.getType()).add(dependencyModItem); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index cca80f4af6..02a6d121f0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -97,11 +97,11 @@ public void loadVersion(Profile profile, String versionId) { item.versionProperty().set(null); } - item.installActionProperty().set(e -> { + item.setOnInstall(() -> { Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion)); }); - item.removeActionProperty().set(e -> profile.getDependency().removeLibraryAsync(version, libraryId) + item.setOnRemove(() -> profile.getDependency().removeLibraryAsync(version, libraryId) .thenComposeAsync(profile.getRepository()::saveAsync) .withComposeAsync(profile.getRepository().refreshVersionsAsync()) .withRunAsync(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId)) @@ -121,7 +121,7 @@ public void loadVersion(Profile profile, String versionId) { InstallerItem installerItem = new InstallerItem(libraryId, InstallerItem.Style.LIST_ITEM); installerItem.versionProperty().set(new InstallerItem.InstalledState(libraryVersion, false, false)); - installerItem.removeActionProperty().set(e -> profile.getDependency().removeLibraryAsync(version, libraryId) + installerItem.setOnRemove(() -> profile.getDependency().removeLibraryAsync(version, libraryId) .thenComposeAsync(profile.getRepository()::saveAsync) .withComposeAsync(profile.getRepository().refreshVersionsAsync()) .withRunAsync(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java index 106dfcc114..a19ab6ac50 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java @@ -95,9 +95,7 @@ private Node createCustomIcon() { RipplerContainer container = new RipplerContainer(shape); FXUtils.setLimitWidth(container, 36); FXUtils.setLimitHeight(container, 36); - container.setOnMouseClicked(e -> { - exploreIcon(); - }); + FXUtils.onClicked(container, this::exploreIcon); return container; } @@ -107,7 +105,7 @@ private Node createIcon(VersionIconType type) { RipplerContainer container = new RipplerContainer(imageView); FXUtils.setLimitWidth(container, 36); FXUtils.setLimitHeight(container, 36); - container.setOnMouseClicked(e -> { + FXUtils.onClicked(container, () -> { if (vs != null) { vs.setVersionIcon(type); onAccept(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java index 933bb0887e..4a45486ced 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java @@ -51,7 +51,7 @@ public WorldListItem(World world) { subtitle.set(i18n("world.description", world.getFileName(), formatDateTime(Instant.ofEpochMilli(world.getLastPlayed())), world.getGameVersion() == null ? i18n("message.unknown") : world.getGameVersion())); - setOnMouseClicked(event -> showInfo()); + FXUtils.onClicked(this, this::showInfo); } @Override From e051c212d1a09b37694bcd56f973f8d98fa482d3 Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 25 Oct 2024 12:36:07 +0800 Subject: [PATCH 061/169] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E9=BC=A0=E6=A0=87=E8=BF=94=E5=9B=9E=E9=94=AE=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E4=B8=8A=E7=BA=A7=20(#3381)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 支持使用鼠标返回键返回上级 * fix checkstyle --- .../hmcl/ui/decorator/DecoratorController.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java index 9b07239994..dc34c42deb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java @@ -30,6 +30,8 @@ import javafx.scene.image.Image; import javafx.scene.input.DragEvent; import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.stage.Stage; @@ -144,6 +146,18 @@ public DecoratorController(Stage stage, Node mainPage) { // press ESC to go back onEscPressed(navigator, this::back); + + try { + // For JavaFX 12+ + MouseButton button = MouseButton.valueOf("BACK"); + navigator.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> { + if (e.getButton() == button) { + back(); + e.consume(); + } + }); + } catch (IllegalArgumentException ignored) { + } } public Decorator getDecorator() { From b08d2b0dc021450b04beda7d0a99d0bf061b42b4 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Fri, 25 Oct 2024 16:11:16 +0800 Subject: [PATCH 062/169] Remove some unnecessary tooltips (#3386) * Remove some unnecessary tooltips These texts are basically fixed, and the problem of too long texts can be solved by revising the translation for different languages. Currently, for both Chinese and English, the i18n keys involved in this PR will not be partially obscured due to long text, so their tooltips are removed. * fix checkstyle --- .../java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java | 2 -- .../java/org/jackhuang/hmcl/ui/versions/GameListPage.java | 3 --- .../main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java | 4 ---- 3 files changed, 9 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java index b9395c07dd..4806f58d55 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java @@ -36,7 +36,6 @@ import java.util.Locale; import static org.jackhuang.hmcl.ui.versions.VersionPage.wrap; -import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class LauncherSettingsPage extends DecoratorAnimatedPage implements DecoratorPage, PageAware { @@ -76,7 +75,6 @@ public LauncherSettingsPage() { settingsItem.setTitle(i18n("settings.type.global.manage")); settingsItem.setLeftGraphic(wrap(SVG.GAMEPAD)); settingsItem.activeProperty().bind(tab.getSelectionModel().selectedItemProperty().isEqualTo(gameTab)); - runInFX(() -> FXUtils.installFastTooltip(settingsItem, i18n("settings.type.global.manage"))); settingsItem.setOnAction(e -> tab.select(gameTab)); }) .addNavigationDrawerItem(javaItem -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListPage.java index 1482b510a5..26216e5463 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListPage.java @@ -91,13 +91,11 @@ public GameListPage() { installNewGameItem.setTitle(i18n("install.new_game")); installNewGameItem.setLeftGraphic(VersionPage.wrap(SVG.PLUS_CIRCLE_OUTLINE)); installNewGameItem.setOnAction(e -> Versions.addNewGame()); - runInFX(() -> FXUtils.installFastTooltip(installNewGameItem, i18n("install.new_game"))); }) .addNavigationDrawerItem(installModpackItem -> { installModpackItem.setTitle(i18n("install.modpack")); installModpackItem.setLeftGraphic(VersionPage.wrap(SVG.PACK)); installModpackItem.setOnAction(e -> Versions.importModpack()); - runInFX(() -> FXUtils.installFastTooltip(installModpackItem, i18n("install.modpack"))); }) .addNavigationDrawerItem(refreshItem -> { refreshItem.setTitle(i18n("button.refresh")); @@ -108,7 +106,6 @@ public GameListPage() { globalManageItem.setTitle(i18n("settings.type.global.manage")); globalManageItem.setLeftGraphic(VersionPage.wrap(SVG.GEAR_OUTLINE)); globalManageItem.setOnAction(e -> modifyGlobalGameSettings()); - runInFX(() -> FXUtils.installFastTooltip(globalManageItem, i18n("settings.type.global.manage"))); }); FXUtils.setLimitHeight(bottomLeftCornerList, 40 * 4 + 12 * 2); setLeft(pane, bottomLeftCornerList); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java index e5ed85a480..0866e1e6e4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java @@ -244,7 +244,6 @@ protected Skin(VersionPage control) { versionSettingsItem.setLeftGraphic(wrap(SVG.GEAR_OUTLINE)); versionSettingsItem.setActionButtonVisible(false); versionSettingsItem.activeProperty().bind(control.tab.getSelectionModel().selectedItemProperty().isEqualTo(control.versionSettingsTab)); - runInFX(() -> FXUtils.installFastTooltip(versionSettingsItem, i18n("settings.game"))); versionSettingsItem.setOnAction(e -> control.tab.select(control.versionSettingsTab)); AdvancedListItem installerListItem = new AdvancedListItem(); @@ -253,7 +252,6 @@ protected Skin(VersionPage control) { installerListItem.setLeftGraphic(wrap(SVG.CUBE)); installerListItem.setActionButtonVisible(false); installerListItem.activeProperty().bind(control.tab.getSelectionModel().selectedItemProperty().isEqualTo(control.installerListTab)); - runInFX(() -> FXUtils.installFastTooltip(installerListItem, i18n("settings.tabs.installers"))); installerListItem.setOnAction(e -> control.tab.select(control.installerListTab)); AdvancedListItem modListItem = new AdvancedListItem(); @@ -262,7 +260,6 @@ protected Skin(VersionPage control) { modListItem.setLeftGraphic(wrap(SVG.PUZZLE)); modListItem.setActionButtonVisible(false); modListItem.activeProperty().bind(control.tab.getSelectionModel().selectedItemProperty().isEqualTo(control.modListTab)); - runInFX(() -> FXUtils.installFastTooltip(modListItem, i18n("mods.manage"))); modListItem.setOnAction(e -> control.tab.select(control.modListTab)); AdvancedListItem worldListItem = new AdvancedListItem(); @@ -271,7 +268,6 @@ protected Skin(VersionPage control) { worldListItem.setLeftGraphic(wrap(SVG.EARTH)); worldListItem.setActionButtonVisible(false); worldListItem.activeProperty().bind(control.tab.getSelectionModel().selectedItemProperty().isEqualTo(control.worldListTab)); - runInFX(() -> FXUtils.installFastTooltip(worldListItem, i18n("world.manage"))); worldListItem.setOnAction(e -> control.tab.select(control.worldListTab)); AdvancedListBox sideBar = new AdvancedListBox() From 446cdc32d71d05067706592964061155ffc6a9f4 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Fri, 25 Oct 2024 22:03:52 +0800 Subject: [PATCH 063/169] Adjust language file header comments (#3385) - Update copyright year - Unify typesetting style --- .../resources/assets/lang/I18N.properties | 2 +- .../resources/assets/lang/I18N_es.properties | 2 +- .../resources/assets/lang/I18N_ja.properties | 3 ++- .../resources/assets/lang/I18N_ru.properties | 25 +++++++++---------- .../resources/assets/lang/I18N_zh.properties | 3 ++- .../assets/lang/I18N_zh_CN.properties | 3 ++- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 30077aca46..517d995d43 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2023 huangyuhui and contributors +# Copyright (C) 2024 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 126a653c0a..dbecca9ebe 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2023 huangyuhui and contributors +# Copyright (C) 2024 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 8476fc6b96..1fa331b63b 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2023 huangyuhui and contributors +# Copyright (C) 2024 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,6 +17,7 @@ # # Contributors: zhixuan2333 + about=About about.copyright=著作権 about.copyright.statement=Copyright © 2024 huangyuhui。 diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 36c792bf78..9469297025 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -1,23 +1,22 @@ # # Hello Minecraft! Launcher -# Авторские права (C) 2023 huangyuhui и участников +# Copyright (C) 2024 huangyuhui and contributors # -# Эта программа является бесплатным программным обеспечением: -# вы можете распространять и/или изменять её на условиях GNU -# General Public License, опубликованной Free Software Foundation, -# либо 3й версией лицензии, либо (по вашему выбору) любой версией выше. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. # -# Эта программа распространяется в надежде, что она окажется полезной, -# но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; даже без подразумеваемых гарантий -# ТОВАРНОЙ ПРИГОДНОСТИ или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. -# Подробности смотрите в Стандартной общественной лицензии GNU. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. # -# Вместе с этой программой вы должны были получить копию GNU -# General Public License. Если нет, смотрите . +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # -# Соавторы: vanja-san -# +# Contributors: vanja-san about=О лаунчере about.copyright=Авторские права diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 9e6edc6c13..f6f14d017f 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2023 huangyuhui and contributors +# Copyright (C) 2024 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,6 +17,7 @@ # # Contributors: pan93412 + about=關於 about.copyright=著作權 about.copyright.statement=著作權所有 © 2024 huangyuhui 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 62127bcfd0..97029ec225 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2023 huangyuhui and contributors +# Copyright (C) 2024 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,6 +17,7 @@ # # Contributors: huangyuhui + about=关于 about.copyright=版权 about.copyright.statement=版权所有 © 2024 huangyuhui From da66622994596fdbe9996f8696a9517e77660425 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Fri, 25 Oct 2024 22:04:48 +0800 Subject: [PATCH 064/169] Adjust Microsoft login hint (zh_CN only) (#3384) --- .../assets/lang/I18N_zh_CN.properties | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) 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 97029ec225..887a328136 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -112,23 +112,23 @@ account.methods.microsoft.error.wrong_verify_method=请在微软账户登录页 account.methods.microsoft.logging_in=登录中…… account.methods.microsoft.makegameidsettings=创建档案 / 编辑档案名称 account.methods.microsoft.hint=你需要按照以下步骤添加账户:\n\ - \ 1.点击“登录”按钮;\n\ - \ 2.在弹出的网页中输入 HMCL 显示的代码,并点击“下一步”;\n\ - \ 3.按照网站的提示登录;\n\ - \ 4.当网站提示“是否允许此应用访问你的信息?”的标识时,请点击“是”;\n\ - \ 5.在网站提示“大功告成”后,只需等待账户完成添加即可。\n\ - 若网站提示“出现错误”的标识或账户添加失败时,请重新按照以上步骤重新添加。\n\ - 若设备网络环境不佳,可能登录网站加载很慢甚至无法加载,此时请使用网络代理并重试。\n\ + \ 1. 点击“登录”按钮;\n\ + \ 2. 在弹出的网页中输入 HMCL 显示的代码,并点击“允许访问”;\n\ + \ 3. 按照网站的提示登录;\n\ + \ 4. 当网站提示“是否允许此应用访问你的信息?”时,请点击“接受”;\n\ + \ 5. 在网站提示“大功告成”后,只需等待账户完成添加即可。\n\ + 若网站提示“出现错误”或账户添加失败时,请重新按照以上步骤重新添加。\n\ + 若设备网络环境不佳,可能会导致网页加载缓慢甚至无法加载,请使用网络代理并重试。\n\ 如遇到问题,你可以点击右上角帮助按钮进行求助。 account.methods.microsoft.manual=你需要按照以下步骤添加:\n\ - \ 1.点击“登录”按钮;\n\ - \ 2.在弹出的网页中输入:%1$s (已自动复制,点此再次复制),并点击“下一步”;\n\ - \ 3.按照网站的提示登录;\n\ - \ 4.当网站提示“是否允许此应用访问你的信息?”的标识时,请点击“是”;\n\ - \ 5.在网站提示“大功告成”后,只需等待账户完成添加即可。\n\ + \ 1. 点击“登录”按钮;\n\ + \ 2. 在弹出的网页中输入 %1$s (已自动复制),并点击“允许访问”;\n\ + \ 3. 按照网站的提示登录;\n\ + \ 4. 当网站提示“是否允许此应用访问你的信息?”时,请点击“接受”;\n\ + \ 5. 在网站提示“大功告成”后,只需等待账户完成添加即可。\n\ 若网站未能显示,请手动在浏览器中打开:%2$s\n\ - 若网站提示“出现错误”的标识或账户添加失败时,请重新按照以上步骤重新添加。\n\ - 若设备网络环境不佳,可能登录网站加载很慢甚至无法加载,此时请使用网络代理并重试。\n\ + 若网站提示“出现错误”或账户添加失败时,请重新按照以上步骤重新添加。\n\ + 若设备网络环境不佳,可能会导致网页加载缓慢甚至无法加载,请使用网络代理并重试。\n\ 如遇到问题,你可以点击右上角帮助按钮进行求助。 account.methods.microsoft.profile=账户设置页 account.methods.microsoft.purchase=购买 Minecraft From 3313a1ed27574aae6bd58df24a4c9ef11146e338 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Fri, 25 Oct 2024 22:05:19 +0800 Subject: [PATCH 065/169] For language selection, remove all region descriptions (#3383) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, HMCL does not provide variants for languages ​​(e.g. US, UK, etc.). For Chinese, there are already descriptions of Simplified (简体) and Traditional (繁體) to distinguish them, so keep them. --- HMCL/src/main/resources/assets/lang/I18N.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 517d995d43..712359e9ba 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -729,7 +729,7 @@ java.reveal=Reveal the Java directory java.uninstall=Uninstall Java java.uninstall.confirm=Are you sure you want to uninstall this Java? This action cannot be undone! -lang=English (United States) +lang=English lang.default=Use System Locales 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 cause unable to launch the game or affect the game experience.\nDo you still want to continue to launch? 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 887a328136..8b0d363af7 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -558,7 +558,7 @@ java.reveal=浏览 Java 文件夹 java.uninstall=卸载此 Java java.uninstall.confirm=你确定要卸载此 Java 吗?此操作无法撤销! -lang=简体中文 (中国大陆) +lang=简体中文 lang.default=跟随系统语言 launch.advice==%s 是否继续启动? From b3f27cc96e244689b2ca88949afd2bbc4e5cc097 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Fri, 25 Oct 2024 22:30:12 +0800 Subject: [PATCH 066/169] Adjust homepage hint typesetting (#3382) - Adjustments made for all languages. - Remove outdated hidden hint links. --- HMCL/src/main/resources/assets/lang/I18N.properties | 10 ++-------- .../main/resources/assets/lang/I18N_es.properties | 10 ++++------ .../main/resources/assets/lang/I18N_ja.properties | 13 ++++++------- .../main/resources/assets/lang/I18N_ru.properties | 13 ++++++------- .../main/resources/assets/lang/I18N_zh.properties | 10 ++++------ .../resources/assets/lang/I18N_zh_CN.properties | 10 ++++------ 6 files changed, 26 insertions(+), 40 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 712359e9ba..ea95743789 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1287,18 +1287,12 @@ update.changelog=Changelog update.channel.dev=Beta update.channel.dev.hint=You are currently using a Beta channel build of the launcher, which may include some extra features, but is also sometimes more unstable than the Release channel.\n\ \n\ - If you encounter any bugs or problems, please navigate to "Settings → Feedback" or submit your feedback through the following channels.\n\ - \n\ - GitHub Discord QQ Group\n\ - \n\ - Click Here to Hide This Tooltip for the Current Channel + If you encounter any bugs or problems, please navigate to Settings → Feedback page to submit your feedback. update.channel.dev.title=Beta Channel Notice update.channel.nightly=Nightly update.channel.nightly.hint=You are currently using a Nightly channel build of the launcher, which may include some extra features, but is also always more unstable than the other channels.\n\ \n\ - If you encounter any bugs or problems, please navigate to "Settings → Feedback" or submit your feedback through the following channels.\n\ - \n\ - GitHub Discord QQ Group + If you encounter any bugs or problems, please navigate to Settings → Feedback page to submit your feedback. update.channel.nightly.title=Nightly Channel Notice update.channel.stable=Release update.checking=Checking for Updates diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index dbecca9ebe..50011d35ee 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -1033,15 +1033,13 @@ update.accept=Actualizar update.changelog=Registro de cambios update.channel.dev=Beta update.channel.dev.hint=Actualmente está utilizando una versión beta del launcher, que puede incluir algunas características adicionales, pero también es más inestable que las versiones de lanzamiento.\n\ -\n\ -Si encuentra algún error o problema, puede ir a la página de comentarios para informar de ello, o bien para decírnoslo en nuestro Discord o en la comunidad QQ.\n\ -\n\ -Haga clic aquí para ocultar el recordatorio para la versión de prueba actual. + \n\ + Si encuentra algún error o problema, puede ir a la página de comentarios para informar de ello. update.channel.dev.title=Aviso de versión beta update.channel.nightly=Nocturna update.channel.nightly.hint=Estás utilizando una versión nocturna del launcher, que puede incluir algunas características adicionales, pero también es siempre más inestable que las otras versiones.\n\ -\n\ -Si encuentra algún error o problema, puede ir a la página de comentarios para informar de ello, o bien para decírnoslo en nuestro Discord o en la comunidad QQ community. + \n\ + Si encuentra algún error o problema, puede ir a la página de comentarios para informar de ello. update.channel.nightly.title=Aviso de versión nocturna update.channel.stable=Estable update.checking=Buscando actualizaciones diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 1fa331b63b..a6d47a6c19 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -854,15 +854,14 @@ update=更新 update.accept=更新 update.changelog=変更 update.channel.dev=ベータ -update.channel.dev.hint=ベータ版を使用しています。ベータ版には、リリースバージョンと比較していくつかの追加機能が含まれている可能性があり、テストにのみ使用されます。\n\ - ベータ版は不安定なはずです!\n\ - 問題が発生した場合は、フィードバックページにアクセスして報告するか、チャット DiscordまたはQQで問題を報告します。\n\n\ - 現在のテスト版のヒントを非表示にするには、ここをクリックしてください。 +update.channel.dev.hint=ベータ版を使用しています。ベータ版には、リリースバージョンと比較していくつかの追加機能が含まれている可能性があり、テストにのみ使用されます。ベータ版は不安定なはずです!\n\ + \n\ + 問題が発生した場合は、フィードバックページにアクセスして報告してください。 update.channel.dev.title=ベータ版のヒント update.channel.nightly=アルファ -update.channel.nightly.hint=アルファ版を使用しています。これには、ベータ版およびリリース版と比較していくつかの追加機能が含まれている可能性があり、テストにのみ使用されます。\n\ - アルファ版は不安定です!\n\ - 問題が発生した場合は、フィードバックページにアクセスして報告するか、チャット Discordで問題を報告します。 +update.channel.nightly.hint=アルファ版を使用しています。これには、ベータ版およびリリース版と比較していくつかの追加機能が含まれている可能性があり、テストにのみ使用されます。アルファ版は不安定です!\n\ + \n\ + 問題が発生した場合は、フィードバックページにアクセスして報告してください。 update.channel.nightly.title=アルファ版のヒント update.channel.stable=リリース update.checking=更新の確認 diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 9469297025..0a484a9244 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -926,15 +926,14 @@ update=Обновление update.accept=Обновить update.changelog=Изменения update.channel.dev=Бета -update.channel.dev.hint=Вы используете бета-версию, которая может включать некоторые дополнительные функции по сравнению с релизной версией, используемой только для тестирования.\n\ - Бета-версия может быть нестабильной!\n\ - Если вы встретили какие-то проблемы, вы можете зайти на страницу обратной связи, чтобы сообщить о них, или присоединиться к чату Discord или QQ, чтобы сообщить о проблемах.\n\n\ - Нажмите здесь, чтобы скрыть подсказку для текущей тестовой версии. +update.channel.dev.hint=Вы используете бета-версию, которая может включать некоторые дополнительные функции по сравнению с релизной версией, используемой только для тестирования. Бета-версия может быть нестабильной!\n\ + \n\ + Если вы встретили какие-то проблемы, вы можете зайти на страницу обратной связи. update.channel.dev.title=Подсказки для бета-версии update.channel.nightly=Альфа -update.channel.nightly.hint=Вы используете альфа-версию, которая может включать некоторые дополнительные функциональные возможности по сравнению с бета-версией и версией релиза, используемой только для тестирования.\n\ - Альфа-версия может быть нестабильной!\n\ - Если вы встретили какие-то проблемы, вы можете зайти на страницу обратной связи, чтобы сообщить о них, или присоединиться к чату Discord или QQ, чтобы сообщить о проблемах. +update.channel.nightly.hint=Вы используете альфа-версию, которая может включать некоторые дополнительные функциональные возможности по сравнению с бета-версией и версией релиза, используемой только для тестирования. Альфа-версия может быть нестабильной!\n\ + \n\ + Если вы встретили какие-то проблемы, вы можете зайти на страницу обратной связи. update.channel.nightly.title=Подсказки для альфа-версии update.channel.stable=Релиз update.checking=Проверка наличия обновлений diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index f6f14d017f..64c06b5b57 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1085,15 +1085,13 @@ update=啟動器更新 update.accept=更新 update.changelog=更新日誌 update.channel.dev=開發版 -update.channel.dev.hint=你正在使用 HMCL 開發版。開發版包含一些未在穩定版中包含的測試性功能,僅用於體驗新功能。\n\ - 開發版功能未受充分驗證,使用起來可能不穩定!\n\ - 如果你遇到了使用問題,可以透過設定中 回報頁面 提供的管道進行回報。\n\ +update.channel.dev.hint=你正在使用 HMCL 開發版。開發版包含一些未在穩定版中包含的測試性功能,僅用於體驗新功能。開發版功能未受充分驗證,使用起來可能不穩定!\n\ \n\ - 為目前版本隱藏該提示。 + 如果你遇到了使用問題,可以透過設定中 回報頁面 提供的管道進行回報。 update.channel.dev.title=開發版提示 update.channel.nightly=預覽版 -update.channel.nightly.hint=你正在使用 HMCL 預覽版。預覽版更新較為頻繁,包含一些未在穩定版和開發版中包含的測試性功能,僅用於體驗新功能。\n\ - 預覽版功能未受充分驗證,使用起來可能不穩定!\n\ +update.channel.nightly.hint=你正在使用 HMCL 預覽版。預覽版更新較為頻繁,包含一些未在穩定版和開發版中包含的測試性功能,僅用於體驗新功能。預覽版功能未受充分驗證,使用起來可能不穩定!\n\ + \n\ 如果你遇到了使用問題,可以透過設定中 回報頁面 提供的管道進行回報。 update.channel.nightly.title=預覽版提示 update.channel.stable=穩定版 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 8b0d363af7..bdfa31158d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1096,15 +1096,13 @@ update=启动器更新 update.accept=更新 update.changelog=更新日志 update.channel.dev=开发版 -update.channel.dev.hint=你正在使用 HMCL 开发版。开发版包含一些未在稳定版中包含的测试性功能,仅用于体验新功能。\n\ - 开发版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ - 如果你使用时遇到了问题,可以通过设置中反馈页面提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。\n\ +update.channel.dev.hint=你正在使用 HMCL 开发版。开发版包含一些未在稳定版中包含的测试性功能,仅用于体验新功能。开发版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ \n\ - 为当前版本隐藏该提示。 + 如果你使用时遇到了问题,可以通过设置中反馈页面提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。 update.channel.dev.title=开发版提示 update.channel.nightly=预览版 -update.channel.nightly.hint=你正在使用 HMCL 预览版。预览版更新较为频繁,包含一些未在稳定版和开发版中包含的测试性功能,仅用于体验新功能。\n\ - 预览版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ +update.channel.nightly.hint=你正在使用 HMCL 预览版。预览版更新较为频繁,包含一些未在稳定版和开发版中包含的测试性功能,仅用于体验新功能。预览版功能未受充分验证,使用起来可能不稳定!下载稳定版\n\ + \n\ 如果你使用时遇到了问题,可以通过设置中反馈页面提供的渠道进行反馈。欢迎关注 B 站账号 @huanghongxun 以关注 HMCL 的开发进展。 update.channel.nightly.title=预览版提示 update.channel.stable=稳定版 From 8775194d26ea4bf96d2929ea9aecc07a9fcfe0df Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 26 Oct 2024 01:14:28 +0800 Subject: [PATCH 067/169] Adjust i18n for Linux/FreeBSD-specific settings in Advanced Settings (#3388) I checked the code and it looked like this was a Linux/FreeBSD-specific feature, so I adjusted the translation for that. --- HMCL/src/main/resources/assets/lang/I18N.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_es.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_ja.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_ru.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index ea95743789..da2dbbe79d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1185,8 +1185,8 @@ settings.advanced.renderer.llvmpipe=Software (Poor performance and best compatib settings.advanced.renderer.zink=Vulkan (Best performance and poor compatibility) settings.advanced.server_ip=Server Address settings.advanced.server_ip.prompt=Automatically join after launching the game -settings.advanced.use_native_glfw=[Linux Only] Use system GLFW -settings.advanced.use_native_openal=[Linux Only] Use system OpenAL +settings.advanced.use_native_glfw=[Linux/FreeBSD Only] Use System GLFW +settings.advanced.use_native_openal=[Linux/FreeBSD Only] Use System OpenAL settings.advanced.workaround=Workaround settings.advanced.workaround.warning=Workaround options are intended only for advanced users. Tweaking with these options may crash the game. Unless you know what you are doing, please do not edit these options. settings.advanced.wrapper_launcher=Wrapper Command diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 50011d35ee..1196c0812e 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -937,8 +937,8 @@ settings.advanced.post_exit_command=Comando post-salida settings.advanced.post_exit_command.prompt=Comandos a ejecutar tras la salida del juego settings.advanced.server_ip=Dirección del servidor settings.advanced.server_ip.prompt=Entrar automáticamente después de ejecutar el juego -settings.advanced.use_native_glfw=[Sólo Linux] Utilizar GLFW nativo -settings.advanced.use_native_openal=[Sólo Linux] Utilizar OpenAL nativo +settings.advanced.use_native_glfw=[Sólo Linux/FreeBSD] Utilizar GLFW nativo +settings.advanced.use_native_openal=[Sólo Linux/FreeBSD] Utilizar OpenAL nativo settings.advanced.workaround=Métodos alternativos settings.advanced.workaround.warning=Éstas opciones están pensadas sólo para usuarios expertos. Jugar con estas opciones puede romper el juego. A menos que sepas lo que estás haciendo, por favor no modifiques estas opciones. settings.advanced.wrapper_launcher=Wrapper Launcher diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index a6d47a6c19..39e8726e62 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -762,8 +762,8 @@ settings.advanced.post_exit_command=終了後のコマンド settings.advanced.post_exit_command.prompt=ゲーム終了後に実行されます settings.advanced.server_ip=サーバーアドレス settings.advanced.server_ip.prompt=ゲームの起動時にサーバーに参加する -settings.advanced.use_native_glfw=システムGLFWを使用する -settings.advanced.use_native_openal=システムOpenALを使用する +settings.advanced.use_native_glfw=[Linux/FreeBSDのみ]システムGLFWを使用する +settings.advanced.use_native_openal=[Linux/FreeBSDのみ]システムOpenALを使用する settings.advanced.workaround=デバッグ用オプション settings.advanced.workaround.warning=デバッグオプションはプロフェッショナルのみ使用可能です。デバッグオプションにより、ゲームが起動しない場合があります。これらのオプションは、ご自分が何をしているのかが分からない限り、変更しないでください。 settings.advanced.wrapper_launcher=パッキングオーダー diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 0a484a9244..b46233b082 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -830,8 +830,8 @@ settings.advanced.post_exit_command=Команда после выхода settings.advanced.post_exit_command.prompt=Команды, которые необходимо выполнить после выхода из игры settings.advanced.server_ip=Адрес сервера settings.advanced.server_ip.prompt=Присоединяться к серверу при запуске игры -settings.advanced.use_native_glfw=Использовать системный GLFW -settings.advanced.use_native_openal=Использовать системный OpenAL +settings.advanced.use_native_glfw=[Только для Linux/FreeBSD] Использовать системный GLFW +settings.advanced.use_native_openal=[Только для Linux/FreeBSD] Использовать системный OpenAL settings.advanced.workaround=Обходные пути settings.advanced.workaround.warning=Варианты обхода предназначены только для опытных пользователей. Изменение этих параметров может привести к вылету игры. Если не знаете, что делаете, то не изменяйте эти параметры. settings.advanced.wrapper_launcher=Команда-оболочка diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 64c06b5b57..5edc152be8 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -987,8 +987,8 @@ settings.advanced.renderer.llvmpipe=軟繪製器 (效能較差,相容性最好 settings.advanced.renderer.zink=Vulkan (效能最好,相容性較差) settings.advanced.server_ip=伺服器位址 settings.advanced.server_ip.prompt=預設,啟動遊戲後直接進入對應伺服器 -settings.advanced.use_native_glfw=使用系統 GLFW -settings.advanced.use_native_openal=使用系統 OpenAL +settings.advanced.use_native_glfw=[僅限 Linux/FreeBSD] 使用系統 GLFW +settings.advanced.use_native_openal=[僅限 Linux/FreeBSD] 使用系統 OpenAL settings.advanced.workaround=除錯選項 settings.advanced.workaround.warning=除錯選項僅提供給專業玩家使用。修改除錯選項可能會導致遊戲無法啟動。除非你知道你在做什麼,否則請不要修改這些選項。 settings.advanced.wrapper_launcher=前置指令 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 bdfa31158d..16d81e8523 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -998,8 +998,8 @@ settings.advanced.renderer.llvmpipe=软渲染器 (性能较差,兼容性最好 settings.advanced.renderer.zink=Vulkan (性能最好,兼容性较差) settings.advanced.server_ip=服务器地址 settings.advanced.server_ip.prompt=默认,启动游戏后可以直接进入对应服务器 -settings.advanced.use_native_glfw=使用系统 GLFW -settings.advanced.use_native_openal=使用系统 OpenAL +settings.advanced.use_native_glfw=[仅 Linux/FreeBSD] 使用系统 GLFW +settings.advanced.use_native_openal=[仅 Linux/FreeBSD] 使用系统 OpenAL settings.advanced.workaround=调试选项 settings.advanced.workaround.warning=调试选项仅提供给专业玩家使用。调试选项可能会导致游戏无法启动。除非你知道你在做什么,否则请不要修改这些选项! settings.advanced.wrapper_launcher=包装命令 From c7122b3fff51f124f7a8a17976e53e2c462da4e5 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 26 Oct 2024 02:45:58 +0800 Subject: [PATCH 068/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=A6=96=E9=A1=B5?= =?UTF-8?q?=E5=85=AC=E5=91=8A=20(#3378)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * 添加公告隐藏动画 * update * update --- .../org/jackhuang/hmcl/ui/Controllers.java | 3 -- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 2 +- .../hmcl/ui/construct/AnnouncementCard.java | 29 ++++++++++++++----- .../org/jackhuang/hmcl/ui/main/MainPage.java | 28 +++++++++++------- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java index 724eb7deff..44e208ac58 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -391,9 +391,6 @@ public static void onHyperlinkAction(String href) { Controllers.getSettingsPage().showFeedback(); Controllers.navigate(Controllers.getSettingsPage()); break; - case "hmcl://hide-announcement": - Controllers.getRootPage().getMainPage().hideAnnouncementPane(); - break; } } else { FXUtils.openLink(href); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index 141ac78a27..d709b9223e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -1005,8 +1005,8 @@ public static List parseSegment(String segment, Consumer hyperlink hyperlinkAction.accept(link); }); text.setCursor(Cursor.HAND); + text.setFill(Color.web("#0070E0")); text.setUnderline(true); - text.setFill(Color.web("#283593")); texts.add(text); } else if ("b".equals(element.getTagName())) { Text text = new Text(element.getTextContent()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AnnouncementCard.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AnnouncementCard.java index 7262bcadd3..5e80222c4d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AnnouncementCard.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/AnnouncementCard.java @@ -17,21 +17,36 @@ */ package org.jackhuang.hmcl.ui.construct; +import javafx.scene.Cursor; +import javafx.scene.Node; import javafx.scene.control.Label; +import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.scene.text.TextFlow; +import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; +import org.jackhuang.hmcl.ui.SVG; -public class AnnouncementCard extends VBox { +public final class AnnouncementCard extends VBox { - public AnnouncementCard(String title, String content) { - TextFlow tf = FXUtils.segmentToTextFlow(content, Controllers::onHyperlinkAction); + public AnnouncementCard(String title, String content, Runnable onClose) { + TextFlow body = FXUtils.segmentToTextFlow(content, Controllers::onHyperlinkAction); + body.setLineSpacing(4); - Label label = new Label(title); - label.getStyleClass().add("title"); - getChildren().setAll(label, tf); - setSpacing(14); + BorderPane titleBar = new BorderPane(); + titleBar.getStyleClass().add("title"); + titleBar.setLeft(new Label(title)); + + if (onClose != null) { + Node hideNode = SVG.CLOSE.createIcon(Theme.blackFill(), 20, 20); + hideNode.setOnMouseClicked(e -> onClose.run()); + hideNode.setCursor(Cursor.HAND); + titleBar.setRight(hideNode); + } + + getChildren().setAll(titleBar, body); + setSpacing(16); getStyleClass().addAll("card", "announcement"); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java index f33272555e..1c0f991627 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java @@ -32,7 +32,6 @@ import javafx.scene.control.Label; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; -import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.shape.Rectangle; @@ -46,6 +45,8 @@ import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; import org.jackhuang.hmcl.ui.animation.AnimationUtils; +import org.jackhuang.hmcl.ui.animation.ContainerAnimations; +import org.jackhuang.hmcl.ui.animation.TransitionPane; import org.jackhuang.hmcl.ui.construct.AnnouncementCard; import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.ui.construct.PopupMenu; @@ -83,7 +84,7 @@ public final class MainPage extends StackPane implements DecoratorPage { private final ObservableList versionNodes; private Profile profile; - private VBox announcementPane; + private TransitionPane announcementPane; private final StackPane updatePane; private final JFXButton menuButton; @@ -102,13 +103,23 @@ public final class MainPage extends StackPane implements DecoratorPage { setPadding(new Insets(20)); if (Metadata.isNightly() || (Metadata.isDev() && !Objects.equals(Metadata.VERSION, config().getShownTips().get(ANNOUNCEMENT)))) { - announcementPane = new VBox(16); + AnnouncementCard announcementCard = null; + if (Metadata.isNightly()) { - announcementPane.getChildren().add(new AnnouncementCard(i18n("update.channel.nightly.title"), i18n("update.channel.nightly.hint"))); + announcementCard = new AnnouncementCard(i18n("update.channel.nightly.title"), i18n("update.channel.nightly.hint"), null); } else if (Metadata.isDev()) { - announcementPane.getChildren().add(new AnnouncementCard(i18n("update.channel.dev.title"), i18n("update.channel.dev.hint"))); + announcementCard = new AnnouncementCard(i18n("update.channel.dev.title"), i18n("update.channel.dev.hint"), this::hideAnnouncementPane); + } + + if (announcementCard != null) { + VBox announcementBox = new VBox(16); + announcementBox.getChildren().add(announcementCard); + + announcementPane = new TransitionPane(); + announcementPane.setContent(announcementBox, ContainerAnimations.NONE.getAnimationProducer()); + + getChildren().add(announcementPane); } - getChildren().add(announcementPane); } updatePane = new StackPane(); @@ -290,10 +301,7 @@ private void closeUpdateBubble() { public void hideAnnouncementPane() { if (announcementPane != null) { config().getShownTips().put(ANNOUNCEMENT, Metadata.VERSION); - Pane parent = (Pane) announcementPane.getParent(); - if (parent != null) - parent.getChildren().remove(announcementPane); - announcementPane = null; + announcementPane.setContent(new StackPane(), ContainerAnimations.FADE.getAnimationProducer()); } } From 3193e028670d1c6591636fcb6bdf4deb919cf9e6 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 26 Oct 2024 02:49:58 +0800 Subject: [PATCH 069/169] Adjust feedback page i18n (#3389) - Adjust for all languages. - Add missing translations to some languages. --- HMCL/src/main/resources/assets/lang/I18N.properties | 6 +++--- HMCL/src/main/resources/assets/lang/I18N_es.properties | 7 ++++++- HMCL/src/main/resources/assets/lang/I18N_ja.properties | 8 +++++++- HMCL/src/main/resources/assets/lang/I18N_ru.properties | 7 ++++++- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 8 ++++---- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index da2dbbe79d..103e6204fa 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -399,11 +399,11 @@ fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher has provided feedback=Feedback feedback.channel=Feedback Channel feedback.discord=Discord -feedback.discord.statement=Join our Discord community. +feedback.discord.statement=Welcome to join our Discord server. feedback.github=GitHub Issues feedback.github.statement=Submit an issue on GitHub. -feedback.qq_group=HMCL User Group -feedback.qq_group.statement=Welcome to join our user group. +feedback.qq_group=HMCL User QQ Group +feedback.qq_group.statement=Welcome to join our user QQ group. file=File diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 1196c0812e..647d665ce0 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -345,8 +345,13 @@ fatal.illegal_char=Su ruta de usuario contiene un carácter ilegal '\=', por lo Por ejemplo, no podrá utilizar authlib-injector o cambiar el skin de su cuenta offline. feedback=Comentarios +feedback.channel=Canal de comentarios feedback.discord=Discord -feedback.discord.statement=¡Únete a nuestra comunidad de Discord! +feedback.discord.statement=¡Únase a nuestro servidor Discord! +feedback.github=GitHub Issues +feedback.github.statement=Envíe una propuesta en GitHub. +feedback.qq_group=Grupo QQ de usuarios de HMCL +feedback.qq_group.statement=¡Únase a nuestro grupo QQ de usuarios! file=Archivo diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 39e8726e62..874f366084 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -314,9 +314,15 @@ fatal.apply_update_failure=ごめんなさい、Hello Minecraft! Launcher 何か fatal.samba=If you are trying to run HMCL in a shared folder by Samba, HMCL may not working, please try updating your Java or running HMCL in a local folder. fatal.illegal_char=ユーザーフォルダーのパスに不正な文字'='が含まれています, ログインアカウントやオフラインログインではスキンの変更ができなくなり。 + feedback=フィードバック +feedback.channel=フィードバックチャンネル feedback.discord=Discord -feedback.discord.statement=チャットに参加しよう! +feedback.discord.statement=Discordサーバーに参加してください! +feedback.github=GitHub Issues +feedback.github.statement=GitHubで問題を送信します。 +feedback.qq_group=HMCLユーザーQQグループ +feedback.qq_group.statement=ユーザーQQグループに参加してください! file=ファイル diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index b46233b082..338a8c4c8c 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -335,8 +335,13 @@ fatal.samba=Если вы пытаетесь запустить лаунчер fatal.illegal_char=Недопустимый символ '=' в пути к папке пользователя. Лаунчер может работать, но некоторые функции не будут работать.\nВы не сможете использовать аккаунт authlib-injector или изменить офлайн скин. feedback=Обратная связь +feedback.channel=Канал обратной связи feedback.discord=Discord -feedback.discord.statement=Присоединиться! +feedback.discord.statement=Добро пожаловать присоединиться к нашему Discord. +feedback.github=Проблемы GitHub +feedback.github.statement=Отправьте проблему на GitHub. +feedback.qq_group=Группа QQ пользователя HMCL +feedback.qq_group.statement=Добро пожаловать присоединиться к нашей группе QQ! file=Файл diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 5edc152be8..2634f0267f 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -375,12 +375,12 @@ fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已為 Window feedback=回報 feedback.channel=回報管道 -feedback.discord=Discord -feedback.discord.statement=歡迎加入 Discord 討論區,加入後請遵守討論區規定 +feedback.discord=Discord 伺服器 +feedback.discord.statement=歡迎加入 Discord 伺服器,加入後請遵守討論區規則 feedback.github=GitHub Issues feedback.github.statement=提交一個 GitHub Issue -feedback.qq_group=HMCL 使用者群組 -feedback.qq_group.statement=歡迎加入 HMCL 使用者群組,加入後請遵守群規 +feedback.qq_group=HMCL 使用者 QQ 群組 +feedback.qq_group.statement=歡迎加入 HMCL 使用者 QQ 群組,加入後請遵守群組規則 file=檔案 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 16d81e8523..3a41fe1cd5 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -386,7 +386,7 @@ fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher 已为 Window feedback=反馈 feedback.channel=反馈渠道 feedback.discord=Discord -feedback.discord.statement=欢迎加入 Discord 讨论区,加入后请遵守讨论区规定 +feedback.discord.statement=欢迎加入 Discord 服务器,加入后请遵守讨论区规定 feedback.github=GitHub Issue feedback.github.statement=提交一个 GitHub Issue feedback.qq_group=HMCL 用户群 From 4052136217b388963f9a246f90361b4456015570 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 26 Oct 2024 02:51:19 +0800 Subject: [PATCH 070/169] Adjust sponsor hint i18n (#3387) - Adjust for all languages. - For BMCLAPI: Make it clear that this is a service for users in Chinese Mainland. - For HMCL: Since the page that was opened was not Afdian but the GitHub repo page, I made adjustments based on the actual situation. - Fix some typos. --- HMCL/src/main/resources/assets/lang/I18N.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_es.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_ja.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_ru.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 103e6204fa..843b8c5295 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1273,7 +1273,7 @@ settings.type.special.edit=Edit Current Instance Settings settings.type.special.edit.hint=Current instance "%s" has enabled the "Instance-specific Settings", all options on this page will NOT affect that instance. Click here to edit its own settings. sponsor=Donors -sponsor.bmclapi=Downloads are provided by BMCLAPI. Click here for more information. +sponsor.bmclapi=Downloads for Chinese Mainland are provided by BMCLAPI. Click here for more information. sponsor.hmcl=Hello Minecraft! Launcher is a FOSS Minecraft launcher which allows users to manage multiple Minecraft instances easily. Click here for more information. system.architecture=Architecture diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 647d665ce0..78cf70dcee 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -1027,8 +1027,8 @@ settings.type.special.edit=Editar ajustes de la instancia actual settings.type.special.edit.hint=La instancia actual [%s] tiene activada la configuración por instancia, todas las opciones de esta página NO afectarán a esa instancia. Haga clic aquí para modificar sus propias opciones. sponsor=Donantes -sponsor.bmclapi=Las descargas son proporcionadas por BMCLAPI. Haz clic aquí para obtener más información. -sponsor.hmcl=¡Hello Minecraft! Launcher es un launcher FOSS de Minecraft que permite a los usuarios gestionar múltiples instancias de Minecraft fácilmente. Usted puede donar a nosotros en Afdian para apoyar nuestro alojamiento de archivos y el desarrollo del proyecto. Haga clic aquí para obtener más información. +sponsor.bmclapi=Las descargas de China continental son proporcionadas por BMCLAPI. Haga clic aquí para obtener más información. +sponsor.hmcl=Hello Minecraft! Launcher es un launcher FOSS de Minecraft que permite a los usuarios gestionar múltiples instancias de Minecraft fácilmente. Haga clic aquí para obtener más información. system.architecture=Arquitectura system.operating_system=Sistema operativo diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 874f366084..c191bcd241 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -850,8 +850,8 @@ settings.type.special.edit=現在のゲーム設定を構成します settings.type.special.edit.hint=現在のゲームバージョン %s で特殊な設定が有効になっているため、現在のページのオプションはそのゲームバージョンに適用されません。リンクをクリックして、現在のゲーム設定を構成します。 sponsor=寄付 -sponsor.bmclapi=ダウンロードサービスはBMCLAPIによって提供されます。詳細については、ここをクリックしてください。 -sponsor.hmcl=こんにちはマインクラフト! Launcherは、無料のオープンソースのMinecraftランチャーであり、ユーザーは複数の個別のMinecraftインストールを簡単に管理できます。私たちはAfdianを使用して、ホスティングとプロジェクト開発の費用を引き続き支払います。詳細については、ここをクリックしてください。 +sponsor.bmclapi=中国本土向けのダウンロードサービスはBMCLAPIによって提供されています。詳細については、ここをクリックしてください。 +sponsor.hmcl=Hello Minecraft! Launcherは、無料のオープンソースのMinecraftランチャーであり、ユーザーは複数の個別のMinecraftインストールを簡単に管理できます。詳細については、ここをクリックしてください。 system.architecture=Arch system.operating_system=OS diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 338a8c4c8c..e6475ca918 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -921,8 +921,8 @@ settings.type.special.edit=Изменить настройки текущего settings.type.special.edit.hint=В текущем экземпляре [%s] включены раздельные настройки для экземпляров, параметры на этой странице НЕ повлияют на этот экземпляр. Нажмите здесь, чтобы изменить раздельные параметры. sponsor=Спонсоры -sponsor.bmclapi=Скачивание предоставляется BMCLAPI. Нажмите здесь для получения подробностей. -sponsor.hmcl=Hello Minecraft! Launcher — лаунчер Minecraft с открытым исходным кодом, который позволяет пользователям легко управлять несколькими экземплярами Minecraft. Пожертвуйте нам на Afdian для поддержки нашего файлового хостинга и развития проекта. Для получения подробностей нажмите здесь. +sponsor.bmclapi=Загрузки для материкового Китая предоставляются BMCLAPI. Нажмите здесь для получения подробностей. +sponsor.hmcl=Hello Minecraft! Launcher — лаунчер Minecraft с открытым исходным кодом, который позволяет пользователям легко управлять несколькими экземплярами Minecraft. Для получения подробностей нажмите здесь. system.architecture=Архитектура system.operating_system=Операционная система diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 2634f0267f..7b9ca4f731 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1073,8 +1073,8 @@ settings.type.special.edit=編輯實例特定遊戲設定 settings.type.special.edit.hint=目前實例「%s」啟用了「實例特定遊戲設定」,本頁面選項不對目前實例生效。點擊連結以修改目前實例設定。 sponsor=贊助 -sponsor.bmclapi=中國大陸下載源由 BMCLAPI 提供高速下載服務。 -sponsor.hmcl=Hello Minecraft! Launcher 是一個免費、自由、開源的 Minecraft 啟動器,允許玩家方便快捷地安裝、管理、執行遊戲。點選此處查閱更多詳細訊息。 +sponsor.bmclapi=中國大陸下載源由 BMCLAPI 提供高速下載服務。點選此處查閱詳細訊息。 +sponsor.hmcl=Hello Minecraft! Launcher 是一個免費、自由、開源的 Minecraft 啟動器,允許玩家方便快捷地安裝、管理、執行遊戲。點選此處查閱詳細訊息。 system.architecture=架構 system.operating_system=作業系統 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 3a41fe1cd5..eae47b67ce 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1084,8 +1084,8 @@ settings.type.special.edit=编辑版本特定游戏设置 settings.type.special.edit.hint=当前游戏版本“%s”启用了“版本特定游戏设置”,因此本页面选项不对该版本生效。点击链接前往该版本的“游戏设置”页。 sponsor=赞助 -sponsor.bmclapi=国内下载源由 BMCLAPI 提供高速下载服务。BMCLAPI 为公益服务,赞助 BMCLAPI 可以帮助作者更好的提供稳定高速的下载服务。[点击此处查阅详细信息] -sponsor.hmcl=Hello Minecraft! Launcher 是一个免费、自由、开放源代码的 Minecraft 启动器。[点击此处查阅更多详细信息] +sponsor.bmclapi=国内下载源由 BMCLAPI 提供高速下载服务。BMCLAPI 为公益服务,赞助 BMCLAPI 可以帮助作者更好地提供稳定高速的下载服务。[点击此处查阅详细信息] +sponsor.hmcl=Hello Minecraft! Launcher 是一个免费、自由、开放源代码的 Minecraft 启动器。[点击此处查阅详细信息] system.architecture=架构 system.operating_system=操作系统 From 474d298fd3d1bcc80fc0deba8f61625eea5edae3 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 26 Oct 2024 13:52:49 +0800 Subject: [PATCH 071/169] Bump Gradle to 8.10.2 (#3390) --- gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew | 7 +++++-- gradlew.bat | 22 ++++++++++++---------- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917707c1f8861d8cb53dd15194d4248596..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 34592 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 delta 34555 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22ce5c..94913af205 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip -networkTimeout=10000 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +networkTimeout=120000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1aa94a4269..f5feea6d6b 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 6689b85bee..9b42019c79 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail From 422f681fe6a4e6b153a0548c4a761ac2947f96d5 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 26 Oct 2024 20:54:48 +0800 Subject: [PATCH 072/169] Bump XZ to 1.10 (#3391) --- HMCLCore/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/build.gradle.kts b/HMCLCore/build.gradle.kts index 53ae7fcb0b..c25db1c3ee 100644 --- a/HMCLCore/build.gradle.kts +++ b/HMCLCore/build.gradle.kts @@ -6,7 +6,7 @@ dependencies { api("org.glavo:simple-png-javafx:0.3.0") api("com.google.code.gson:gson:2.11.0") api("com.moandjiezana.toml:toml4j:0.7.2") - api("org.tukaani:xz:1.9") + api("org.tukaani:xz:1.10") api("org.hildan.fxgson:fx-gson:5.0.0") api("org.jenkins-ci:constant-pool-scanner:1.2") api("com.github.steveice10:opennbt:1.5") From 959adf1075d5c57af9a3895ec0f9a7daf71aad63 Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Sat, 26 Oct 2024 21:02:34 +0800 Subject: [PATCH 073/169] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=B8=BB=E9=A1=B5=20?= =?UTF-8?q?UI=20(#3129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change root page UI * Update HMCL/src/main/resources/assets/lang/I18N.properties Co-authored-by: 3gf8jv4dv <158490944+3gf8jv4dv@users.noreply.github.com> * Shorten I18N * update --------- Co-authored-by: 3gf8jv4dv <158490944+3gf8jv4dv@users.noreply.github.com> Co-authored-by: Glavo --- .../hmcl/ui/versions/GameAdvancedListItem.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java index da7306d5ac..29743853bf 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.ui.versions; import javafx.scene.Node; -import javafx.scene.control.Tooltip; import javafx.scene.image.ImageView; import org.jackhuang.hmcl.event.Event; import org.jackhuang.hmcl.setting.Profile; @@ -34,15 +33,13 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class GameAdvancedListItem extends AdvancedListItem { - private final Tooltip tooltip; private final ImageView imageView; private final WeakListenerHolder holder = new WeakListenerHolder(); private Profile profile; + @SuppressWarnings("unused") private Consumer onVersionIconChangedListener; public GameAdvancedListItem() { - tooltip = new Tooltip(); - Pair view = createImageView(null); setLeftGraphic(view.getKey()); imageView = view.getValue(); @@ -63,17 +60,13 @@ private void loadVersion(String version) { } if (version != null && Profiles.getSelectedProfile() != null && Profiles.getSelectedProfile().getRepository().hasVersion(version)) { - FXUtils.installFastTooltip(this, tooltip); - setTitle(version); - setSubtitle(null); + setTitle(i18n("version.manage.manage")); + setSubtitle(version); imageView.setImage(Profiles.getSelectedProfile().getRepository().getVersionIconImage(version)); - tooltip.setText(version); } else { - Tooltip.uninstall(this,tooltip); setTitle(i18n("version.empty")); setSubtitle(i18n("version.empty.add")); imageView.setImage(VersionIconType.DEFAULT.getIcon()); - tooltip.setText(""); } } } From 602840519b6056b341afb74295c39939b519755a Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 26 Oct 2024 23:32:12 +0800 Subject: [PATCH 074/169] Change forgot password link (#3392) --- .../java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java index 51fb48ceb7..1c3ff28c92 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java @@ -317,7 +317,7 @@ private void initDetailsPane() { JFXHyperlink deauthorizeLink = new JFXHyperlink(i18n("account.methods.microsoft.deauthorize")); deauthorizeLink.setExternalLink("https://account.live.com/consent/Edit?client_id=000000004C794E0A"); JFXHyperlink forgotpasswordLink = new JFXHyperlink(i18n("account.methods.forgot_password")); - forgotpasswordLink.setExternalLink("https://www.minecraft.net/password/forgot"); + forgotpasswordLink.setExternalLink("https://account.live.com/ResetPassword.aspx"); JFXHyperlink createProfileLink = new JFXHyperlink(i18n("account.methods.microsoft.makegameidsettings")); createProfileLink.setExternalLink("https://www.minecraft.net/msaprofile/mygames/editprofile"); box.getChildren().setAll(profileLink, birthLink, purchaseLink, deauthorizeLink, forgotpasswordLink, createProfileLink); From fecd567eabcf6d62f7b524e3ac5f45fd894696c7 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 26 Oct 2024 23:34:41 +0800 Subject: [PATCH 075/169] =?UTF-8?q?=E7=AE=80=E5=8C=96=20ContainerAnimation?= =?UTF-8?q?s=20(#3395)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../account/AddAuthlibInjectorServerPane.java | 6 +- .../ui/animation/ContainerAnimations.java | 344 ++++++++++-------- .../hmcl/ui/construct/Navigator.java | 2 +- .../hmcl/ui/construct/SpinnerPane.java | 6 +- .../ui/decorator/DecoratorController.java | 2 +- .../hmcl/ui/decorator/DecoratorSkin.java | 6 +- .../hmcl/ui/decorator/DecoratorTabPage.java | 2 +- .../decorator/DecoratorWizardDisplayer.java | 2 +- .../hmcl/ui/download/DownloadPage.java | 2 +- .../hmcl/ui/download/VersionsPage.java | 8 +- .../hmcl/ui/main/LauncherSettingsPage.java | 2 +- .../org/jackhuang/hmcl/ui/main/MainPage.java | 4 +- .../hmcl/ui/versions/ModListPageSkin.java | 2 +- .../hmcl/ui/versions/VersionPage.java | 2 +- 14 files changed, 221 insertions(+), 169 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index 914046649d..c19c80131c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -147,7 +147,7 @@ public AddAuthlibInjectorServerPane() { confirmServerPane.setActions(prevButton, cancelButton, finishButton); } - this.setContent(addServerPane, ContainerAnimations.NONE.getAnimationProducer()); + this.setContent(addServerPane, ContainerAnimations.NONE); lblCreationWarning.maxWidthProperty().bind(((FlowPane) lblCreationWarning.getParent()).widthProperty()); btnAddNext.disableProperty().bind(txtServerUrl.textProperty().isEmpty()); @@ -198,7 +198,7 @@ private void onAddNext() { lblServerWarning.setVisible("http".equals(NetworkUtils.toURL(serverBeingAdded.getUrl()).getProtocol())); - this.setContent(confirmServerPane, ContainerAnimations.SWIPE_LEFT.getAnimationProducer()); + this.setContent(confirmServerPane, ContainerAnimations.SWIPE_LEFT); } else { LOG.warning("Failed to resolve auth server: " + url, exception); lblCreationWarning.setText(resolveFetchExceptionMessage(exception)); @@ -208,7 +208,7 @@ private void onAddNext() { } private void onAddPrev() { - this.setContent(addServerPane, ContainerAnimations.SWIPE_RIGHT.getAnimationProducer()); + this.setContent(addServerPane, ContainerAnimations.SWIPE_RIGHT); } private void onAddFinish() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/ContainerAnimations.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/ContainerAnimations.java index 20bca631dd..281ac618db 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/ContainerAnimations.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/ContainerAnimations.java @@ -1,6 +1,6 @@ /* * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors + * Copyright (C) 2020 huangyuhui and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,165 +27,225 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -public enum ContainerAnimations { - NONE(c -> { - c.getPreviousNode().setTranslateX(0); - c.getPreviousNode().setTranslateY(0); - c.getPreviousNode().setScaleX(1); - c.getPreviousNode().setScaleY(1); - c.getPreviousNode().setOpacity(1); - c.getCurrentNode().setTranslateX(0); - c.getCurrentNode().setTranslateY(0); - c.getCurrentNode().setScaleX(1); - c.getCurrentNode().setScaleY(1); - c.getCurrentNode().setOpacity(1); - }, c -> Collections.emptyList()), +public enum ContainerAnimations implements AnimationProducer { + NONE { + @Override + public void init(AnimationHandler c) { + c.getPreviousNode().setTranslateX(0); + c.getPreviousNode().setTranslateY(0); + c.getPreviousNode().setScaleX(1); + c.getPreviousNode().setScaleY(1); + c.getPreviousNode().setOpacity(1); + c.getCurrentNode().setTranslateX(0); + c.getCurrentNode().setTranslateY(0); + c.getCurrentNode().setScaleX(1); + c.getCurrentNode().setScaleY(1); + c.getCurrentNode().setOpacity(1); + } + + @Override + public List animate(AnimationHandler c) { + return Collections.emptyList(); + } + }, /** * A fade between the old and new view */ - FADE(c -> { - c.getPreviousNode().setTranslateX(0); - c.getPreviousNode().setTranslateY(0); - c.getPreviousNode().setScaleX(1); - c.getPreviousNode().setScaleY(1); - c.getPreviousNode().setOpacity(1); - c.getCurrentNode().setTranslateX(0); - c.getCurrentNode().setTranslateY(0); - c.getCurrentNode().setScaleX(1); - c.getCurrentNode().setScaleY(1); - c.getCurrentNode().setOpacity(0); - }, c -> - Arrays.asList(new KeyFrame(Duration.ZERO, + FADE { + @Override + public void init(AnimationHandler c) { + c.getPreviousNode().setTranslateX(0); + c.getPreviousNode().setTranslateY(0); + c.getPreviousNode().setScaleX(1); + c.getPreviousNode().setScaleY(1); + c.getPreviousNode().setOpacity(1); + c.getCurrentNode().setTranslateX(0); + c.getCurrentNode().setTranslateY(0); + c.getCurrentNode().setScaleX(1); + c.getCurrentNode().setScaleY(1); + c.getCurrentNode().setOpacity(0); + } + + @Override + public List animate(AnimationHandler c) { + return Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getPreviousNode().opacityProperty(), 1, Interpolator.EASE_BOTH), new KeyValue(c.getCurrentNode().opacityProperty(), 0, Interpolator.EASE_BOTH)), new KeyFrame(c.getDuration(), new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH), - new KeyValue(c.getCurrentNode().opacityProperty(), 1, Interpolator.EASE_BOTH)))), + new KeyValue(c.getCurrentNode().opacityProperty(), 1, Interpolator.EASE_BOTH))); + } + }, /** * A fade between the old and new view */ - FADE_IN(c -> { - c.getCurrentNode().setTranslateX(0); - c.getCurrentNode().setTranslateY(0); - c.getCurrentNode().setScaleX(1); - c.getCurrentNode().setScaleY(1); - c.getCurrentNode().setOpacity(0); - }, c -> - Arrays.asList(new KeyFrame(Duration.ZERO, + FADE_IN { + @Override + public void init(AnimationHandler c) { + c.getCurrentNode().setTranslateX(0); + c.getCurrentNode().setTranslateY(0); + c.getCurrentNode().setScaleX(1); + c.getCurrentNode().setScaleY(1); + c.getCurrentNode().setOpacity(0); + } + + @Override + public List animate(AnimationHandler c) { + return Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getCurrentNode().opacityProperty(), 0, FXUtils.SINE)), new KeyFrame(c.getDuration(), - new KeyValue(c.getCurrentNode().opacityProperty(), 1, FXUtils.SINE)))), + new KeyValue(c.getCurrentNode().opacityProperty(), 1, FXUtils.SINE))); + } + }, /** * A fade between the old and new view */ - FADE_OUT(c -> { - c.getCurrentNode().setTranslateX(0); - c.getCurrentNode().setTranslateY(0); - c.getCurrentNode().setScaleX(1); - c.getCurrentNode().setScaleY(1); - c.getCurrentNode().setOpacity(1); - }, c -> - Arrays.asList(new KeyFrame(Duration.ZERO, + FADE_OUT { + @Override + public void init(AnimationHandler c) { + c.getCurrentNode().setTranslateX(0); + c.getCurrentNode().setTranslateY(0); + c.getCurrentNode().setScaleX(1); + c.getCurrentNode().setScaleY(1); + c.getCurrentNode().setOpacity(1); + } + + @Override + public List animate(AnimationHandler c) { + return Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getCurrentNode().opacityProperty(), 1, FXUtils.SINE)), new KeyFrame(c.getDuration(), - new KeyValue(c.getCurrentNode().opacityProperty(), 0, FXUtils.SINE)))), + new KeyValue(c.getCurrentNode().opacityProperty(), 0, FXUtils.SINE))); + } + }, /** * A zoom effect */ - ZOOM_IN(c -> { - c.getPreviousNode().setTranslateX(0); - c.getPreviousNode().setTranslateY(0); - c.getPreviousNode().setScaleX(1); - c.getPreviousNode().setScaleY(1); - c.getPreviousNode().setOpacity(1); - c.getCurrentNode().setTranslateX(0); - c.getCurrentNode().setTranslateY(0); - }, c -> - Arrays.asList(new KeyFrame(Duration.ZERO, + ZOOM_IN { + @Override + public void init(AnimationHandler c) { + c.getPreviousNode().setTranslateX(0); + c.getPreviousNode().setTranslateY(0); + c.getPreviousNode().setScaleX(1); + c.getPreviousNode().setScaleY(1); + c.getPreviousNode().setOpacity(1); + c.getCurrentNode().setTranslateX(0); + c.getCurrentNode().setTranslateY(0); + } + + @Override + public List animate(AnimationHandler c) { + return Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getPreviousNode().scaleXProperty(), 1, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().scaleYProperty(), 1, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().opacityProperty(), 1, Interpolator.EASE_BOTH)), new KeyFrame(c.getDuration(), new KeyValue(c.getPreviousNode().scaleXProperty(), 4, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().scaleYProperty(), 4, Interpolator.EASE_BOTH), - new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH)))), + new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH))); + } + }, /** * A zoom effect */ - ZOOM_OUT(c -> { - c.getPreviousNode().setTranslateX(0); - c.getPreviousNode().setTranslateY(0); - c.getPreviousNode().setScaleX(1); - c.getPreviousNode().setScaleY(1); - c.getPreviousNode().setOpacity(1); - c.getCurrentNode().setTranslateX(0); - c.getCurrentNode().setTranslateY(0); - }, c -> - (Arrays.asList(new KeyFrame(Duration.ZERO, + ZOOM_OUT { + @Override + public void init(AnimationHandler c) { + c.getPreviousNode().setTranslateX(0); + c.getPreviousNode().setTranslateY(0); + c.getPreviousNode().setScaleX(1); + c.getPreviousNode().setScaleY(1); + c.getPreviousNode().setOpacity(1); + c.getCurrentNode().setTranslateX(0); + c.getCurrentNode().setTranslateY(0); + } + + @Override + public List animate(AnimationHandler c) { + return Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getPreviousNode().scaleXProperty(), 1, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().scaleYProperty(), 1, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().opacityProperty(), 1, Interpolator.EASE_BOTH)), new KeyFrame(c.getDuration(), new KeyValue(c.getPreviousNode().scaleXProperty(), 0, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().scaleYProperty(), 0, Interpolator.EASE_BOTH), - new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH))))), + new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH))); + } + }, /** * A swipe effect */ - SWIPE_LEFT(c -> { - c.getPreviousNode().setScaleX(1); - c.getPreviousNode().setScaleY(1); - c.getPreviousNode().setOpacity(0); - c.getPreviousNode().setTranslateX(0); - c.getCurrentNode().setScaleX(1); - c.getCurrentNode().setScaleY(1); - c.getCurrentNode().setOpacity(1); - c.getCurrentNode().setTranslateX(c.getCurrentRoot().getWidth()); - }, c -> - Arrays.asList(new KeyFrame(Duration.ZERO, + SWIPE_LEFT { + @Override + public void init(AnimationHandler c) { + c.getPreviousNode().setScaleX(1); + c.getPreviousNode().setScaleY(1); + c.getPreviousNode().setOpacity(0); + c.getPreviousNode().setTranslateX(0); + c.getCurrentNode().setScaleX(1); + c.getCurrentNode().setScaleY(1); + c.getCurrentNode().setOpacity(1); + c.getCurrentNode().setTranslateX(c.getCurrentRoot().getWidth()); + } + + @Override + public List animate(AnimationHandler c) { + return Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getCurrentNode().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().translateXProperty(), 0, Interpolator.EASE_BOTH)), new KeyFrame(c.getDuration(), new KeyValue(c.getCurrentNode().translateXProperty(), 0, Interpolator.EASE_BOTH), - new KeyValue(c.getPreviousNode().translateXProperty(), -c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH)))), + new KeyValue(c.getPreviousNode().translateXProperty(), -c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH))); + } + }, /** * A swipe effect */ - SWIPE_RIGHT(c -> { - c.getPreviousNode().setScaleX(1); - c.getPreviousNode().setScaleY(1); - c.getPreviousNode().setOpacity(0); - c.getPreviousNode().setTranslateX(0); - c.getCurrentNode().setScaleX(1); - c.getCurrentNode().setScaleY(1); - c.getCurrentNode().setOpacity(1); - c.getCurrentNode().setTranslateX(-c.getCurrentRoot().getWidth()); - }, c -> - Arrays.asList(new KeyFrame(Duration.ZERO, + SWIPE_RIGHT { + @Override + public void init(AnimationHandler c) { + c.getPreviousNode().setScaleX(1); + c.getPreviousNode().setScaleY(1); + c.getPreviousNode().setOpacity(0); + c.getPreviousNode().setTranslateX(0); + c.getCurrentNode().setScaleX(1); + c.getCurrentNode().setScaleY(1); + c.getCurrentNode().setOpacity(1); + c.getCurrentNode().setTranslateX(-c.getCurrentRoot().getWidth()); + } + + @Override + public List animate(AnimationHandler c) { + return Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getCurrentNode().translateXProperty(), -c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().translateXProperty(), 0, Interpolator.EASE_BOTH)), new KeyFrame(c.getDuration(), new KeyValue(c.getCurrentNode().translateXProperty(), 0, Interpolator.EASE_BOTH), - new KeyValue(c.getPreviousNode().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH)))), + new KeyValue(c.getPreviousNode().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH))); + } + }, + + SWIPE_LEFT_FADE_SHORT { + @Override + public void init(AnimationHandler c) { + c.getPreviousNode().setScaleX(1); + c.getPreviousNode().setScaleY(1); + c.getPreviousNode().setOpacity(0); + c.getPreviousNode().setTranslateX(0); + c.getCurrentNode().setScaleX(1); + c.getCurrentNode().setScaleY(1); + c.getCurrentNode().setOpacity(1); + c.getCurrentNode().setTranslateX(c.getCurrentRoot().getWidth()); + } - SWIPE_LEFT_FADE_SHORT(c -> { - c.getPreviousNode().setScaleX(1); - c.getPreviousNode().setScaleY(1); - c.getPreviousNode().setOpacity(0); - c.getPreviousNode().setTranslateX(0); - c.getCurrentNode().setScaleX(1); - c.getCurrentNode().setScaleY(1); - c.getCurrentNode().setOpacity(1); - c.getCurrentNode().setTranslateX(c.getCurrentRoot().getWidth()); - }, c -> - Arrays.asList(new KeyFrame(Duration.ZERO, + @Override + public List animate(AnimationHandler c) { + return Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getCurrentNode().translateXProperty(), 50, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().translateXProperty(), 0, Interpolator.EASE_BOTH), new KeyValue(c.getCurrentNode().opacityProperty(), 0, Interpolator.EASE_BOTH), @@ -194,19 +254,26 @@ public enum ContainerAnimations { new KeyValue(c.getCurrentNode().translateXProperty(), 0, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().translateXProperty(), -50, Interpolator.EASE_BOTH), new KeyValue(c.getCurrentNode().opacityProperty(), 1, Interpolator.EASE_BOTH), - new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH)))), + new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH))); + } + }, - SWIPE_RIGHT_FADE_SHORT(c -> { - c.getPreviousNode().setScaleX(1); - c.getPreviousNode().setScaleY(1); - c.getPreviousNode().setOpacity(0); - c.getPreviousNode().setTranslateX(0); - c.getCurrentNode().setScaleX(1); - c.getCurrentNode().setScaleY(1); - c.getCurrentNode().setOpacity(1); - c.getCurrentNode().setTranslateX(c.getCurrentRoot().getWidth()); - }, c -> - Arrays.asList(new KeyFrame(Duration.ZERO, + SWIPE_RIGHT_FADE_SHORT { + @Override + public void init(AnimationHandler c) { + c.getPreviousNode().setScaleX(1); + c.getPreviousNode().setScaleY(1); + c.getPreviousNode().setOpacity(0); + c.getPreviousNode().setTranslateX(0); + c.getCurrentNode().setScaleX(1); + c.getCurrentNode().setScaleY(1); + c.getCurrentNode().setOpacity(1); + c.getCurrentNode().setTranslateX(c.getCurrentRoot().getWidth()); + } + + @Override + public List animate(AnimationHandler c) { + return Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getCurrentNode().translateXProperty(), -50, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().translateXProperty(), 0, Interpolator.EASE_BOTH), new KeyValue(c.getCurrentNode().opacityProperty(), 0, Interpolator.EASE_BOTH), @@ -215,38 +282,12 @@ public enum ContainerAnimations { new KeyValue(c.getCurrentNode().translateXProperty(), 0, Interpolator.EASE_BOTH), new KeyValue(c.getPreviousNode().translateXProperty(), 50, Interpolator.EASE_BOTH), new KeyValue(c.getCurrentNode().opacityProperty(), 1, Interpolator.EASE_BOTH), - new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH)))); + new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH))); + } + }; - private final AnimationProducer animationProducer; private ContainerAnimations opposite; - ContainerAnimations(Consumer init, Function> animationProducer) { - this.animationProducer = new AnimationProducer() { - @Override - public void init(AnimationHandler handler) { - init.accept(handler); - } - - @Override - public List animate(AnimationHandler handler) { - return animationProducer.apply(handler); - } - - @Override - public @Nullable AnimationProducer opposite() { - return opposite != null ? opposite.getAnimationProducer() : null; - } - }; - } - - public AnimationProducer getAnimationProducer() { - return animationProducer; - } - - public ContainerAnimations getOpposite() { - return opposite; - } - static { NONE.opposite = NONE; FADE.opposite = FADE; @@ -257,4 +298,15 @@ public ContainerAnimations getOpposite() { ZOOM_IN.opposite = ZOOM_OUT; ZOOM_OUT.opposite = ZOOM_IN; } + + @Override + public abstract void init(AnimationHandler handler); + + @Override + public abstract List animate(AnimationHandler handler); + + @Override + public @Nullable ContainerAnimations opposite() { + return opposite; + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/Navigator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/Navigator.java index 209c893f7e..4ec4989929 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/Navigator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/Navigator.java @@ -126,7 +126,7 @@ public void close(Node from) { if (obj instanceof AnimationProducer) { setContent(node, (AnimationProducer) obj); } else { - setContent(node, ContainerAnimations.NONE.getAnimationProducer()); + setContent(node, ContainerAnimations.NONE); } NavigationEvent navigated = new NavigationEvent(this, node, Navigation.NavigationDirection.PREVIOUS, NavigationEvent.NAVIGATED); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/SpinnerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/SpinnerPane.java index 8686011c2f..2d6ee81f89 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/SpinnerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/SpinnerPane.java @@ -146,12 +146,12 @@ private static final class Skin extends SkinBase { observer = FXUtils.observeWeak(() -> { if (getSkinnable().getFailedReason() != null) { - root.setContent(failedPane, ContainerAnimations.FADE.getAnimationProducer()); + root.setContent(failedPane, ContainerAnimations.FADE); failedReasonLabel.setText(getSkinnable().getFailedReason()); } else if (getSkinnable().isLoading()) { - root.setContent(topPane, ContainerAnimations.FADE.getAnimationProducer()); + root.setContent(topPane, ContainerAnimations.FADE); } else { - root.setContent(contentPane, ContainerAnimations.FADE.getAnimationProducer()); + root.setContent(contentPane, ContainerAnimations.FADE); } }, getSkinnable().loadingProperty(), getSkinnable().failedReasonProperty()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java index dc34c42deb..7b7b552292 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java @@ -457,7 +457,7 @@ public void startWizard(WizardProvider wizardProvider) { public void startWizard(WizardProvider wizardProvider, String category) { FXUtils.checkFxUserThread(); - navigator.navigate(new DecoratorWizardDisplayer(wizardProvider, category), ContainerAnimations.FADE.getAnimationProducer()); + navigator.navigate(new DecoratorWizardDisplayer(wizardProvider, category), ContainerAnimations.FADE); } // ==== Authlib Injector DnD ==== diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index 21b33277a8..161bb51be0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -174,11 +174,11 @@ public DecoratorSkin(Decorator control) { if (s.isAnimate()) { AnimationProducer animation; if (skinnable.getNavigationDirection() == Navigation.NavigationDirection.NEXT) { - animation = ContainerAnimations.SWIPE_LEFT_FADE_SHORT.getAnimationProducer(); + animation = ContainerAnimations.SWIPE_LEFT_FADE_SHORT; } else if (skinnable.getNavigationDirection() == Navigation.NavigationDirection.PREVIOUS) { - animation = ContainerAnimations.SWIPE_RIGHT_FADE_SHORT.getAnimationProducer(); + animation = ContainerAnimations.SWIPE_RIGHT_FADE_SHORT; } else { - animation = ContainerAnimations.FADE.getAnimationProducer(); + animation = ContainerAnimations.FADE; } skinnable.setNavigationDirection(Navigation.NavigationDirection.START); navBarPane.setContent(node, animation); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorTabPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorTabPage.java index 325edd2691..e7cf6b0339 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorTabPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorTabPage.java @@ -36,7 +36,7 @@ public DecoratorTabPage() { if (newValue.getNode() != null) { onNavigating(getCurrentPage()); if (getCurrentPage() != null) getCurrentPage().fireEvent(new Navigator.NavigationEvent(null, getCurrentPage(), Navigation.NavigationDirection.NEXT, Navigator.NavigationEvent.NAVIGATING)); - navigate(newValue.getNode(), ContainerAnimations.FADE.getAnimationProducer()); + navigate(newValue.getNode(), ContainerAnimations.FADE); onNavigated(getCurrentPage()); if (getCurrentPage() != null) getCurrentPage().fireEvent(new Navigator.NavigationEvent(null, getCurrentPage(), Navigation.NavigationDirection.NEXT, Navigator.NavigationEvent.NAVIGATED)); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java index ed6164e7fa..e6a6b5b997 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorWizardDisplayer.java @@ -74,7 +74,7 @@ public void onEnd() { @Override public void navigateTo(Node page, Navigation.NavigationDirection nav) { displayer.navigateTo(page, nav); - navigate(page, nav.getAnimation().getAnimationProducer()); + navigate(page, nav.getAnimation()); String prefix = category == null ? "" : category + " - "; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java index 7b8e894860..74e447abe8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadPage.java @@ -97,7 +97,7 @@ public DownloadPage() { tab.select(newGameTab); FXUtils.onChangeAndOperate(tab.getSelectionModel().selectedItemProperty(), newValue -> { - transitionPane.setContent(newValue.getNode(), ContainerAnimations.FADE.getAnimationProducer()); + transitionPane.setContent(newValue.getNode(), ContainerAnimations.FADE); }); { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index f419810301..3d4a3c3efe 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -210,7 +210,7 @@ private List loadVersions() { @Override public void refresh() { VersionList currentVersionList = versionList; - root.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); + root.setContent(spinner, ContainerAnimations.FADE); executor = currentVersionList.refreshAsync(gameVersion).whenComplete((result, exception) -> { if (exception == null) { List items = loadVersions(); @@ -218,7 +218,7 @@ public void refresh() { Platform.runLater(() -> { if (versionList != currentVersionList) return; if (currentVersionList.getVersions(gameVersion).isEmpty()) { - root.setContent(emptyPane, ContainerAnimations.FADE.getAnimationProducer()); + root.setContent(emptyPane, ContainerAnimations.FADE); } else { if (items.isEmpty()) { chkRelease.setSelected(true); @@ -227,14 +227,14 @@ public void refresh() { } else { list.getItems().setAll(items); } - root.setContent(center, ContainerAnimations.FADE.getAnimationProducer()); + root.setContent(center, ContainerAnimations.FADE); } }); } else { LOG.warning("Failed to fetch versions list", exception); Platform.runLater(() -> { if (versionList != currentVersionList) return; - root.setContent(failedPane, ContainerAnimations.FADE.getAnimationProducer()); + root.setContent(failedPane, ContainerAnimations.FADE); }); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java index 4806f58d55..8e59718feb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/LauncherSettingsPage.java @@ -66,7 +66,7 @@ public LauncherSettingsPage() { gameTab.initializeIfNeeded(); gameTab.getNode().loadVersion(Profiles.getSelectedProfile(), null); FXUtils.onChangeAndOperate(tab.getSelectionModel().selectedItemProperty(), newValue -> { - transitionPane.setContent(newValue.getNode(), ContainerAnimations.FADE.getAnimationProducer()); + transitionPane.setContent(newValue.getNode(), ContainerAnimations.FADE); }); { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java index 1c0f991627..08999fb7a1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java @@ -116,7 +116,7 @@ public final class MainPage extends StackPane implements DecoratorPage { announcementBox.getChildren().add(announcementCard); announcementPane = new TransitionPane(); - announcementPane.setContent(announcementBox, ContainerAnimations.NONE.getAnimationProducer()); + announcementPane.setContent(announcementBox, ContainerAnimations.NONE); getChildren().add(announcementPane); } @@ -301,7 +301,7 @@ private void closeUpdateBubble() { public void hideAnnouncementPane() { if (announcementPane != null) { config().getShownTips().put(ANNOUNCEMENT, Metadata.VERSION); - announcementPane.setContent(new StackPane(), ContainerAnimations.FADE.getAnimationProducer()); + announcementPane.setContent(new StackPane(), ContainerAnimations.FADE); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index 7da53efe96..cb3883342d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -204,7 +204,7 @@ class ModListPageSkin extends SkinBase { private void changeToolbar(HBox newToolbar) { Node oldToolbar = toolbarPane.getCurrentNode(); if (newToolbar != oldToolbar) { - toolbarPane.setContent(newToolbar, ContainerAnimations.FADE.getAnimationProducer()); + toolbarPane.setContent(newToolbar, ContainerAnimations.FADE); if (newToolbar == searchBar) { searchField.requestFocus(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java index 0866e1e6e4..6d36a9051e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java @@ -78,7 +78,7 @@ public class VersionPage extends DecoratorAnimatedPage implements DecoratorPage tab.select(versionSettingsTab); FXUtils.onChangeAndOperate(tab.getSelectionModel().selectedItemProperty(), newValue -> { - transitionPane.setContent(newValue.getNode(), ContainerAnimations.FADE.getAnimationProducer()); + transitionPane.setContent(newValue.getNode(), ContainerAnimations.FADE); }); listenerHolder.add(EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).registerWeak(event -> checkSelectedVersion(), EventPriority.HIGHEST)); From 228942c60ae2f7cd664eb59d6c2620bc7345b089 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 26 Oct 2024 23:49:43 +0800 Subject: [PATCH 076/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E6=8C=89=E9=92=AE=E5=9B=BE=E6=A0=87=20(#3396?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/ui/account/AccountListItemSkin.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index 52fceb890c..ea6b28dbfa 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -42,10 +42,9 @@ import org.jackhuang.hmcl.ui.construct.SpinnerPane; import org.jackhuang.hmcl.util.javafx.BindingMapping; -import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -public class AccountListItemSkin extends SkinBase { +public final class AccountListItemSkin extends SkinBase { public AccountListItemSkin(AccountListItem skinnable) { super(skinnable); @@ -118,10 +117,10 @@ public void fire() { btnMove.getStyleClass().add("toggle-icon4"); if (skinnable.getAccount().isPortable()) { btnMove.setGraphic(SVG.EARTH.createIcon(Theme.blackFill(), -1, -1)); - runInFX(() -> FXUtils.installFastTooltip(btnMove, i18n("account.move_to_global"))); + FXUtils.installFastTooltip(btnMove, i18n("account.move_to_global")); } else { btnMove.setGraphic(SVG.EXPORT.createIcon(Theme.blackFill(), -1, -1)); - runInFX(() -> FXUtils.installFastTooltip(btnMove, i18n("account.move_to_portable"))); + FXUtils.installFastTooltip(btnMove, i18n("account.move_to_portable")); } spinnerMove.setContent(btnMove); right.getChildren().add(spinnerMove); @@ -143,7 +142,7 @@ public void fire() { }); btnRefresh.getStyleClass().add("toggle-icon4"); btnRefresh.setGraphic(SVG.REFRESH.createIcon(Theme.blackFill(), -1, -1)); - runInFX(() -> FXUtils.installFastTooltip(btnRefresh, i18n("button.refresh"))); + FXUtils.installFastTooltip(btnRefresh, i18n("button.refresh")); spinnerRefresh.setContent(btnRefresh); right.getChildren().add(spinnerRefresh); @@ -160,7 +159,7 @@ public void fire() { }); btnUpload.getStyleClass().add("toggle-icon4"); btnUpload.setGraphic(SVG.HANGER.createIcon(Theme.blackFill(), -1, -1)); - runInFX(() -> FXUtils.installFastTooltip(btnUpload, i18n("account.skin.upload"))); + FXUtils.installFastTooltip(btnUpload, i18n("account.skin.upload")); spinnerUpload.managedProperty().bind(spinnerUpload.visibleProperty()); spinnerUpload.visibleProperty().bind(skinnable.canUploadSkin()); spinnerUpload.setContent(btnUpload); @@ -170,9 +169,10 @@ public void fire() { JFXButton btnCopyUUID = new JFXButton(); SpinnerPane spinnerCopyUUID = new SpinnerPane(); spinnerCopyUUID.getStyleClass().add("small-spinner-pane"); + btnUpload.getStyleClass().add("toggle-icon4"); btnCopyUUID.setOnAction(e -> FXUtils.copyText(skinnable.getAccount().getUUID().toString())); btnCopyUUID.setGraphic(SVG.COPY.createIcon(Theme.blackFill(), -1, -1)); - runInFX(() -> FXUtils.installFastTooltip(btnCopyUUID, i18n("account.copy_uuid"))); + FXUtils.installFastTooltip(btnCopyUUID, i18n("account.copy_uuid")); spinnerCopyUUID.setContent(btnCopyUUID); right.getChildren().add(spinnerCopyUUID); @@ -180,8 +180,8 @@ public void fire() { btnRemove.setOnAction(e -> Controllers.confirm(i18n("button.remove.confirm"), i18n("button.remove"), skinnable::remove, null)); btnRemove.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnRemove, Pos.CENTER); - btnRemove.setGraphic(SVG.DELETE.createIcon(Theme.blackFill(), -1, -1)); - runInFX(() -> FXUtils.installFastTooltip(btnRemove, i18n("button.delete"))); + btnRemove.setGraphic(SVG.DELETE_OUTLINE.createIcon(Theme.blackFill(), -1, -1)); + FXUtils.installFastTooltip(btnRemove, i18n("button.delete")); right.getChildren().add(btnRemove); root.setRight(right); From c99f85d9d52553ca97cefedd6d166c7f222ec2f2 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 27 Oct 2024 00:21:31 +0800 Subject: [PATCH 077/169] =?UTF-8?q?=E7=BC=A9=E5=B0=8F=E5=A4=8D=E5=88=B6?= =?UTF-8?q?=E5=9B=BE=E6=A0=87=20(#3397)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update --- HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java index 9231c4b37f..05f7c9d124 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java @@ -32,7 +32,7 @@ public enum SVG { CANCEL("M12 2C17.5 2 22 6.5 22 12S17.5 22 12 22 2 17.5 2 12 6.5 2 12 2M12 4C10.1 4 8.4 4.6 7.1 5.7L18.3 16.9C19.3 15.5 20 13.8 20 12C20 7.6 16.4 4 12 4M16.9 18.3L5.7 7.1C4.6 8.4 4 10.1 4 12C4 16.4 7.6 20 12 20C13.9 20 15.6 19.4 16.9 18.3Z"), CHAT("M20,2A2,2 0 0,1 22,4V16A2,2 0 0,1 20,18H6L2,22V4C2,2.89 2.9,2 4,2H20M4,4V17.17L5.17,16H20V4H4M6,7H18V9H6V7M6,11H15V13H6V11Z"), CLOSE("M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"), - COPY("M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"), + COPY("M15 16.4H7V6H15M15.4 4H6.6A1.6 1.6 90 005 5.6V16.8A1.6 1.6 90 006.6 18.4H15.4A1.6 1.6 90 0017 16.8V5.6A1.6 1.6 90 0015.4 4M13 .8H3.4A1.6 1.6 90 001.8 2.4V13.6H3.8V2.8H13V.8Z"), DOTS_VERTICAL("M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z"), DOTS_HORIZONTAL("M16,12A2,2 0 0,1 18,10A2,2 0 0,1 20,12A2,2 0 0,1 18,14A2,2 0 0,1 16,12M10,12A2,2 0 0,1 12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12M4,12A2,2 0 0,1 6,10A2,2 0 0,1 8,12A2,2 0 0,1 6,14A2,2 0 0,1 4,12Z"), DELETE("M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"), From 1877a18ebbf62b3c8537110175d6d2442643faf3 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sun, 27 Oct 2024 22:07:03 +0800 Subject: [PATCH 078/169] Fix en language missing a line break (#3403) --- HMCL/src/main/resources/assets/lang/I18N.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 843b8c5295..e8ac9aa9ee 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -438,7 +438,7 @@ game.crash.reason.duplicated_mod=The game cannot continue to run due to duplicat %2$s\n\ \n\ Each mod can only be installed once, please delete the duplicate mod and try again. -game.crash.reason.entity=The game crashed due to an entity in world. +game.crash.reason.entity=The game crashed due to an entity in world.\n\ \n\ You can try removing this entity using MCEdit or delete that mod that added it.\n\ \n\ From f89ac2231a7ea2383f5ac24d070e32473e24d73a Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sun, 27 Oct 2024 22:07:25 +0800 Subject: [PATCH 079/169] Adjust Java management i18n (#3402) - Add missing languages. --- .../resources/assets/lang/I18N_es.properties | 30 +++++++++++++++++++ .../resources/assets/lang/I18N_ja.properties | 30 +++++++++++++++++++ .../resources/assets/lang/I18N_ru.properties | 30 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 78cf70dcee..2b69a9ef2c 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -597,6 +597,36 @@ install.new_game.malformed=Nombre no válido install.select=Seleccione una operación install.success=Instalado con éxito. +java.add=Añadir Java +java.add.failed=Este Java no es válido o es incompatible con la plataforma actual. +java.disable=Deshabilitar este Java +java.disable.confirm=¿Está seguro de que desea desactivar este Java? +java.disabled.management=Java desactivado +java.disabled.management.remove=Eliminar este Java de la lista +java.disabled.management.restore=Activar este Java +java.download=Descargar Java +java.download.load_list.failed=Error al cargar la lista de versiones +java.download.more=Más distribuciones de Java +java.download.prompt=Elija la versión de Java que desea descargar: +java.download.distribution=Distribución +java.download.version=Versión +java.download.packageType=Tipo de paquete +java.management=Gestión Java +java.info.architecture=Arquitectura +java.info.vendor=Proveedor +java.info.version=Versión +java.info.disco.distribution=Distribución +java.install=Instalar Java +java.install.archive=Fuente Path +java.install.failed.exists=Este nombre ya tiene dueño +java.install.failed.invalid=Este archivo no es un paquete de instalación de Java válido, por lo que no se puede instalar. +java.install.failed.unsupported_platform=Este Java no es compatible con la plataforma actual, por lo que no puede instalarse. +java.install.name=Nombre +java.install.warning.invalid_character=Carácter ilegal en el nombre +java.reveal=Revelar el directorio de Java +java.uninstall=Desinstalar Java +java.uninstall.confirm=¿Está seguro de que desea desinstalar este Java? ¡Esta acción no se puede deshacer! + lang=Español lang.default=Usar idioma del sistema diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index c191bcd241..55af068aea 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -455,6 +455,36 @@ install.new_game.malformed=無効な名前 install.select=操作を選択します install.success=正常にインストールされました +java.add=Javaの追加 +java.add.failed=このJavaは無効であるか、現在のプラットフォームと互換性がない。 +java.disable=無効化 +java.disable.confirm=本当にこのJavaを無効にしますか? +java.disabled.management=無効なJava +java.disabled.management.remove=このJavaをリストから削除する +java.disabled.management.restore=有効化 +java.download=Javaをダウンロード +java.download.load_list.failed=バージョンリストの読み込みに失敗しました +java.download.more=その他のJavaディストリビューション +java.download.prompt=ダウンロードしたいJavaのバージョンを選択してください: +java.download.distribution=配布の種類 +java.download.version=バージョン +java.download.packageType=パッケージの種類 +java.management=Javaの管理 +java.info.architecture=アーキテクチャ +java.info.vendor=発行元 +java.info.version=バージョン +java.info.disco.distribution=配布の種類 +java.install=Javaのインストール +java.install.archive=場所 +java.install.failed.exists=この名前はすでに使用されている +java.install.failed.invalid=このアーカイブは有効なJavaインストール・パッケージではないため、インストールできません。 +java.install.failed.unsupported_platform=このJavaは現在のプラットフォームと互換性がないため、インストールできません。 +java.install.name=名前 +java.install.warning.invalid_character=名前に不正な文字が含まれています +java.reveal=Javaディレクトリを表示する +java.uninstall=このJavaをアンインストールする +java.uninstall.confirm=本当にこのJavaをアンインストールしますか?この操作は元に戻せません! + lang=日本語 lang.default=システム言語を使用する diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index e6475ca918..c552e8deb1 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -475,6 +475,36 @@ install.new_game.malformed=Недопустимое имя install.select=Выберите операцию install.success=Успешно установлено. +java.add=Добавить Java +java.add.failed=Этот Java недопустим или несовместим с текущей платформой. +java.disable=Отключить Java +java.disable.confirm=Вы уверены, что хотите отключить эту Java? +java.disabled.management=Отключенная Java +java.disabled.management.remove=Удалить эту Java из списка +java.disabled.management.restore=Включить эту Java +java.download=Скачать Java +java.download.load_list.failed=Не удалось загрузить список версий +java.download.more=Больше дистрибутивов Java +java.download.prompt=Выберите версию Java, которую вы хотите загрузить: +java.download.distribution=Дистрибуция +java.download.version=Версия +java.download.packageType=Тип упаковки +java.management=Управление Java +java.info.architecture=Архитектура +java.info.vendor=Поставщик +java.info.version=Версия +java.info.disco.distribution=Дистрибуция +java.install=Установите Java +java.install.archive=Расположение +java.install.failed.exists=Это имя уже используется +java.install.failed.invalid=Этот архив не является допустимым установочным пакетом Java, поэтому его установка невозможна. +java.install.failed.unsupported_platform=Эта Java несовместима с текущей платформой, поэтому ее невозможно установить. +java.install.name=Название +java.install.warning.invalid_character=Неправильный символ в названии +java.reveal=Откройте каталог Java +java.uninstall=Удалить Java +java.uninstall.confirm=Вы уверены, что хотите удалить эту Java? Это действие нельзя отменить! + lang=Русский lang.default=Использовать язык системы From 743e93443671d6c77eedbf956b59a66a2a0c3ff6 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 28 Oct 2024 00:29:29 +0800 Subject: [PATCH 080/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=E2=80=9C=E5=A4=8D?= =?UTF-8?q?=E5=88=B6=E2=80=9D=E5=9B=BE=E6=A0=87=20(#3406)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java index 05f7c9d124..618eb270ad 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java @@ -32,7 +32,7 @@ public enum SVG { CANCEL("M12 2C17.5 2 22 6.5 22 12S17.5 22 12 22 2 17.5 2 12 6.5 2 12 2M12 4C10.1 4 8.4 4.6 7.1 5.7L18.3 16.9C19.3 15.5 20 13.8 20 12C20 7.6 16.4 4 12 4M16.9 18.3L5.7 7.1C4.6 8.4 4 10.1 4 12C4 16.4 7.6 20 12 20C13.9 20 15.6 19.4 16.9 18.3Z"), CHAT("M20,2A2,2 0 0,1 22,4V16A2,2 0 0,1 20,18H6L2,22V4C2,2.89 2.9,2 4,2H20M4,4V17.17L5.17,16H20V4H4M6,7H18V9H6V7M6,11H15V13H6V11Z"), CLOSE("M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"), - COPY("M15 16.4H7V6H15M15.4 4H6.6A1.6 1.6 90 005 5.6V16.8A1.6 1.6 90 006.6 18.4H15.4A1.6 1.6 90 0017 16.8V5.6A1.6 1.6 90 0015.4 4M13 .8H3.4A1.6 1.6 90 001.8 2.4V13.6H3.8V2.8H13V.8Z"), + COPY("M15 16H7V6h8m.4-2H6.6A1.6 1.6 90 005 5.6V16.4a1.6 1.6 90 001.6 1.6h8.8A1.6 1.6 90 0017 16.4V5.6A1.6 1.6 90 0015.4 4M13 1H3.6A1.6 1.6 90 002 2.6V13h2V3H13V1Z"), DOTS_VERTICAL("M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z"), DOTS_HORIZONTAL("M16,12A2,2 0 0,1 18,10A2,2 0 0,1 20,12A2,2 0 0,1 18,14A2,2 0 0,1 16,12M10,12A2,2 0 0,1 12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12M4,12A2,2 0 0,1 6,10A2,2 0 0,1 8,12A2,2 0 0,1 6,14A2,2 0 0,1 4,12Z"), DELETE("M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"), From d6a267afa4c71d34ec7d6c176650f0243b988e0f Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 28 Oct 2024 01:52:38 +0800 Subject: [PATCH 081/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20FXUtils.installToo?= =?UTF-8?q?ltip=20(#3407)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * Fix checkstyle * update * update * update * update * update --- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 36 +---- .../jackhuang/hmcl/ui/GameCrashWindow.java | 7 +- .../jackhuang/hmcl/ui/TooltipInstaller.java | 123 ++++++++++++++++++ .../hmcl/ui/account/CreateAccountPane.java | 2 +- .../org/jackhuang/hmcl/ui/main/MainPage.java | 3 +- .../org/jackhuang/hmcl/ui/main/RootPage.java | 2 +- .../hmcl/ui/versions/DownloadListPage.java | 3 +- .../hmcl/ui/versions/DownloadPage.java | 5 +- .../hmcl/ui/versions/GameListItemSkin.java | 7 +- 9 files changed, 141 insertions(+), 47 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/TooltipInstaller.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index d709b9223e..2e29857250 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -72,8 +72,6 @@ import javax.xml.parsers.ParserConfigurationException; import java.io.*; import java.lang.ref.WeakReference; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Files; @@ -298,8 +296,12 @@ public static void smoothScrolling(ScrollPane scrollPane) { ScrollUtils.addSmoothScrolling(scrollPane); } + private static final Duration TOOLTIP_FAST_SHOW_DELAY = Duration.millis(50); + private static final Duration TOOLTIP_SLOW_SHOW_DELAY = Duration.millis(500); + private static final Duration TOOLTIP_SHOW_DURATION = Duration.millis(5000); + public static void installFastTooltip(Node node, Tooltip tooltip) { - installTooltip(node, 50, 5000, 0, tooltip); + runInFX(() -> TooltipInstaller.INSTALLER.installTooltip(node, TOOLTIP_FAST_SHOW_DELAY, TOOLTIP_SHOW_DURATION, Duration.ZERO, tooltip)); } public static void installFastTooltip(Node node, String tooltip) { @@ -307,39 +309,13 @@ public static void installFastTooltip(Node node, String tooltip) { } public static void installSlowTooltip(Node node, Tooltip tooltip) { - installTooltip(node, 500, 5000, 0, tooltip); + runInFX(() -> TooltipInstaller.INSTALLER.installTooltip(node, TOOLTIP_SLOW_SHOW_DELAY, TOOLTIP_SHOW_DURATION, Duration.ZERO, tooltip)); } public static void installSlowTooltip(Node node, String tooltip) { installSlowTooltip(node, new Tooltip(tooltip)); } - public static void installTooltip(Node node, double openDelay, double visibleDelay, double closeDelay, Tooltip tooltip) { - runInFX(() -> { - try { - // Java 8 - Class behaviorClass = Class.forName("javafx.scene.control.Tooltip$TooltipBehavior"); - Constructor behaviorConstructor = behaviorClass.getDeclaredConstructor(Duration.class, Duration.class, Duration.class, boolean.class); - behaviorConstructor.setAccessible(true); - Object behavior = behaviorConstructor.newInstance(new Duration(openDelay), new Duration(visibleDelay), new Duration(closeDelay), false); - Method installMethod = behaviorClass.getDeclaredMethod("install", Node.class, Tooltip.class); - installMethod.setAccessible(true); - installMethod.invoke(behavior, node, tooltip); - } catch (ReflectiveOperationException e) { - try { - // Java 9 - Tooltip.class.getMethod("setShowDelay", Duration.class).invoke(tooltip, new Duration(openDelay)); - Tooltip.class.getMethod("setShowDuration", Duration.class).invoke(tooltip, new Duration(visibleDelay)); - Tooltip.class.getMethod("setHideDelay", Duration.class).invoke(tooltip, new Duration(closeDelay)); - } catch (ReflectiveOperationException e2) { - e.addSuppressed(e2); - LOG.error("Cannot install tooltip", e); - } - Tooltip.install(node, tooltip); - } - }); - } - public static void playAnimation(Node node, String animationKey, Timeline timeline) { animationKey = "FXUTILS.ANIMATION." + animationKey; Object oldTimeline = node.getProperties().get(animationKey); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java index 6515422389..d3d74d24b0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java @@ -65,7 +65,6 @@ import java.util.stream.Collectors; import static org.jackhuang.hmcl.setting.ConfigHolder.config; -import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.Pair.pair; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -387,13 +386,13 @@ private final class View extends VBox { gameDir.getStyleClass().setAll("two-line-item-second-large"); gameDir.setTitle(i18n("game.directory")); gameDir.setSubtitle(launchOptions.getGameDir().getAbsolutePath()); - runInFX(() -> FXUtils.installFastTooltip(gameDir, i18n("game.directory"))); + FXUtils.installFastTooltip(gameDir, i18n("game.directory")); TwoLineListItem javaDir = new TwoLineListItem(); javaDir.getStyleClass().setAll("two-line-item-second-large"); javaDir.setTitle(i18n("settings.game.java_directory")); javaDir.setSubtitle(launchOptions.getJava().getBinary().toAbsolutePath().toString()); - runInFX(() -> FXUtils.installFastTooltip(javaDir, i18n("settings.game.java_directory"))); + FXUtils.installFastTooltip(javaDir, i18n("settings.game.java_directory")); Label reasonTitle = new Label(i18n("game.crash.reason")); reasonTitle.getStyleClass().add("two-line-item-second-large-title"); @@ -424,7 +423,7 @@ private final class View extends VBox { JFXButton helpButton = FXUtils.newRaisedButton(i18n("help")); helpButton.setOnAction(e -> FXUtils.openLink("https://docs.hmcl.net/help.html")); - runInFX(() -> FXUtils.installFastTooltip(helpButton, i18n("logwindow.help"))); + FXUtils.installFastTooltip(helpButton, i18n("logwindow.help")); toolBar.setPadding(new Insets(8)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/TooltipInstaller.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/TooltipInstaller.java new file mode 100644 index 0000000000..acc1530d12 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/TooltipInstaller.java @@ -0,0 +1,123 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2024 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.jackhuang.hmcl.ui; + +import javafx.scene.Node; +import javafx.scene.control.Tooltip; +import javafx.util.Duration; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import static org.jackhuang.hmcl.util.logging.Logger.LOG; + +/** + * @author Glavo + */ +public class TooltipInstaller { + public static final TooltipInstaller INSTALLER; + + static { + TooltipInstaller installer = null; + + try { + installer = new NewInstaller(); + } catch (Throwable e) { + try { + installer = new OldInstaller(); + } catch (Throwable e2) { + e2.addSuppressed(e); + LOG.warning("Failed to initialize TooltipInstaller", e2); + } + } + + INSTALLER = installer != null ? installer : new TooltipInstaller(); + } + + TooltipInstaller() { + } + + public void installTooltip(Node node, Duration showDelay, Duration showDuration, Duration hideDelay, Tooltip tooltip) { + Tooltip.install(node, tooltip); + } + + // For Java 8 + private static final class OldInstaller extends TooltipInstaller { + private static final Constructor createTooltipBehavior; + private static final Method installTooltipBehavior; + + static { + try { + Class behaviorClass = Class.forName("javafx.scene.control.Tooltip$TooltipBehavior"); + createTooltipBehavior = behaviorClass.getDeclaredConstructor(Duration.class, Duration.class, Duration.class, boolean.class); + createTooltipBehavior.setAccessible(true); + installTooltipBehavior = behaviorClass.getDeclaredMethod("install", Node.class, Tooltip.class); + installTooltipBehavior.setAccessible(true); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + @Override + public void installTooltip(Node node, Duration showDelay, Duration showDuration, Duration hideDelay, Tooltip tooltip) { + try { + Object behavior = createTooltipBehavior.newInstance(showDelay, showDuration, hideDelay, false); + installTooltipBehavior.invoke(behavior, node, tooltip); + } catch (ReflectiveOperationException e) { + LOG.warning("Failed to set tooltip show delay", e); + Tooltip.install(node, tooltip); + } + } + } + + // For Java 9+ + private static final class NewInstaller extends TooltipInstaller { + private static final MethodHandle setTooltipShowDelay; + private static final MethodHandle setTooltipShowDuration; + private static final MethodHandle setTooltipHideDelay; + + static { + try { + MethodHandles.Lookup lookup = MethodHandles.publicLookup(); + MethodType methodType = MethodType.methodType(void.class, Duration.class); + + setTooltipShowDelay = lookup.findVirtual(Tooltip.class, "setShowDelay", methodType); + setTooltipShowDuration = lookup.findVirtual(Tooltip.class, "setShowDuration", methodType); + setTooltipHideDelay = lookup.findVirtual(Tooltip.class, "setHideDelay", methodType); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + @Override + public void installTooltip(Node node, Duration showDelay, Duration showDuration, Duration hideDelay, Tooltip tooltip) { + try { + setTooltipShowDelay.invokeExact(tooltip, showDelay); + setTooltipShowDuration.invokeExact(tooltip, showDuration); + setTooltipHideDelay.invokeExact(tooltip, hideDelay); + } catch (Throwable e) { + LOG.warning("Failed to set tooltip show delay", e); + } + + Tooltip.install(node, tooltip); + } + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java index 1c3ff28c92..a5d8bee8b9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java @@ -510,7 +510,7 @@ public AccountDetailsInputPane(AccountFactory factory, Runnable onAction) { if (factory instanceof OfflineAccountFactory) { txtUsername.setPromptText(i18n("account.methods.offline.name.special_characters")); - runInFX(() -> FXUtils.installFastTooltip(txtUsername, i18n("account.methods.offline.name.special_characters"))); + FXUtils.installFastTooltip(txtUsername, i18n("account.methods.offline.name.special_characters")); JFXHyperlink purchaseLink = new JFXHyperlink(i18n("account.methods.microsoft.purchase")); purchaseLink.setExternalLink(YggdrasilService.PURCHASE_URL); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java index 08999fb7a1..7cded1d271 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java @@ -66,7 +66,6 @@ import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.ui.FXUtils.SINE; -import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class MainPage extends StackPane implements DecoratorPage { @@ -224,7 +223,7 @@ public final class MainPage extends StackPane implements DecoratorPage { StackPane.setAlignment(svg, Pos.CENTER_RIGHT); graphic.getChildren().setAll(svg); graphic.setTranslateX(12); - runInFX(() -> FXUtils.installFastTooltip(menuButton, i18n("version.switch"))); + FXUtils.installFastTooltip(menuButton, i18n("version.switch")); menuButton.setGraphic(graphic); launchPane.getChildren().setAll(launchButton, separator, menuButton); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java index abf24d6ce0..21301dee70 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java @@ -165,7 +165,7 @@ protected Skin(RootPage control) { downloadItem.setActionButtonVisible(false); downloadItem.setTitle(i18n("download")); downloadItem.setOnAction(e -> Controllers.navigate(Controllers.getDownloadPage())); - runInFX(() -> FXUtils.installFastTooltip(downloadItem, i18n("download.hint"))); + FXUtils.installFastTooltip(downloadItem, i18n("download.hint")); // fifth item in left sidebar AdvancedListItem launcherSettingsItem = new AdvancedListItem(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java index ead2698201..dffe893a3f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java @@ -64,7 +64,6 @@ import java.util.Optional; import java.util.stream.Collectors; -import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.ui.FXUtils.stringConverter; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor; @@ -302,7 +301,7 @@ protected ModDownloadListPageSkin(DownloadListPage control) { lblGameVersion.visibleProperty().bind(hasVersion); gameVersionField.managedProperty().bind(hasVersion); gameVersionField.visibleProperty().bind(hasVersion); - runInFX(() -> FXUtils.installFastTooltip(gameVersionField, i18n("search.enter"))); + FXUtils.installFastTooltip(gameVersionField, i18n("search.enter")); FXUtils.onChangeAndOperate(getSkinnable().version, version -> { if (StringUtils.isNotBlank(version.getVersion())) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java index f11880540f..86e1a737b7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java @@ -62,7 +62,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class DownloadPage extends Control implements DecoratorPage { @@ -241,14 +240,14 @@ protected ModDownloadPageSkin(DownloadPage control) { openMcmodButton.setExternalLink(getSkinnable().translations.getMcmodUrl(getSkinnable().mod)); descriptionPane.getChildren().add(openMcmodButton); openMcmodButton.setMinWidth(Region.USE_PREF_SIZE); - runInFX(() -> FXUtils.installFastTooltip(openMcmodButton, i18n("mods.mcmod"))); + FXUtils.installFastTooltip(openMcmodButton, i18n("mods.mcmod")); } JFXHyperlink openUrlButton = new JFXHyperlink(control.page.getLocalizedOfficialPage()); openUrlButton.setExternalLink(getSkinnable().addon.getPageUrl()); descriptionPane.getChildren().add(openUrlButton); openUrlButton.setMinWidth(Region.USE_PREF_SIZE); - runInFX(() -> FXUtils.installFastTooltip(openUrlButton, control.page.getLocalizedOfficialPage())); + FXUtils.installFastTooltip(openUrlButton, control.page.getLocalizedOfficialPage()); } SpinnerPane spinnerPane = new SpinnerPane(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java index d2aebb8907..15b8264722 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java @@ -35,7 +35,6 @@ import org.jackhuang.hmcl.ui.construct.RipplerContainer; import org.jackhuang.hmcl.util.Lazy; -import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class GameListItemSkin extends SkinBase { @@ -82,7 +81,7 @@ public GameListItemSkin(GameListItem skinnable) { btnUpgrade.setOnAction(e -> skinnable.update()); btnUpgrade.getStyleClass().add("toggle-icon4"); btnUpgrade.setGraphic(FXUtils.limitingSize(SVG.UPDATE.createIcon(Theme.blackFill(), 24, 24), 24, 24)); - runInFX(() -> FXUtils.installFastTooltip(btnUpgrade, i18n("version.update"))); + FXUtils.installFastTooltip(btnUpgrade, i18n("version.update")); right.getChildren().add(btnUpgrade); } @@ -92,7 +91,7 @@ public GameListItemSkin(GameListItem skinnable) { btnLaunch.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnLaunch, Pos.CENTER); btnLaunch.setGraphic(FXUtils.limitingSize(SVG.ROCKET_LAUNCH_OUTLINE.createIcon(Theme.blackFill(), 24, 24), 24, 24)); - runInFX(() -> FXUtils.installFastTooltip(btnLaunch, i18n("version.launch.test"))); + FXUtils.installFastTooltip(btnLaunch, i18n("version.launch.test")); right.getChildren().add(btnLaunch); } @@ -105,7 +104,7 @@ public GameListItemSkin(GameListItem skinnable) { btnManage.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnManage, Pos.CENTER); btnManage.setGraphic(FXUtils.limitingSize(SVG.DOTS_VERTICAL.createIcon(Theme.blackFill(), 24, 24), 24, 24)); - runInFX(() -> FXUtils.installFastTooltip(btnManage, i18n("settings.game.management"))); + FXUtils.installFastTooltip(btnManage, i18n("settings.game.management")); right.getChildren().add(btnManage); } From 467ff26278222800eb64083f6b775826fac7a8ac Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Wed, 30 Oct 2024 02:19:16 +0800 Subject: [PATCH 082/169] =?UTF-8?q?=E6=A8=A1=E7=BB=84=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8F=B3=E9=94=AE=E6=9F=A5=E7=9C=8B=E6=A8=A1?= =?UTF-8?q?=E7=BB=84=E8=AF=A6=E6=83=85=20(#3232)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update ModListPageSkin.java * Update ModListPageSkin.java * Update ModListPageSkin.java * Update ModListPageSkin.java * Update ModListPageSkin.java --- .../org/jackhuang/hmcl/ui/versions/ModListPageSkin.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index cb3883342d..028e74883b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -186,6 +186,14 @@ class ModListPageSkin extends SkinBase { } }); + listView.setOnContextMenuRequested(event -> { + ModInfoObject selectedItem = listView.getSelectionModel().getSelectedItem(); + if (selectedItem != null && listView.getSelectionModel().getSelectedItems().size() == 1) { + listView.getSelectionModel().clearSelection(); + Controllers.dialog(new ModInfoDialog(selectedItem)); + } + }); + center.setContent(listView); root.getContent().add(center); } From 8bbd1a7cf45392ff582d2509e33a60c4dd1c2c01 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Wed, 30 Oct 2024 02:19:45 +0800 Subject: [PATCH 083/169] Remove unused i18n keys in es, ja & ru (#3405) --- .../src/main/resources/assets/lang/I18N_es.properties | 11 ----------- .../src/main/resources/assets/lang/I18N_ja.properties | 6 ------ .../src/main/resources/assets/lang/I18N_ru.properties | 6 ------ 3 files changed, 23 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 2b69a9ef2c..4d71fd6bd0 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -475,12 +475,9 @@ game.crash.reason.mod_resolution_mod_version.any=%1$s (Cualquier versión) game.crash.reason.forge_repeat_installation=El juego actual no puede continuar ejecutándose debido a una instalación duplicada de Forge. Este es un problema conocido\nSe recomienda cargar los comentarios del registro en GitHub para que podamos encontrar más pistas y arreglar esta pregunta. \nActualmente puede ir a la instalación automática para desinstalar Forge y volver a instalarlo. game.crash.reason.optifine_repeat_installation=El juego actual no puede seguir ejecutándose debido a la instalación repetida de OptiFine. \nElimine OptiFine de la carpeta Mod o vaya a Gestión de juegos-Instalación automática para desinstalar OptiFine que se instala automáticamente. game.crash.reason.modmixin_failure=El juego actual no puede continuar ejecutándose debido a algunas fallas en la inyección de mods. \nEsto generalmente significa que el mod tiene un error o no es compatible con el entorno actual. \nPuede consultar el registro para ver si hay un mod incorrecto. -game.crash.reason.file_or_content_verification_failed=El juego actual tiene un problema porque fallaron algunos archivos o la verificación de contenido. \nIntente eliminar esta versión (incluidas las modificaciones) y vuelva a descargarla, o intente usar un proxy cuando vuelva a descargar, etc. game.crash.reason.mod_repeat_installation=El juego actual tiene múltiples Mods idénticos instalados repetidamente, y cada Mod solo puede aparecer una vez. Elimina los Mods repetidos y luego inicia el juego. game.crash.reason.forge_error=Forge puede haber proporcionado un mensaje de error.\nPuede ver el registro y realizar las acciones correspondientes de acuerdo con la información de registro en el informe de errores.\nSi no ve un mensaje de error, puede consultar el informe de errores para saber cómo ocurrió el error.\n%1$s game.crash.reason.mod_solution0=El juego actual no puede seguir ejecutándose debido a algunos problemas de modificación.\nPuede consultar el registro para ver si hay un mod incorrecto. -game.crash.reason.mod_profile_causes_game_crash=El juego actual no puede seguir ejecutándose debido a un problema con el perfil de mod.\nPuede consultar el registro del mod defectuoso y su archivo de configuración. -game.crash.reason.fabric_reports_an_error_and_gives_a_solution=Forge puede haber dado un mensaje de error.\nPuede ver el registro y realizar las acciones correspondientes de acuerdo con la información de registro en el informe de errores.\nSi no ve un mensaje de error, puede consultar el informe de errores para saber cómo ocurrió el error. game.crash.reason.java_version_is_too_high=El juego actual se bloqueó porque la versión de Java es demasiado alta y no puede seguir ejecutándose.\nCambie a una versión anterior de Java en la pestaña Java Path de Configuración global del juego o Configuración específica del juego antes de iniciar el juego.\nSi no es así, puede descargarlo desde java.com (Java8) o BellSoft Liberica Full JRE (Java17) y otras plataformas para descargar e instalar una (reinicie el iniciador después de la instalación). game.crash.reason.mod_name=El juego actual no puede continuar ejecutándose debido a un problema con el nombre del archivo mod. El nombre del archivo de\nMod solo debe usar mayúsculas y minúsculas (Aa ~ Zz), números (0 ~ 9), líneas horizontales (-), subrayado (_) y puntos (.) en toda la mitad del inglés.\n Por favor, vaya a la carpeta mod para agregar un carácter de Cumplimiento anterior a todos los nombres de archivo mod que no cumplan. game.crash.reason.incomplete_forge_installation=O jogo atual não pode continuar devido a uma instalação incompleta do Forge / NeoForge.\nDesinstale e reinstale o Forge / NeoForge em Configurações de versão - Instalação automática. @@ -538,11 +535,6 @@ game.crash.reason.unsatisfied_link_error=No se puede iniciar Minecraft porque fa Si ha modificado la configuración de la biblioteca nativa, por favor, asegúrese de que estas bibliotecas existen. O, por favor, intente iniciar de nuevo después de revertir a los valores predeterminados.\n\ Si no lo ha hecho, por favor, compruebe si le faltan mods de dependencia.\n\ De lo contrario, si usted cree que esto es causado por HMCL, por favor, comentarios a nosotros. -game.crash.reason.failed_to_load_a_library=Failed to load a library.\n\ -\n\ -Si ha modificado la configuración de la biblioteca nativa, por favor, asegúrese de que estas bibliotecas existen. O, por favor, intente iniciar de nuevo después de revertir a los valores predeterminados.\n\ -Si no lo ha hecho, por favor, compruebe si le faltan mods de dependencia.\n\ -De lo contrario, si usted cree que esto es causado por HMCL, por favor, comentarios a nosotros. game.crash.title=Juego interrumpido game.directory=Ruta del juego game.version=Versión del juego @@ -650,8 +642,6 @@ launch.advice.too_large_memory_for_32bit=Has asignado un tamaño de memoria mayo launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 o inferior sólo admite Java 8 para la plataforma Linux x86-64, porque las versiones posteriores no pueden cargar las bibliotecas nativas de 32 bits como liblwjgl.so\n\ \n\ Por favor, descárguelo de java.com, o instale OpenJDK 8. -launch.advice.vanilla_x86=Minecraft actualmente no proporciona soporte oficial para arquitecturas distintas de x86 o x86-64.\n\ -Puedes intentar descargar la librería nativa de tu plataforma y especificar su ruta, luego vuelve a intentarlo. launch.advice.vanilla_x86.translation=Minecraft no proporciona actualmente soporte oficial para arquitecturas distintas de x86 y x86-64.\n\ Por favor, instale Java para x86-64 para jugar a Minecraft a través del entorno de traducción Rosetta, o descargue sus bibliotecas nativas correspondientes y especifique su ruta. launch.failed=No se puede ejecutar @@ -768,7 +758,6 @@ modpack.scan=Análisis del índice de modpacks modpack.task.install=Instalar Modpack modpack.task.install.error=No se ha podido identificar este modpack. Actualmente sólo soportamos los modpacks Curse, Modrinth, MultiMC y MCBBS. modpack.type.curse=Curse -modpack.type.curse.tolerable_error=No se han podido descargar las dependencias, puedes intentar continuar la descarga ejecutando esta instancia del juego. modpack.type.curse.error=No se han podido descargar las dependencias de CurseForge, inténtalo de nuevo o utiliza una conexión proxy. modpack.type.curse.not_found=Algunas dependencias ya no están disponibles, por favor intenta instalar una versión más reciente del modpack. modpack.type.manual.warning=Este archivo contiene una copia completa de una instancia de Minecraft. La mayoría de las veces, sólo tienes que descomprimirlo y ejecutar el juego usando su launcher incorporado. Pero, HMCL todavía puede importarlo, sin garantía de su utilidad, ¿aún continúa? diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 55af068aea..813bff1b74 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -350,12 +350,9 @@ game.crash.reason.entity=エンティティが原因でゲームを実行でき game.crash.reason.fabric_version_0_12=Fabric 0.12以降は、現在インストールされているmodと互換性がありません。ファブリックを0.11.7にダウングレードする必要があります。 game.crash.reason.fabric_warnings=Fabricはいくつかの警告を出します:\n%1$s game.crash.reason.modmixin_failure=mod インジェクションの失敗により、現在のゲームを続行できません。\nこれは通常、MOD にバグがあるか、現在の環境と互換性がないことを意味します。\n間違った mod のログを確認できます。 -game.crash.reason.file_or_content_verification_failed=一部のファイルまたはコンテンツの検証に失敗したため、現在のゲームに問題があります。\nこのバージョン (mod を含む) を削除して再ダウンロードするか、再ダウンロード時にプロキシを使用するなどしてください。 game.crash.reason.mod_repeat_installation=現在のゲームには複数の同一の Mod が繰り返しインストールされており、各 Mod は 1 回しか表示できません。ゲームを開始する前に繰り返しの Mod を削除してください。 game.crash.reason.forge_error=Forge がエラー メッセージを表示した可能性があります。 \nログを表示し、エラー レポートのログ情報に従って対応するアクションを実行できます。 \nエラー メッセージが表示されない場合は、エラー レポートをチェックして、エラーがどのように発生したかを知ることができます。\n%1$s game.crash.reason.mod_resolution0=mod の問題により、現在のゲームを続行できません。 \n間違った mod のログを確認できます。 -game.crash.reason.mod_profile_causes_game_crash=mod プロファイルに問題があるため、現在のゲームを続行できません。 \n障害のある mod とその構成ファイルのログを確認できます。 -game.crash.reason.fabric_reports_an_error_and_gives_a_solution=Forge がエラー メッセージを表示した可能性があります。 \nログを表示し、エラー レポートのログ情報に従って対応するアクションを実行できます。 \nエラー メッセージが表示されない場合は、エラー レポートをチェックして、エラーがどのように発生したかを知ることができます。 game.crash.reason.java_version_is_too_high=Java のバージョンが高すぎて実行を継続できないため、現在のゲームがクラッシュしました。 \nゲームを起動する前に、グローバル ゲーム設定またはゲーム固有の設定の Java パス タブで Java の以前のバージョンに切り替えてください。 \nそうでない場合は、java.com (Java8) または BellSoft Liberica Full JRE (Java17) およびその他のプラットフォームをダウンロードしてインストールします (インストール後にランチャーを再起動します)。 game.crash.reason.mod_name=現在のゲームはModファイル名の問題で続行できません。\nModファイル名は、英文の全半角の大文字と小文字(Aa ~ Zz)、数字(0 ~ 9)、横線(-)、アンダースコア(_)、点(.)のみを使用してください。\n上記のコンプライアンス文字をModフォルダに追加してください。 game.crash.reason.incomplete_forge_installation=Forge / NeoForge のインストールが不完全なため、現在のゲームを続行できません。\nバージョン設定 - 自動インストールで Forge / NeoForge をアンインストールしてから再インストールしてください。 @@ -400,7 +397,6 @@ game.crash.reason.stacktrace=不明。[ログ]ボタンをクリックすると game.crash.reason.too_old_java=Java仮想マシンのバージョンが低すぎるため、ゲームを実行できません。\nゲーム設定でJava仮想マシンの新しいバージョン(%1$s)に切り替えて、ゲームを再起動する必要があります。そうでない場合は、オンラインでダウンロードできます。 game.crash.reason.unknown=不明。「ログ」ボタンをクリックすると詳細を確認できます。 game.crash.reason.unsatisfied_link_error=必要なネイティブライブラリがないため、ゲームを実行できません。\n不足しているネイティブライブラリ:%1$s。\nゲーム設定でネイティブライブラリパスオプションを変更した場合は、元に戻すことをお勧めします。標準モードに切り替えます。\nすでに標準モードになっている場合は、不足しているネイティブライブラリがmodまたはゲームに属しているかどうかを確認してください。HMCLが原因であることが確実な場合は、フィードバックをお送りください。\nネイティブライブラリパスを本当にカスタマイズする必要がある場合は、ゲームに必要なすべてのネイティブライブラリをディレクトリに配置する必要があります。 -game.crash.reason.failed_to_load_a_library=ネイティブ ライブラリのロードに失敗したため、ゲームを実行できません。\nゲーム設定でネイティブライブラリパスオプションを変更した場合は、元に戻すことをお勧めします。標準モードに切り替えます。\nすでに標準モードになっている場合は、不足しているネイティブライブラリがmodまたはゲームに属しているかどうかを確認してください。HMCLが原因であることが確実な場合は、フィードバックをお送りください。\nネイティブライブラリパスを本当にカスタマイズする必要がある場合は、ゲームに必要なすべてのネイティブライブラリをディレクトリに配置する必要があります。 game.crash.title=ゲームがクラッシュしました game.directory=ゲームディレクトリ game.version=ゲームバージョン @@ -611,8 +607,6 @@ modpack.scan=このmodpackをスキャンしています modpack.task.install=Modpackのインポート modpack.task.install.error=このmodpackファイルは認識できません。CurseおよびMultiMCmodpackのみがサポートされています。 modpack.type.curse=Curse -modpack.type.curse.completion=Cursemodpackに関連するファイルをインストールします -modpack.type.curse.tolerable_error=このmodpackのすべてのファイルのダウンロードを完了できません。対応するゲームバージョンを開始するときに、ダウンロードを再試行できます。ネットワークの問題により、数回再試行する場合があります。 modpack.type.curse.error=このmodpackをインストールできません。再試行してください。 modpack.type.curse.not_found=必要なリソースの一部が欠落しているため、ダウンロードできませんでした。最新バージョンまたは他のmodpackを検討してください。 modpack.type.manual.warning=このmodpackをインポートする代わりに、おそらくこのmodpackファイルを直接解凍する必要があります。そして、バンドルされたランチャーを使用してゲームを起動します。このmodpackは、ランチャーによってエクスポートされるのではなく、.minecraftディレクトリを圧縮することによって手動で作成されます。HMCLはこのmodpackのインポートを試みることができます、続行しますか? diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index c552e8deb1..c5a16cfc65 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -369,13 +369,10 @@ game.crash.reason.fabric_version_0_12=Fabric 0.12 (и выше) несовмес game.crash.reason.mixin_apply_mod_failed=Текущая игра не может продолжать работать из-за невозможности применения мода %1$s с помощью Mixin.\nВы можете попробовать удалить или обновить этот мод, чтобы решить проблему. game.crash.reason.fabric_warnings=Предупреждения от Fabric:\n%1$s game.crash.reason.modmixin_failure=Текущая игра не может продолжать работать из-за некоторых сбоев внедрения модов.\nОбычно это означает, что мод содержит ошибку или несовместим с текущей средой.\nВы можете проверить журнал на наличие неправильного мода. -game.crash.reason.file_or_content_verification_failed=В текущей игре возникла проблема, поскольку не удалось проверить некоторые файлы или содержимое.\nПожалуйста, попробуйте удалить эту версию (включая моды) и загрузить заново, или попробуйте использовать прокси при повторной загрузке и т. д. game.crash.reason.mod_repeat_installation=В текущей игре неоднократно установлено несколько одинаковых модов, и каждый мод может появиться только один раз. Пожалуйста, удалите повторяющиеся моды перед запуском игры. game.crash.reason.need_jdk11=Текущая игра не может продолжать работать из-за неподходящей версии виртуальной машины Java.\nВам необходимо загрузить и установить Java 11, а также установить версию Java, начинающуюся с 11, в глобальных (конкретных) настройках игры. game.crash.reason.forge_error=Возможно, Forge предоставил сообщение об ошибке.\nВы можете просмотреть журнал и выполнить соответствующие действия в соответствии с информацией журнала в отчете об ошибках.\nЕсли вы не видите сообщения об ошибке, вы можете просмотреть отчет об ошибке, чтобы узнать, как она возникла.\n%1$s game.crash.reason.mod_resolution0=Текущая игра не может продолжать работать из-за некоторых проблем с модом.\nВы можете проверить журнал на наличие неправильного мода. -game.crash.reason.mod_profile_causes_game_crash=Текущая игра не может продолжать работать из-за проблемы с профилем мода.\nВы можете проверить журнал на наличие неисправного мода и его конфигурационного файла. -game.crash.reason.fabric_reports_an_error_and_gives_a_solution=Forge мог выдать сообщение об ошибке.\nВы можете просмотреть журнал и выполнить соответствующие действия в соответствии с информацией журнала в отчете об ошибках.\nЕсли вы не видите сообщения об ошибке, вы можете просмотреть отчет об ошибке, чтобы узнать, как она возникла. game.crash.reason.java_version_is_too_high=Текущая игра аварийно завершилась из-за того, что версия Java слишком высока и не может продолжать работать.\nПеред запуском игры переключитесь на более раннюю версию Java на вкладке "Путь к Java" в глобальных настройках игры или в настройках игры.\nЕсли нет, вы можете загрузить его с java.com (Java8) или BellSoft Liberica Full JRE (Java17) и другие платформы, чтобы загрузить и установить ее (перезапустите программу запуска после установки). game.crash.reason.mod_name=Текущая игра не может продолжать работать из - за проблем с именем файла Mod. Имя файла\nMod должно быть использовано только в английском языке в полном углу с большими буквами (Aa ~ Zz), цифрами (0 ~ 9), горизонтальными линиями (-), подчеркнутыми (_) и точками (.) .\nПожалуйста, добавьте символ соответствия в папку Mod для всех несовместимых имен файлов Mod. game.crash.reason.incomplete_forge_installation=Текущая игра не может быть продолжена из-за незавершенной установки Forge / NeoForge.\nУдалите и переустановите Forge / NeoForge в настройках версии - Автоматическая установка. @@ -420,7 +417,6 @@ game.crash.reason.stacktrace=Неизвестно. Вы можете просм game.crash.reason.too_old_java=Невозможно запустить игру из-за того, что версия виртуальной машины Java слишком низкая.\nYou need to switch to a newer version (%1$s) of Java virtual machine in the game settings and restart the game. If not, you can download it online. game.crash.reason.unknown=Неизвестно. Вы можете просмотреть подробности, кликнув на кнопку «Журналы». game.crash.reason.unsatisfied_link_error=Невозможно запустить игру из-за того, что отсутствуют необходимые встроенные библиотеки.\nОтсутствующая нативная библиотека: %1$s.\nЕсли в настройках игры вы изменили параметр пути к нативной библиотеке, лучше переключиться обратно в стандартный режим.\nЕсли это уже стандартный режим, проверьте, принадлежит ли отсутствующая нативная библиотека моду или игре. Если вы уверены, что это произошло по вине HMCL, вы можете написать нам через обратную связь.\nЕсли вам действительно нужно настроить путь к нативным библиотекам, вы должны поместить в каталог все нативные библиотеки, которые требуются игре. -game.crash.reason.failed_to_load_a_library=Не удалось запустить игру, так как не удалось загрузить встроенную библиотеку.\nЕсли в настройках игры вы изменили параметр пути к нативной библиотеке, лучше переключиться обратно в стандартный режим.\nЕсли это уже стандартный режим, проверьте, принадлежит ли отсутствующая нативная библиотека моду или игре. Если вы уверены, что это произошло по вине HMCL, вы можете написать нам через обратную связь.\nЕсли вам действительно нужно настроить путь к нативным библиотекам, вы должны поместить в каталог все нативные библиотеки, которые требуются игре. game.crash.title=Игра вылетела game.directory=Путь игры game.version=Версия игры @@ -636,8 +632,6 @@ modpack.scan=Разбор индекса модпака modpack.task.install=Установить модпак modpack.task.install.error=Не удаётся идентифицировать этот модпак. Поддерживаются только модпаки Curse, Modrinth, MultiMC и MCBBS. modpack.type.curse=Curse -modpack.type.curse.completion=Установите файлы, связанные с модпаком Curse -modpack.type.curse.tolerable_error=Мы не можем завершить скачивание всех файлов этого модпака. Вы можете повторить скачивание при запуске соответствующей версии игры. Вы можете повторить попытку несколько раз из-за проблем с сетью. modpack.type.curse.error=Невозможно установить этот модпак. Повторите ещё раз. modpack.type.curse.not_found=Некоторые из необходимых ресурсов отсутствуют и поэтому не могут быть загружены. Скачайте последнюю версию или другие модпаки. modpack.type.manual.warning=Возможно, вам нужно напрямую распаковать файл этого модпака, а не импортировать его. И запустите игру с помощью прилагаемого лаунчера. Этот модпак создаётся вручную путем сжатия директории .minecraft, а не экспортируется лаунчером. HMCL может попытаться импортировать этот модпак, продолжать? From adcc3eb43f8890d5f9a97614cc9dc1291b925528 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Wed, 30 Oct 2024 02:20:39 +0800 Subject: [PATCH 084/169] Adjust buttons, chat & crash i18n (#3401) * Adjust buttons, chat & crash i18n - Add missing translations * fix * fix * fix * fix ja * fix es & ja --- HMCL/src/main/resources/assets/lang/I18N.properties | 1 + .../main/resources/assets/lang/I18N_es.properties | 11 ++++++++--- .../main/resources/assets/lang/I18N_ja.properties | 13 +++++++++---- .../main/resources/assets/lang/I18N_ru.properties | 3 +++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index e8ac9aa9ee..77d1cc321b 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -191,6 +191,7 @@ chat=Join Group Chat color.recent=Recommended color.custom=Custom Color + crash.NoClassDefFound=Please verify the integrity of this software, or try updating your Java. crash.user_fault=The launcher crashed due to a corrupted Java or system environment. Please make sure your Java or OS is installed properly. diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 4d71fd6bd0..ca3c6178e0 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -148,6 +148,7 @@ assets.index.malformed=Los archivos de índice de los activos descargados estaba button.cancel=Cancelar button.change_source=Cambiar fuente de descarga button.clear=Limpiar +button.copy_and_exit=Copiar y salir button.delete=Borrar button.edit=Editar button.install=Instalar @@ -156,17 +157,21 @@ button.no=No button.ok=Aceptar button.refresh=Refrescar button.remove=Eliminar -button.remove.confirm=¿Está seguro de querer eliminarlo definitivamente? Esta acción no se puede deshacer. +button.remove.confirm=¿Estás seguro de que deseas eliminarlo de forma permanente? ¡Esta acción no se puede deshacer! +button.retry=Reintentar button.save=Guardar button.save_as=Guardar como button.select_all=Seleccionar todo +button.view=Vista button.yes=Sí +chat=Chat de grupo + color.recent=Recomendado color.custom=Color personalizado -crash.NoClassDefFound=Por favor, verifique la integridad de este software, o intente actualizar su versión de Java. -crash.user_fault=El launcher se ha bloqueado debido a un entorno Java o de sistema corrupto. Por favor, asegúrese de que su Java o sistema operativo está instalado correctamente. +crash.NoClassDefFound=Por favor, verifique la integridad de este software, o intente actualizar su Java. +crash.user_fault=El lanzador se ha bloqueado debido a que Java o el entorno del sistema están dañados. Por favor, asegúrese de que su Java o sistema operativo está instalado correctamente. curse.category.0=Todos diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 813bff1b74..757eef2b6e 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -136,6 +136,7 @@ assets.index.malformed=アセットインデックスの形式が正しくあり button.cancel=キャンセル button.change_source=ダウンロードソースの変更 button.clear=クリア +button.copy_and_exit=コピーして終了 button.delete=削除 button.edit=編集 button.install=インストール @@ -144,19 +145,23 @@ button.no=いいえ button.ok=OK button.refresh=更新 button.remove=削除 -button.remove.confirm=削除してもよろしいですか?この操作をロールバックすることはできません! +button.remove.confirm=本当に完全に削除しますか?この操作は元に戻せません! +button.retry=リトライ button.save=保存 button.save_as=名前を付けて保存 button.select_all=すべて選択 +button.view=読む button.yes=はい +chat=グループチャット + color.recent=推奨 color.custom=カスタムカラー -crash.NoClassDefFound=「HelloMinecraft!Launcher」ソフトウェアが破損していないことを確認してください。 -crash.user_fault=OSまたはJava環境が正しくインストールされていない可能性があり、クラッシュする可能性があります。Javaランタイム環境またはコンピュータを確認してください。 +crash.NoClassDefFound=このソフトウェアの整合性を確認するか、Javaの更新をお試しください。 +crash.user_fault=JavaまたはOSの環境が壊れているため、ランチャーがクラッシュしました。JavaまたはOSが正しくインストールされているかご確認ください。 -curse.category.0=すべて +curse.category.0=全て # https://addons-ecs.forgesvc.net/api/v2/category/section/4471 curse.category.4474=Sci-Fi diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index c5a16cfc65..9d93bac688 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -156,8 +156,11 @@ button.retry=Повторить снова button.save=Сохранить button.save_as=Сохранить как button.select_all=Выбрать все +button.view=Просмотреть button.yes=Да +chat=Групповой чат + color.recent=Рекомендуемые color.custom=Пользовательский цвет From 4a8dcce3d4642f201c1712632cf4e115870c0349 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Wed, 30 Oct 2024 02:21:54 +0800 Subject: [PATCH 085/169] Adjust about page i18n (#3398) * Adjust about page i18n - Adjust all languages - Add missing translations * fix * fix --- .../resources/assets/lang/I18N.properties | 2 +- .../resources/assets/lang/I18N_es.properties | 22 ++++++---- .../resources/assets/lang/I18N_ja.properties | 42 ++++++++++--------- .../resources/assets/lang/I18N_ru.properties | 18 ++++---- 4 files changed, 48 insertions(+), 36 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 77d1cc321b..8e29f3c7fb 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -38,7 +38,7 @@ about.thanks_to.glavo.statement=Responsible for maintaining HMCL. about.thanks_to.zekerzhayard.statement=Contribute a lot of technical support to HMCL. about.thanks_to.zkitefly.statement=Responsible for maintaining the documentation of HMCL. about.thanks_to.mcbbs=MCBBS (Minecraft Chinese Forum) -about.thanks_to.mcbbs.statement=For providing the mcbbs.net download mirror for Chinese Mainland users. +about.thanks_to.mcbbs.statement=For providing the mcbbs.net download mirror for Chinese Mainland users. (No longer available) about.thanks_to.mcmod=MCMod (mcmod.cn) about.thanks_to.mcmod.statement=For providing the Simplified Chinese translations and wiki for various mods. about.thanks_to.red_lnn.statement=For providing the default background image. diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index ca3c6178e0..e250a6bd31 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -23,25 +23,29 @@ about=Acerca de about.copyright=Copyright about.copyright.statement=Copyright © 2024 huangyuhui. about.author=Autor -about.author.statement=@huanghongxun en bilibili +about.author.statement=bilibili @huanghongxun about.claim=EULA -about.claim.statement=Haz clic en este enlace para ver el texto completo. +about.claim.statement=Haga clic en este enlace para ver el texto completo. about.dependency=Bibliotecas de terceros about.legal=Reconocimiento legal about.thanks_to=Gracias a -about.thanks_to.bangbang93.statement=Por proporcionar la API de descarga de BMCLAPI, por favor considere hacer una donación. +about.thanks_to.bangbang93.statement=Por proporcionar el espejo de descarga de BMCLAPI, por favor considere hacer una donación! +about.thanks_to.burningtnt.statement=Aportar mucho apoyo técnico a HMCL. about.thanks_to.contributors=Todos los colaboradores en GitHub -about.thanks_to.contributors.statement=Sin la impresionante comunidad de código abierto, Hello Minecraft! Launcher no habría llegado tan lejos. +about.thanks_to.contributors.statement=Sin la impresionante comunidad de código abierto, HMCL no habría llegado tan lejos. about.thanks_to.gamerteam.statement=Por proporcionar la imagen de fondo por defecto. -about.thanks_to.glavo.statement=Aportar mucho apoyo técnico a HMCL. +about.thanks_to.glavo.statement=Responsable del mantenimiento de HMCL. about.thanks_to.zekerzhayard.statement=Aportar mucho apoyo técnico a HMCL. -about.thanks_to.zkitefly.statement=Aportar mucho apoyo técnico a HMCL. -about.thanks_to.mcmod=mcmod.cn -about.thanks_to.mcmod.statement=Por facilitar las traducciones al chino y el wiki de varios mods. +about.thanks_to.zkitefly.statement=Responsable del mantenimiento de la documentación de HMCL. +about.thanks_to.mcbbs=MCBBS (Foro Chino Minecraft) +about.thanks_to.mcbbs.statement=Por proporcionar el espejo de descarga de mcbbs.net para los usuarios de China continental. (Ya no disponible) +about.thanks_to.mcmod=MCMod (mcmod.cn) +about.thanks_to.mcmod.statement=Por proporcionar las traducciones al chino simplificado y la wiki de varios mods. about.thanks_to.red_lnn.statement=Por proporcionar la imagen de fondo por defecto. +about.thanks_to.shulkersakura.statement=Por proporcionar el logotipo de HMCL. about.thanks_to.users=Miembros del grupo de usuarios de HMCL about.thanks_to.users.statement=Gracias por las donaciones, los informes de errores, etc. -about.thanks_to.yushijinhun.statement=Por proporcionar soporte relacionado con authlib-injector. +about.thanks_to.yushijinhun.statement=Por proporcionar el soporte relacionado con authlib-injector. about.open_source=Código abierto about.open_source.statement=GPL v3 (https://github.com/HMCL-dev/HMCL) diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 757eef2b6e..2194eb81d2 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -18,31 +18,35 @@ # Contributors: zhixuan2333 -about=About +about=について about.copyright=著作権 -about.copyright.statement=Copyright © 2024 huangyuhui。 -about.author=Author -about.author.statement=bilibili : @huanghongxun +about.copyright.statement=Copyright © 2024 huangyuhui +about.author=著者 +about.author.statement=bilibili @huanghongxun about.claim=EULA -about.claim.statement=テキスト全体のリンクをクリックします。 -about.dependency=Dependencies +about.claim.statement=全文はこのリンクをクリック +about.dependency=依存関係 about.legal=法的承認 -about.thanks_to=Thanks to -about.thanks_to.bangbang93.statement=BMCLAPIダウンロードソースプロバイダー。 -about.thanks_to.contributors=問題、プルリクエストなどを介してこのプロジェクトに参加したすべての貢献者。 -about.thanks_to.contributors.statement=Hello Minecraftをサポートしてくれたオープンソースコミュニティに感謝します!ランチャー -about.thanks_to.gamerteam.statement=デフォルトの背景画像プロバイダー。 -about.thanks_to.glavo.statement=HMCLに多くのテクニカルサポートを提供 +about.thanks_to=感謝します… +about.thanks_to.bangbang93.statement=BMCLAPIダウンロードミラープロバイダー。寄付をご検討ください! +about.thanks_to.burningtnt.statement=HMCLに多くのテクニカルサポートを提供 +about.thanks_to.contributors=GitHubのすべての貢献者 +about.thanks_to.contributors.statement=HMCLをサポートしてくれたオープンソースコミュニティに感謝する +about.thanks_to.gamerteam.statement=デフォルトの背景画像プロバイダー +about.thanks_to.glavo.statement=HMCLのメンテナ about.thanks_to.zekerzhayard.statement=HMCLに多くのテクニカルサポートを提供 -about.thanks_to.zkitefly.statement=HMCLに多くのテクニカルサポートを提供。 -about.thanks_to.mcmod=mcmod.cn -about.thanks_to.mcmod.statement=Mod中国語の名前翻訳プロバイダー。 -about.thanks_to.red_lnn.statement=デフォルトの背景画像プロバイダー。 +about.thanks_to.zkitefly.statement=HMCLドキュメントメンテナ +about.thanks_to.mcbbs=MCBBS (Minecraft中国語フォーラム) +about.thanks_to.mcbbs.statement=中国本土ユーザー向けのmcbbs.netダウンロードミラープロバイダー(もう利用できません) +about.thanks_to.mcmod=MCMod (mcmod.cn) +about.thanks_to.mcmod.statement=様々なMODの簡体字中国語名前翻訳とウィキを提供する +about.thanks_to.red_lnn.statement=デフォルトの背景画像プロバイダー +about.thanks_to.shulkersakura.statement=HMCLロゴプロバイダー about.thanks_to.users=HMCLユーザーグループのメンバー -about.thanks_to.users.statement=寄付、バグレポートなどに感謝します。 -about.thanks_to.yushijinhun.statement=authlib-インジェクターのサポート +about.thanks_to.users.statement=寄付、バグレポートなどに感謝します +about.thanks_to.yushijinhun.statement=authlib-injector関連のサポートを提供する about.open_source=オープンソース -about.open_source.statement=GPL v3(https://github.com/HMCL-dev/HMCL/) +about.open_source.statement=GPL v3 (https://github.com/HMCL-dev/HMCL) account=アカウント account.cape=マント diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 9d93bac688..2938888937 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -22,22 +22,26 @@ about=О лаунчере about.copyright=Авторские права about.copyright.statement=Авторские права © 2024 huangyuhui. about.author=Автор -about.author.statement=bilibili: @huanghongxun +about.author.statement=bilibili @huanghongxun about.claim=EULA about.claim.statement=Кликните на ссылку, чтобы увидеть весь текст. about.dependency=Зависимости about.legal=Юридическое подтверждение about.thanks_to=Отдельная благодарность -about.thanks_to.bangbang93.statement=За предоставление API скачивания BMCLAPI. Рассмотрите возможность пожертвования. +about.thanks_to.bangbang93.statement=За предоставление зеркала загрузки BMCLAPI, пожалуйста, подумайте о пожертвовании! +about.thanks_to.burningtnt.statement=Оказал большую техническую поддержку HMCL. about.thanks_to.contributors=Всем участникам на GitHub -about.thanks_to.contributors.statement=Без потрясающего сообщества с открытым исходным кодом, Hello Minecraft! Launcher не смог бы добраться так далеко. +about.thanks_to.contributors.statement=Без потрясающего сообщества с открытым исходным кодом, HMCL не смог бы добраться так далеко. about.thanks_to.gamerteam.statement=За предоставление фонового изображения. -about.thanks_to.glavo.statement=Оказал большую техническую поддержку HMCL. +about.thanks_to.glavo.statement=Отвечает за поддержание HMCL. about.thanks_to.zekerzhayard.statement=Оказал большую техническую поддержку HMCL. -about.thanks_to.zkitefly.statement=Оказал большую техническую поддержку HMCL. -about.thanks_to.mcmod=mcmod.cn -about.thanks_to.mcmod.statement=За предоставление перевода на китайский и вики для различных модов. +about.thanks_to.zkitefly.statement=Отвечает за поддержание документации HMCL. +about.thanks_to.mcbbs=MCBBS (Китайский форум Minecraft) +about.thanks_to.mcbbs.statement=За предоставление зеркала загрузки mcbbs.net для пользователей материкового Китая. (Больше недоступно) +about.thanks_to.mcmod=MCMod (mcmod.cn) +about.thanks_to.mcmod.statement=За предоставление упрощенного китайского перевода и вики для различных модов. about.thanks_to.red_lnn.statement=За предоставление фонового изображения. +about.thanks_to.shulkersakura.statement=За предоставление логотипа для HMCL. about.thanks_to.users=Членам группы пользователей HMCL about.thanks_to.users.statement=Спасибо за пожертвования, отчёты об ошибках и так далее. about.thanks_to.yushijinhun.statement=За предоставление поддержки, связанной с authlib-injector. From 7a3f125802b3ed3a91fedcb539a73a9db3049f07 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Wed, 30 Oct 2024 02:22:34 +0800 Subject: [PATCH 086/169] Adjust custom command hint (zh_CN only) (#3394) I forgot to change the zh_CN part. A half-width colon is better. --- .../assets/lang/I18N_zh_CN.properties | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) 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 eae47b67ce..9fca104a79 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -944,17 +944,17 @@ settings.advanced.modify=编辑高级设置 settings.advanced.title=高级设置 - %s settings.advanced.custom_commands=自定义命令 settings.advanced.custom_commands.hint=自定义命令被调用时将包含如下的环境变量:\n\ - \ · $INST_NAME:版本名称;\n\ - \ · $INST_ID:版本名称;\n\ - \ · $INST_DIR:当前版本运行路径;\n\ - \ · $INST_MC_DIR:当前游戏文件夹路径;\n\ - \ · $INST_JAVA:游戏运行使用的 Java 路径;\n\ - \ · $INST_FORGE:若安装了 Forge,将会存在本环境变量;\n\ - \ · $INST_NEOFORGE:若安装了 NeoForge,将会存在本环境变量;\n\ - \ · $INST_LITELOADER:若安装了 LiteLoader,将会存在本环境变量;\n\ - \ · $INST_OPTIFINE:若安装了 OptiFine,将会存在本环境变量;\n\ - \ · $INST_FABRIC:若安装了 Fabric,将会存在本环境变量;\n\ - \ · $INST_QUILT:若安装了 Quilt,将会存在本环境变量。 + \ · $INST_NAME: 版本名称;\n\ + \ · $INST_ID: 版本名称;\n\ + \ · $INST_DIR: 当前版本运行路径;\n\ + \ · $INST_MC_DIR: 当前游戏文件夹路径;\n\ + \ · $INST_JAVA: 游戏运行使用的 Java 路径;\n\ + \ · $INST_FORGE: 若安装了 Forge,将会存在本环境变量;\n\ + \ · $INST_NEOFORGE: 若安装了 NeoForge,将会存在本环境变量;\n\ + \ · $INST_LITELOADER: 若安装了 LiteLoader,将会存在本环境变量;\n\ + \ · $INST_OPTIFINE: 若安装了 OptiFine,将会存在本环境变量;\n\ + \ · $INST_FABRIC: 若安装了 Fabric,将会存在本环境变量;\n\ + \ · $INST_QUILT: 若安装了 Quilt,将会存在本环境变量。 settings.advanced.dont_check_game_completeness=不检查游戏完整性 settings.advanced.dont_check_jvm_validity=不检查 JVM 与游戏的兼容性 settings.advanced.dont_patch_natives=不尝试自动替换本地库 From a66ccd7385df548a3f1f61120422feffcfb50ac9 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Wed, 30 Oct 2024 02:26:55 +0800 Subject: [PATCH 087/169] Adjust Microsoft login related i18n (#3393) * Adjust Microsoft login related i18n - Adjust English and Chinese - Fix typos and grammatical errors * fix --- .../main/resources/assets/lang/I18N.properties | 4 ++-- .../resources/assets/lang/I18N_zh.properties | 16 ++++++++-------- .../assets/lang/I18N_zh_CN.properties | 18 +++++++++--------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 8e29f3c7fb..9e8364c102 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -95,13 +95,13 @@ account.copy_uuid=Copy UUID of the Account account.methods=Login Type account.methods.authlib_injector=authlib-injector account.methods.microsoft=Microsoft -account.methods.microsoft.birth=How to Update Your Account Birthday +account.methods.microsoft.birth=How to Change Your Account Birthday account.methods.microsoft.close_page=Microsoft account authorization is now completed.\n\ \n\ There are some extra works for us, but you can safely close this tab for now. account.methods.microsoft.deauthorize=Deauthorize account.methods.microsoft.error.add_family=An adult must add you to a family in order for you to play Minecraft due to you are not yet 18 years old. -account.methods.microsoft.error.add_family_probably=Please check if the age indicated in your account settings is at least 18 years old. If not and you believe this is an error, you can click "How to Update Your Account Birthday" to learn how to change it. +account.methods.microsoft.error.add_family_probably=Please check if the age indicated in your account settings is at least 18 years old. If not and you believe this is an error, you can click "How to Change Your Account Birthday" to learn how to change it. account.methods.microsoft.error.country_unavailable=Xbox Live is not available in your current country/region. account.methods.microsoft.error.missing_xbox_account=Your Microsoft account does not have a linked Xbox account yet. Please click "Create Profile / Edit Profile Name" to create one before continuing. account.methods.microsoft.error.no_character=Your account does not own the Minecraft Java Edition.\nThe game profile may not have been created\nplease click "Create Profile / Edit Profile Name" to create it. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 7b9ca4f731..11938d23f9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -65,7 +65,7 @@ account.failed.injector_download_failure=無法下載 authlib-injector,請檢 account.failed.invalid_credentials=你的使用者名稱或密碼錯誤,或者登入次數過多被暫時禁止登入,請稍後再試。 account.failed.invalid_password=密碼無效 account.failed.invalid_token=請嘗試登出並重新輸入密碼登入。 -account.failed.migration=你的帳戶需要遷移至 Microsoft 帳戶。如果你已經遷移,你需要使用 Microsoft 方式登入遷移後的帳戶。 +account.failed.migration=你的帳戶需要遷移至 Microsoft 帳戶。如果你已經遷移,你需要使用遷移後的 Microsoft 帳戶登入。 account.failed.no_character=該帳戶沒有角色。 account.failed.server_disconnected=無法訪問登入伺服器,帳戶資訊重新整理失敗。\n\ 你可以選取「再次重新整理帳戶」重新嘗試。\n\ @@ -98,11 +98,11 @@ account.copy_uuid=複製該帳戶的 UUID account.methods=登入方式 account.methods.authlib_injector=authlib-injector 登入 account.methods.microsoft=Microsoft 帳戶 -account.methods.microsoft.birth=如何修改帳戶出生日期 -account.methods.microsoft.deauthorize=解除帳戶授權 +account.methods.microsoft.birth=如何變更帳戶出生日期 +account.methods.microsoft.deauthorize=移除應用存取權 account.methods.microsoft.close_page=已完成 Microsoft 帳戶授權,接下來啟動器還需要完成其餘登入步驟。你現在可以關閉本頁面了。 -account.methods.microsoft.error.add_family=由於你未滿 18 歲,你的帳戶必須被加入到家庭中才能登入遊戲。你也可以點擊上方連結更改你的帳戶的出生日期,使年齡滿 18 歲以上以繼續登入。 -account.methods.microsoft.error.add_family_probably=請檢查你的帳戶設定,如果你未滿 18 歲,你的帳戶必須被加入到家庭中才能登入遊戲。你也可以點擊上方連結更改你的帳戶的出生日期,使年齡滿 18 歲以上以繼續登入。 +account.methods.microsoft.error.add_family=由於你未滿 18 歲,你的帳戶必須被加入到家庭中才能登入遊戲。你也可以點擊上方「編輯帳戶配置檔」更改你的帳戶出生日期,使年齡滿 18 歲以上以繼續登入。 +account.methods.microsoft.error.add_family_probably=請檢查你的帳戶設定,如果你未滿 18 歲,你的帳戶必須被加入到家庭中才能登入遊戲。你也可以點擊上方「編輯帳戶配置檔」更改你的帳戶出生日期,使年齡滿 18 歲以上以繼續登入。 account.methods.microsoft.error.country_unavailable=你所在的國家或地區不受 Xbox Live 的支援。 account.methods.microsoft.error.missing_xbox_account=你的 Microsoft 帳戶尚未關聯 Xbox 帳戶,你必須先建立 Xbox 帳戶,才能登入遊戲。 account.methods.microsoft.error.no_character=該帳戶未包含 Minecraft: Java 版購買記錄。\n若已購買,則可能未建立遊戲檔案,請點擊上方連結建立。 @@ -112,17 +112,17 @@ account.methods.microsoft.logging_in=登入中…… account.methods.microsoft.makegameidsettings=建立檔案 / 編輯檔案名稱 account.methods.microsoft.hint=請點擊「登入」按鈕,稍後複製此處顯示的代碼,在打開的登入網頁中完成登入過程。\n\ \n\ - 如果登入 Microsoft 帳戶的令牌洩露,可點擊下方連結解除授權,然後等待令牌過期。\n\ + 如果登入 Microsoft 帳戶的令牌洩露,可點擊下方「移除應用存取權」,然後等待令牌過期。\n\ \n\ 如遇到問題,你可以點擊右上角幫助按鈕進行求助。 account.methods.microsoft.manual=你的代碼為 %1$s,請點擊此處複製。\n\ \n\ 點擊「登入」按鈕後,你應該在打開的登入網頁中完成登入過程。如果網頁沒有打開,你可以自行在瀏覽器中訪問 %2$s\n\ \n\ - 如果登入 Microsoft 帳戶的令牌洩露,可點擊下方連結解除授權,然後等待令牌過期。\n\ + 如果登入 Microsoft 帳戶的令牌洩露,可點擊下方「移除應用存取權」,然後等待令牌過期。\n\ \n\ 如遇到問題,你可以點擊右上角幫助按鈕進行求助。 -account.methods.microsoft.profile=帳戶設定頁 +account.methods.microsoft.profile=編輯帳戶配置檔 account.methods.microsoft.purchase=購買 Minecraft account.methods.forgot_password=忘記密碼 account.methods.microsoft.snapshot=你正在使用第三方提供的 HMCL,請下載官方版本進行登入。 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 9fca104a79..4de5ee6e5d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -65,7 +65,7 @@ account.failed.injector_download_failure=无法下载 authlib-injector,可能 account.failed.invalid_credentials=你的用户名或密码错误,或登录次数过多被暂时禁止登录,请稍后再试。 account.failed.invalid_password=无效的密码 account.failed.invalid_token=请尝试登出并重新输入密码登录 -account.failed.migration=你的账户需要迁移至微软账户。如果你已经迁移,你需要使用微软账户登录迁移后的账户。 +account.failed.migration=你的账户需要迁移至微软账户。如果你已经迁移,你需要使用迁移后的微软账户登录。 account.failed.no_character=该账户没有角色 account.failed.server_disconnected=无法访问登录服务器,账户信息刷新失败。\n\ 你可以选择“再次刷新账户”重新尝试。\n\ @@ -99,11 +99,11 @@ account.copy_uuid=复制该账户的 UUID account.methods=登录方式 account.methods.authlib_injector=外置登录 (authlib-injector) account.methods.microsoft=微软账户 -account.methods.microsoft.birth=如何修改账户出生日期 +account.methods.microsoft.birth=如何更改账户出生日期 account.methods.microsoft.close_page=已完成微软账户授权,接下来启动器还需要完成其余登录步骤。你现在可以关闭本页面了。 account.methods.microsoft.deauthorize=解除账户授权 -account.methods.microsoft.error.add_family=请点击上方“账户设置页”更改你的账户出生日期,使年龄满 18 岁以上,或将账户加入到家庭中。\n你可以点击右上角帮助按钮进行求助。 -account.methods.microsoft.error.add_family_probably=请点击上方“账户设置页”更改你的账户出生日期,使年龄满 18 岁以上,或将账户加入到家庭中。\n你可以点击右上角帮助按钮进行求助。 +account.methods.microsoft.error.add_family=请点击上方“编辑账户个人信息”更改你的账户出生日期,使年龄满 18 岁以上,或将账户加入到家庭中。\n你可以点击右上角帮助按钮进行求助。 +account.methods.microsoft.error.add_family_probably=请点击上方“编辑账户个人信息”更改你的账户出生日期,使年龄满 18 岁以上,或将账户加入到家庭中。\n你可以点击右上角帮助按钮进行求助。 account.methods.microsoft.error.country_unavailable=你所在的国家或地区不受 Xbox Live 的支持。 account.methods.microsoft.error.missing_xbox_account=请点击上方“创建档案”关联 Xbox 账户。\n你可以点击右上角帮助按钮进行求助。 account.methods.microsoft.error.no_character=请确认你已经购买了 Minecraft: Java 版。\n若已购买,则可能未创建游戏档案,请点击上方“创建档案”以创建游戏档案。\n你可以点击右上角帮助按钮进行求助。 @@ -116,8 +116,8 @@ account.methods.microsoft.hint=你需要按照以下步骤添加账户:\n\ \ 2. 在弹出的网页中输入 HMCL 显示的代码,并点击“允许访问”;\n\ \ 3. 按照网站的提示登录;\n\ \ 4. 当网站提示“是否允许此应用访问你的信息?”时,请点击“接受”;\n\ - \ 5. 在网站提示“大功告成”后,只需等待账户完成添加即可。\n\ - 若网站提示“出现错误”或账户添加失败时,请重新按照以上步骤重新添加。\n\ + \ 5. 在网站提示“大功告成”后,等待账户完成添加即可。\n\ + 若网站提示“出现错误”或账户添加失败时,请按照以上步骤重新添加。\n\ 若设备网络环境不佳,可能会导致网页加载缓慢甚至无法加载,请使用网络代理并重试。\n\ 如遇到问题,你可以点击右上角帮助按钮进行求助。 account.methods.microsoft.manual=你需要按照以下步骤添加:\n\ @@ -125,12 +125,12 @@ account.methods.microsoft.manual=你需要按照以下步骤添加:\n\ \ 2. 在弹出的网页中输入 %1$s (已自动复制),并点击“允许访问”;\n\ \ 3. 按照网站的提示登录;\n\ \ 4. 当网站提示“是否允许此应用访问你的信息?”时,请点击“接受”;\n\ - \ 5. 在网站提示“大功告成”后,只需等待账户完成添加即可。\n\ + \ 5. 在网站提示“大功告成”后,等待账户完成添加即可。\n\ 若网站未能显示,请手动在浏览器中打开:%2$s\n\ - 若网站提示“出现错误”或账户添加失败时,请重新按照以上步骤重新添加。\n\ + 若网站提示“出现错误”或账户添加失败时,请按照以上步骤重新添加。\n\ 若设备网络环境不佳,可能会导致网页加载缓慢甚至无法加载,请使用网络代理并重试。\n\ 如遇到问题,你可以点击右上角帮助按钮进行求助。 -account.methods.microsoft.profile=账户设置页 +account.methods.microsoft.profile=编辑账户个人信息 account.methods.microsoft.purchase=购买 Minecraft account.methods.forgot_password=忘记密码 account.methods.microsoft.snapshot=你正在使用第三方提供的 HMCL,请下载官方版本来登录微软账户。 From 0b1ce6e94a00144a7a831854f6e9021ce57c8e40 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Thu, 31 Oct 2024 23:30:44 +0800 Subject: [PATCH 088/169] Adjust language selection order (#3411) Sort alphabetically by language code. --- .../org/jackhuang/hmcl/util/i18n/Locales.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/Locales.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/Locales.java index 6f5309d3e1..868371dce8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/Locales.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/Locales.java @@ -39,16 +39,6 @@ private Locales() { */ public static final SupportedLocale EN = new SupportedLocale(Locale.ROOT); - /** - * Traditional Chinese - */ - public static final SupportedLocale ZH = new SupportedLocale(Locale.TRADITIONAL_CHINESE); - - /** - * Simplified Chinese - */ - public static final SupportedLocale ZH_CN = new SupportedLocale(Locale.SIMPLIFIED_CHINESE); - /** * Spanish */ @@ -64,23 +54,33 @@ private Locales() { */ public static final SupportedLocale JA = new SupportedLocale(Locale.JAPANESE); - public static final List LOCALES = Lang.immutableListOf(DEFAULT, EN, ZH_CN, ZH, ES, RU, JA); + /** + * Traditional Chinese + */ + public static final SupportedLocale ZH = new SupportedLocale(Locale.TRADITIONAL_CHINESE); + + /** + * Simplified Chinese + */ + public static final SupportedLocale ZH_CN = new SupportedLocale(Locale.SIMPLIFIED_CHINESE); + + public static final List LOCALES = Lang.immutableListOf(DEFAULT, EN, ES, JA, RU, ZH_CN, ZH); public static SupportedLocale getLocaleByName(String name) { if (name == null) return DEFAULT; switch (name.toLowerCase(Locale.ROOT)) { case "en": return EN; - case "zh": - return ZH; - case "zh_cn": - return ZH_CN; case "es": return ES; - case "ru": - return RU; case "ja": return JA; + case "ru": + return RU; + case "zh": + return ZH; + case "zh_cn": + return ZH_CN; default: return DEFAULT; } @@ -88,11 +88,11 @@ public static SupportedLocale getLocaleByName(String name) { public static String getNameByLocale(SupportedLocale locale) { if (locale == EN) return "en"; - else if (locale == ZH) return "zh"; - else if (locale == ZH_CN) return "zh_CN"; else if (locale == ES) return "es"; else if (locale == RU) return "ru"; else if (locale == JA) return "ja"; + else if (locale == ZH) return "zh"; + else if (locale == ZH_CN) return "zh_CN"; else if (locale == DEFAULT) return "def"; else throw new IllegalArgumentException("Unknown locale: " + locale); } From 3bf5204e793228071543ef691eb84fe6bfb3fce6 Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 1 Nov 2024 02:12:16 +0800 Subject: [PATCH 089/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20Theme=20(#3414)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/setting/Theme.java | 95 ++++++++----------- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 17 ++++ HMCL/src/main/resources/assets/css/custom.css | 30 ------ 3 files changed, 59 insertions(+), 83 deletions(-) delete mode 100644 HMCL/src/main/resources/assets/css/custom.css diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java index 076c284611..e5b116ad85 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java @@ -24,9 +24,8 @@ import javafx.beans.binding.ObjectBinding; import javafx.scene.paint.Color; import javafx.scene.text.Font; -import org.jackhuang.hmcl.util.Lang; +import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.io.IOUtils; import java.io.File; import java.io.IOException; @@ -36,11 +35,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Base64; import java.util.Locale; import java.util.Objects; import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -58,34 +56,6 @@ public class Theme { Color.web("#B71C1C") // red }; - private static Charset cssCharset; - - private static Charset getCssCharset() { - if (cssCharset != null) - return cssCharset; - - Charset defaultCharset = Charset.defaultCharset(); - if (defaultCharset != StandardCharsets.UTF_8) { - // https://bugs.openjdk.org/browse/JDK-8279328 - // For JavaFX 17 or earlier, native encoding should be used - String jfxVersion = System.getProperty("javafx.version"); - if (jfxVersion != null) { - Matcher matcher = Pattern.compile("^(?[0-9]+)").matcher(jfxVersion); - if (matcher.find()) { - int v = Lang.parseInt(matcher.group(), -1); - if (v >= 18) { - cssCharset = StandardCharsets.UTF_8; - } - } - } - } - - if (cssCharset == null) - cssCharset = defaultCharset; - - return cssCharset; - } - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private static Optional font; @@ -145,6 +115,14 @@ public Color getForegroundColor() { return isLight() ? Color.BLACK : Color.WHITE; } + private static String rgba(Color color, double opacity) { + return String.format("rgba(%d, %d, %d, %.1f)", + (int) Math.ceil(color.getRed() * 256), + (int) Math.ceil(color.getGreen() * 256), + (int) Math.ceil(color.getBlue() * 256), + opacity); + } + public String[] getStylesheets(String overrideFontFamily) { String css = "/assets/css/blue.css"; @@ -163,30 +141,41 @@ public String[] getStylesheets(String overrideFontFamily) { if (fontFamily != null || !this.color.equalsIgnoreCase(BLUE.color)) { Color textFill = getForegroundColor(); - String fontCss = ""; + + StringBuilder themeBuilder = new StringBuilder(512); + themeBuilder.append(".root {") + .append("-fx-base-color:").append(color).append(';') + .append("-fx-base-darker-color: derive(-fx-base-color, -10%);") + .append("-fx-base-check-color: derive(-fx-base-color, 30%);") + .append("-fx-rippler-color:").append(rgba(paint, 0.3)).append(';') + .append("-fx-base-rippler-color: derive(").append(rgba(paint, 0.3)).append(", 100%);") + .append("-fx-base-disabled-text-fill:").append(rgba(textFill, 0.7)).append(";") + .append("-fx-base-text-fill:").append(getColorDisplayName(getForegroundColor())).append(";") + .append("-theme-thumb:").append(rgba(paint, 0.7)).append(";"); + if (fontFamily != null) { - fontCss = "-fx-font-family: \"" + fontFamily + "\";"; + themeBuilder.append("-fx-font-family:\"").append(fontFamily).append("\";"); if (fontStyle != null && !fontStyle.isEmpty()) - fontCss += " -fx-font-style: \"" + fontStyle + "\";"; + themeBuilder.append("-fx-font-style:\"").append(fontStyle).append("\";"); } - try { - File temp = File.createTempFile("hmcl", ".css"); - String themeText = IOUtils.readFullyAsString(Theme.class.getResourceAsStream("/assets/css/custom.css")) - .replace("%base-color%", color) - .replace("%base-red%", Integer.toString((int) Math.ceil(paint.getRed() * 256))) - .replace("%base-green%", Integer.toString((int) Math.ceil(paint.getGreen() * 256))) - .replace("%base-blue%", Integer.toString((int) Math.ceil(paint.getBlue() * 256))) - .replace("%base-rippler-color%", String.format("rgba(%d, %d, %d, 0.3)", (int) Math.ceil(paint.getRed() * 256), (int) Math.ceil(paint.getGreen() * 256), (int) Math.ceil(paint.getBlue() * 256))) - .replace("%disabled-font-color%", String.format("rgba(%d, %d, %d, 0.7)", (int) Math.ceil(textFill.getRed() * 256), (int) Math.ceil(textFill.getGreen() * 256), (int) Math.ceil(textFill.getBlue() * 256))) - .replace("%font-color%", getColorDisplayName(getForegroundColor())) - .replace("%font%", fontCss); - FileUtils.writeText(temp, themeText, getCssCharset()); - temp.deleteOnExit(); - css = temp.toURI().toString(); - } catch (IOException | NullPointerException e) { - LOG.error("Unable to create theme stylesheet. Fallback to blue theme.", e); - } + themeBuilder.append('}'); + + if (FXUtils.JAVAFX_MAJOR_VERSION >= 17) + // JavaFX 17+ support loading stylesheets from data URIs + // https://bugs.openjdk.org/browse/JDK-8267554 + css = "data:text/css;charset=UTF-8;base64," + Base64.getEncoder().encodeToString(themeBuilder.toString().getBytes(StandardCharsets.UTF_8)); + else + try { + File temp = File.createTempFile("hmcl", ".css"); + // For JavaFX 17 or earlier, CssParser uses the default charset + // https://bugs.openjdk.org/browse/JDK-8279328 + FileUtils.writeText(temp, themeBuilder.toString(), Charset.defaultCharset()); + temp.deleteOnExit(); + css = temp.toURI().toString(); + } catch (IOException | NullPointerException e) { + LOG.error("Unable to create theme stylesheet. Fallback to blue theme.", e); + } } return new String[]{css, "/assets/css/root.css"}; @@ -235,7 +224,7 @@ else if (name.startsWith("#")) } public static String getColorDisplayName(Color c) { - return c != null ? String.format("#%02x%02x%02x", Math.round(c.getRed() * 255.0D), Math.round(c.getGreen() * 255.0D), Math.round(c.getBlue() * 255.0D)).toUpperCase(Locale.ROOT) : null; + return c != null ? String.format("#%02X%02X%02X", Math.round(c.getRed() * 255.0D), Math.round(c.getGreen() * 255.0D), Math.round(c.getBlue() * 255.0D)) : null; } private static ObjectBinding FOREGROUND_FILL; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index 2e29857250..5d0d684731 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -54,6 +54,7 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.animation.AnimationUtils; import org.jackhuang.hmcl.util.Holder; +import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.ResourceNotFoundError; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.FileUtils; @@ -83,6 +84,8 @@ import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import static org.jackhuang.hmcl.util.Lang.thread; @@ -94,6 +97,20 @@ public final class FXUtils { private FXUtils() { } + public static final int JAVAFX_MAJOR_VERSION; + + static { + String jfxVersion = System.getProperty("javafx.version"); + int majorVersion = -1; + if (jfxVersion != null) { + Matcher matcher = Pattern.compile("^(?[0-9]+)").matcher(jfxVersion); + if (matcher.find()) { + majorVersion = Lang.parseInt(matcher.group(), -1); + } + } + JAVAFX_MAJOR_VERSION = majorVersion; + } + public static final String DEFAULT_MONOSPACE_FONT = OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS ? "Consolas" : "Monospace"; private static final Map builtinImageCache = new ConcurrentHashMap<>(); diff --git a/HMCL/src/main/resources/assets/css/custom.css b/HMCL/src/main/resources/assets/css/custom.css deleted file mode 100644 index 72c29e9aca..0000000000 --- a/HMCL/src/main/resources/assets/css/custom.css +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -.root { - -fx-base-color: %base-color%; - -fx-base-darker-color: derive(-fx-base-color, -10%); - -fx-base-check-color: derive(-fx-base-color, 30%); - -fx-rippler-color: rgba(%base-red%, %base-green%, %base-blue%, 0.3); - -fx-base-rippler-color: derive(%base-rippler-color%, 100%); - -fx-base-disabled-text-fill: %disabled-font-color%; - -fx-base-text-fill: %font-color%; - - -theme-thumb: rgba(%base-red%, %base-green%, %base-blue%, 0.7); - - %font% -} \ No newline at end of file From 995d3bd4b9455744084c0333d0af9ee52672d4d6 Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 1 Nov 2024 20:59:33 +0800 Subject: [PATCH 090/169] =?UTF-8?q?=E4=B8=8D=E5=86=8D=E7=94=9F=E6=88=90=20?= =?UTF-8?q?bss=20=E6=96=87=E4=BB=B6=20(#3418)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/build.gradle.kts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/HMCL/build.gradle.kts b/HMCL/build.gradle.kts index 5c42b7814f..011620e2b0 100644 --- a/HMCL/build.gradle.kts +++ b/HMCL/build.gradle.kts @@ -167,24 +167,6 @@ fun createExecutable(suffix: String, header: String) { } tasks.processResources { - fun convertToBSS(resource: String) { - doFirst { - val cssFile = File(projectDir, "src/main/resources/$resource") - val bssFile = File(projectDir, "build/compiled-resources/${resource.substring(0, resource.length - 4)}.bss") - bssFile.parentFile.mkdirs() - javaexec { - classpath = sourceSets["main"].compileClasspath - mainClass.set("com.sun.javafx.css.parser.Css2Bin") - args(cssFile, bssFile) - } - } - } - - from("build/compiled-resources") - - convertToBSS("assets/css/root.css") - convertToBSS("assets/css/blue.css") - into("META-INF/versions/11") { from(sourceSets["java11"].output) } From 0697aa9755f314af31d8b0b0995fa56aa7748cfa Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 2 Nov 2024 01:05:52 +0800 Subject: [PATCH 091/169] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=E5=8C=85=20?= =?UTF-8?q?moe.mickey.minecraft.skin.fx=20(#3419)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/ui/account/OfflineAccountSkinPane.java | 6 +++--- .../jackhuang/hmcl/ui/skin}/FunctionHelper.java | 2 +- .../jackhuang/hmcl/ui/skin}/SkinAnimation.java | 2 +- .../jackhuang/hmcl/ui/skin}/SkinAnimationPlayer.java | 2 +- .../jackhuang/hmcl/ui/skin}/SkinCanvas.java | 2 +- .../fx => org/jackhuang/hmcl/ui/skin}/SkinCube.java | 2 +- .../fx => org/jackhuang/hmcl/ui/skin}/SkinGroup.java | 2 +- .../jackhuang/hmcl/ui/skin}/SkinHelper.java | 2 +- .../jackhuang/hmcl/ui/skin}/SkinMultipleCubes.java | 2 +- .../jackhuang/hmcl/ui/skin}/SkinTransition.java | 2 +- .../hmcl/ui/skin}/animation/SkinAniRunning.java | 10 +++++----- .../hmcl/ui/skin}/animation/SkinAniWavingArms.java | 10 +++++----- .../jackhuang/hmcl/ui/skin}/SkinCanvasSupport.java | 4 ++-- .../fx => org/jackhuang/hmcl/ui/skin}/test/Test.java | 12 ++++++------ 14 files changed, 30 insertions(+), 30 deletions(-) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/FunctionHelper.java (98%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/SkinAnimation.java (97%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/SkinAnimationPlayer.java (98%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/SkinCanvas.java (99%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/SkinCube.java (99%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/SkinGroup.java (96%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/SkinHelper.java (99%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/SkinMultipleCubes.java (99%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/SkinTransition.java (96%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/animation/SkinAniRunning.java (80%) rename HMCL/src/main/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/animation/SkinAniWavingArms.java (76%) rename HMCL/src/test/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/SkinCanvasSupport.java (98%) rename HMCL/src/test/java/{moe/mickey/minecraft/skin/fx => org/jackhuang/hmcl/ui/skin}/test/Test.java (76%) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/OfflineAccountSkinPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/OfflineAccountSkinPane.java index c143c60b99..73e940d137 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/OfflineAccountSkinPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/OfflineAccountSkinPane.java @@ -28,9 +28,9 @@ import javafx.scene.input.DragEvent; import javafx.scene.input.TransferMode; import javafx.scene.layout.*; -import moe.mickey.minecraft.skin.fx.SkinCanvas; -import moe.mickey.minecraft.skin.fx.animation.SkinAniRunning; -import moe.mickey.minecraft.skin.fx.animation.SkinAniWavingArms; +import org.jackhuang.hmcl.ui.skin.SkinCanvas; +import org.jackhuang.hmcl.ui.skin.animation.SkinAniRunning; +import org.jackhuang.hmcl.ui.skin.animation.SkinAniWavingArms; import org.jackhuang.hmcl.auth.offline.OfflineAccount; import org.jackhuang.hmcl.auth.offline.Skin; import org.jackhuang.hmcl.auth.yggdrasil.TextureModel; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/FunctionHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/FunctionHelper.java similarity index 98% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/FunctionHelper.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/FunctionHelper.java index 43e88bde57..7c8871f485 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/FunctionHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/FunctionHelper.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.event.Event; import javafx.event.EventHandler; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinAnimation.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinAnimation.java similarity index 97% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinAnimation.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinAnimation.java index f7f49b2340..2c8c9c6050 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinAnimation.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinAnimation.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.event.ActionEvent; import javafx.event.EventHandler; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinAnimationPlayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinAnimationPlayer.java similarity index 98% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinAnimationPlayer.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinAnimationPlayer.java index 683b478fac..8132566441 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinAnimationPlayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinAnimationPlayer.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.animation.AnimationTimer; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinCanvas.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCanvas.java similarity index 99% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinCanvas.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCanvas.java index 8faf860b23..5bf3cc4c1c 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinCanvas.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCanvas.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.scene.*; import javafx.scene.image.Image; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinCube.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java similarity index 99% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinCube.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java index 0929156c6e..d94bbd24d8 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinCube.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.scene.shape.Mesh; import javafx.scene.shape.MeshView; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinGroup.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinGroup.java similarity index 96% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinGroup.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinGroup.java index 70134e85af..5fcf2476fd 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinGroup.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinGroup.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.scene.Group; import javafx.scene.Node; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinHelper.java similarity index 99% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinHelper.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinHelper.java index 5125f3e0a7..e31ee03ea5 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinHelper.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.scene.image.Image; import javafx.scene.image.PixelReader; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinMultipleCubes.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java similarity index 99% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinMultipleCubes.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java index c8f3f128e6..4e9e1b4b19 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinMultipleCubes.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.geometry.Point2D; import javafx.scene.Group; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinTransition.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinTransition.java similarity index 96% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinTransition.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinTransition.java index ab6e9514d5..f1bbfd70ba 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/SkinTransition.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinTransition.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.animation.Transition; import javafx.beans.value.WritableValue; diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/animation/SkinAniRunning.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/animation/SkinAniRunning.java similarity index 80% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/animation/SkinAniRunning.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/animation/SkinAniRunning.java index 5a2b836937..c6fa30d516 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/animation/SkinAniRunning.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/animation/SkinAniRunning.java @@ -1,10 +1,10 @@ -package moe.mickey.minecraft.skin.fx.animation; +package org.jackhuang.hmcl.ui.skin.animation; import javafx.util.Duration; -import moe.mickey.minecraft.skin.fx.FunctionHelper; -import moe.mickey.minecraft.skin.fx.SkinAnimation; -import moe.mickey.minecraft.skin.fx.SkinCanvas; -import moe.mickey.minecraft.skin.fx.SkinTransition; +import org.jackhuang.hmcl.ui.skin.FunctionHelper; +import org.jackhuang.hmcl.ui.skin.SkinAnimation; +import org.jackhuang.hmcl.ui.skin.SkinCanvas; +import org.jackhuang.hmcl.ui.skin.SkinTransition; public final class SkinAniRunning extends SkinAnimation { diff --git a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/animation/SkinAniWavingArms.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/animation/SkinAniWavingArms.java similarity index 76% rename from HMCL/src/main/java/moe/mickey/minecraft/skin/fx/animation/SkinAniWavingArms.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/animation/SkinAniWavingArms.java index 46060216dd..0eabc7bb4e 100644 --- a/HMCL/src/main/java/moe/mickey/minecraft/skin/fx/animation/SkinAniWavingArms.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/animation/SkinAniWavingArms.java @@ -1,10 +1,10 @@ -package moe.mickey.minecraft.skin.fx.animation; +package org.jackhuang.hmcl.ui.skin.animation; import javafx.util.Duration; -import moe.mickey.minecraft.skin.fx.FunctionHelper; -import moe.mickey.minecraft.skin.fx.SkinAnimation; -import moe.mickey.minecraft.skin.fx.SkinCanvas; -import moe.mickey.minecraft.skin.fx.SkinTransition; +import org.jackhuang.hmcl.ui.skin.FunctionHelper; +import org.jackhuang.hmcl.ui.skin.SkinAnimation; +import org.jackhuang.hmcl.ui.skin.SkinCanvas; +import org.jackhuang.hmcl.ui.skin.SkinTransition; public final class SkinAniWavingArms extends SkinAnimation { diff --git a/HMCL/src/test/java/moe/mickey/minecraft/skin/fx/SkinCanvasSupport.java b/HMCL/src/test/java/org/jackhuang/hmcl/ui/skin/SkinCanvasSupport.java similarity index 98% rename from HMCL/src/test/java/moe/mickey/minecraft/skin/fx/SkinCanvasSupport.java rename to HMCL/src/test/java/org/jackhuang/hmcl/ui/skin/SkinCanvasSupport.java index 51f7826c52..51c00cab59 100644 --- a/HMCL/src/test/java/moe/mickey/minecraft/skin/fx/SkinCanvasSupport.java +++ b/HMCL/src/test/java/org/jackhuang/hmcl/ui/skin/SkinCanvasSupport.java @@ -1,4 +1,4 @@ -package moe.mickey.minecraft.skin.fx; +package org.jackhuang.hmcl.ui.skin; import javafx.application.Platform; import javafx.scene.Scene; @@ -8,7 +8,7 @@ import javafx.scene.input.ScrollEvent; import javafx.scene.input.TransferMode; import javafx.stage.Stage; -import moe.mickey.minecraft.skin.fx.test.Test; +import org.jackhuang.hmcl.ui.skin.test.Test; import java.io.File; import java.io.FileInputStream; diff --git a/HMCL/src/test/java/moe/mickey/minecraft/skin/fx/test/Test.java b/HMCL/src/test/java/org/jackhuang/hmcl/ui/skin/test/Test.java similarity index 76% rename from HMCL/src/test/java/moe/mickey/minecraft/skin/fx/test/Test.java rename to HMCL/src/test/java/org/jackhuang/hmcl/ui/skin/test/Test.java index f89d5b6aee..d311285bf4 100644 --- a/HMCL/src/test/java/moe/mickey/minecraft/skin/fx/test/Test.java +++ b/HMCL/src/test/java/org/jackhuang/hmcl/ui/skin/test/Test.java @@ -1,13 +1,13 @@ -package moe.mickey.minecraft.skin.fx.test; +package org.jackhuang.hmcl.ui.skin.test; import javafx.application.Application; import javafx.scene.Scene; import javafx.stage.Stage; -import moe.mickey.minecraft.skin.fx.FunctionHelper; -import moe.mickey.minecraft.skin.fx.SkinCanvas; -import moe.mickey.minecraft.skin.fx.SkinCanvasSupport; -import moe.mickey.minecraft.skin.fx.animation.SkinAniRunning; -import moe.mickey.minecraft.skin.fx.animation.SkinAniWavingArms; +import org.jackhuang.hmcl.ui.skin.FunctionHelper; +import org.jackhuang.hmcl.ui.skin.SkinCanvas; +import org.jackhuang.hmcl.ui.skin.SkinCanvasSupport; +import org.jackhuang.hmcl.ui.skin.animation.SkinAniRunning; +import org.jackhuang.hmcl.ui.skin.animation.SkinAniWavingArms; import org.jackhuang.hmcl.game.TexturesLoader; import java.util.function.Consumer; From aff5db7759c3e4a793224163975fc219ec891752 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 2 Nov 2024 02:27:54 +0800 Subject: [PATCH 092/169] Change the terminology `%AppData%` to `%APPDATA%` (#3420) --- HMCL/src/main/resources/assets/lang/I18N_es.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_ja.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_ru.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index e250a6bd31..d889c7287e 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -688,7 +688,7 @@ launcher.background.translucent=Translúcido launcher.cache_directory=Directorio de la caché launcher.cache_directory.clean=Borrar caché launcher.cache_directory.choose=Elegir el directorio de la caché -launcher.cache_directory.default=Por defecto (%AppData%/.minecraft o ~/.minecraft) +launcher.cache_directory.default=Por defecto (%APPDATA%/.minecraft o ~/.minecraft) launcher.cache_directory.disabled=Desactivado launcher.cache_directory.invalid=No se ha podido crear el directorio de la caché, volviendo a los valores por defecto. launcher.contact=Contacta con nosotros diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 2194eb81d2..d3daea14ce 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -541,7 +541,7 @@ launcher.background.translucent=半透明 launcher.cache_directory=キャッシュ用のディレクトリ launcher.cache_directory.clean=クリアランス launcher.cache_directory.choose=キャッシュするディレクトリを選択します -launcher.cache_directory.default=標準(%AppData%/.minecraft または ~/.minecraft) +launcher.cache_directory.default=標準(%APPDATA%/.minecraft または ~/.minecraft) launcher.cache_directory.disabled=無効(常にゲームパスを使用する) launcher.cache_directory.invalid=無効なディレクトリ。デフォルト設定の復元。 launcher.contact=お問い合わせ diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 2938888937..20d3c8f8c0 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -563,7 +563,7 @@ launcher.background.translucent=Полупрозрачный launcher.cache_directory=Папка с кэшем launcher.cache_directory.clean=Очистить кэш launcher.cache_directory.choose=Выберите папку для кэша -launcher.cache_directory.default=По умолчанию (%AppData%/.minecraft или ~/.minecraft) +launcher.cache_directory.default=По умолчанию (%APPDATA%/.minecraft или ~/.minecraft) launcher.cache_directory.disabled=Отключено launcher.cache_directory.invalid=Не удаётся создать папку для кэша, возвращаем к значению по умолчанию. launcher.contact=Связаться с нами diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 11938d23f9..030bcbf524 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -608,7 +608,7 @@ launcher.background.translucent=半透明 launcher.cache_directory=檔案下載快取目錄 launcher.cache_directory.clean=清理 launcher.cache_directory.choose=選取檔案下載快取目錄 -launcher.cache_directory.default=預設 ("%AppData%/.minecraft" 或 "~/.minecraft") +launcher.cache_directory.default=預設 ("%APPDATA%/.minecraft" 或 "~/.minecraft") launcher.cache_directory.disabled=停用 launcher.cache_directory.invalid=無法建立自訂的快取目錄,還原至預設設定 launcher.contact=聯絡我們 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 4de5ee6e5d..8354f852f2 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -619,7 +619,7 @@ launcher.background.translucent=半透明 launcher.cache_directory=文件下载缓存文件夹 launcher.cache_directory.clean=清理缓存 launcher.cache_directory.choose=选择文件下载缓存文件夹 -launcher.cache_directory.default=默认 ("%AppData%/.minecraft" 或 "~/.minecraft") +launcher.cache_directory.default=默认 ("%APPDATA%/.minecraft" 或 "~/.minecraft") launcher.cache_directory.disabled=禁用 (总是使用游戏文件夹路径) launcher.cache_directory.invalid=无法创建自定义的缓存文件夹,恢复默认设置 launcher.contact=联系我们 From 16d304dbb4f8b6acccf4c8c3d786dc501b32ad87 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 2 Nov 2024 17:36:20 +0800 Subject: [PATCH 093/169] en_US Post-fix (#3413) * en_US Post-fix Some minor fixes. * fix `game.crash.feedback` * oops... * oops... * Bunch of grammar fixes :/ * Another bunch fixes * Minor fixes * fix * fix * fix --- .../resources/assets/lang/I18N.properties | 299 +++++++++--------- 1 file changed, 151 insertions(+), 148 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 9e8364c102..43b6d4256f 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -29,10 +29,10 @@ about.claim.statement=Click this link for full text. about.dependency=Third-party Libraries about.legal=Legal Acknowledgement about.thanks_to=Thanks to -about.thanks_to.bangbang93.statement=For providing the BMCLAPI download mirror, please consider donating! +about.thanks_to.bangbang93.statement=For providing the BMCLAPI download mirror. Please consider donating! about.thanks_to.burningtnt.statement=Contribute a lot of technical support to HMCL. about.thanks_to.contributors=All contributors on GitHub -about.thanks_to.contributors.statement=Without the awesome open-source community, HMCL would not make it so far. +about.thanks_to.contributors.statement=Without the awesome open-source community, HMCL would not have made it so far. about.thanks_to.gamerteam.statement=For providing the default background image. about.thanks_to.glavo.statement=Responsible for maintaining HMCL. about.thanks_to.zekerzhayard.statement=Contribute a lot of technical support to HMCL. @@ -63,20 +63,20 @@ account.failed.character_deleted=The player has already been deleted. account.failed.connect_authentication_server=Unable to connect to the authentication server, your network connection may be down. account.failed.connect_injector_server=Unable to connect to the authentication server. Please check your network and make sure you entered the correct URL. account.failed.injector_download_failure=Unable to download the authlib-injector. Please check your network, or try switching to a different download source. -account.failed.invalid_credentials=Incorrect password or rate limited, please try again later. +account.failed.invalid_credentials=Incorrect password or rate limited. Please try again later. account.failed.invalid_password=Invalid password. account.failed.invalid_token=Please try logging in again. account.failed.migration=Your account needs to be migrated to a Microsoft account. If you already did, you should re-login to your migrated Microsoft account instead. account.failed.no_character=There are no characters linked to this account. account.failed.server_disconnected=Unable to connect to the authentication server. You can log in offline mode or try logging in again.\n\ If you try several times and still fail, please try adding the account again. -account.failed.server_response_malformed=Invalid server response, the authentication server may not be working. +account.failed.server_response_malformed=Invalid server response. The authentication server may not be working. account.failed.ssl=An SSL error occurred while connecting to the server. Please try updating your Java. account.failed.wrong_account=You have logged in to the wrong account. account.hmcl.hint=You need to click "Login" and complete the process in the opened browser window. account.injector.add=New Auth Server account.injector.empty=None (You can click "+" to add one) -account.injector.http=Warning: This server uses the unsafe HTTP protocol, anyone between your connection will be able to see your credentials in cleartext. +account.injector.http=Warning: This server uses the unsafe HTTP protocol. Anyone between your connections will be able to see your credentials in cleartext. account.injector.link.homepage=Homepage account.injector.link.register=Register account.injector.server=Authentication Server @@ -87,7 +87,7 @@ account.login.hint=We never store your password. account.login.skip=Login offline account.login.retry=Retry account.login.refresh=Re-login -account.login.refresh.microsoft.hint=You need to re-add your Microsoft account due to the account authorization is invalid. +account.login.refresh.microsoft.hint=You need to re-add your Microsoft account because the account authorization is invalid. account.logout=Logout account.register=Register account.manage=Account List @@ -100,7 +100,7 @@ account.methods.microsoft.close_page=Microsoft account authorization is now comp \n\ There are some extra works for us, but you can safely close this tab for now. account.methods.microsoft.deauthorize=Deauthorize -account.methods.microsoft.error.add_family=An adult must add you to a family in order for you to play Minecraft due to you are not yet 18 years old. +account.methods.microsoft.error.add_family=An adult must add you to a family in order for you to play Minecraft because you are not yet 18 years old. account.methods.microsoft.error.add_family_probably=Please check if the age indicated in your account settings is at least 18 years old. If not and you believe this is an error, you can click "How to Change Your Account Birthday" to learn how to change it. account.methods.microsoft.error.country_unavailable=Xbox Live is not available in your current country/region. account.methods.microsoft.error.missing_xbox_account=Your Microsoft account does not have a linked Xbox account yet. Please click "Create Profile / Edit Profile Name" to create one before continuing. @@ -111,7 +111,7 @@ account.methods.microsoft.logging_in=Logging in... account.methods.microsoft.hint=Please click "Login" and copy the code displayed here to complete the login process in the browser window that opens.\n\ \n\ If the token used to log in to the Microsoft account is leaked, you can click "Deauthorize" to deauthorize it. -account.methods.microsoft.manual=Your device code is %1$s, please click here to copy.\n\ +account.methods.microsoft.manual=Your device code is %1$s. Please click here to copy.\n\ \n\ After clicking "Login", you should complete the login process in the opened browser window. If it did not show, you can navigate to %2$s manually.\n\ \n\ @@ -122,8 +122,8 @@ account.methods.microsoft.purchase=Buy Minecraft account.methods.microsoft.snapshot=You are using an unofficial build of HMCL. Please download the official build for login. account.methods.microsoft.snapshot.website=Official Website account.methods.offline=Offline -account.methods.offline.name.special_characters=Recommended to use English letters, numbers and underscores -account.methods.offline.name.invalid=Generally, game usernames only allow English letters, numbers, and underscores, and cannot exceed 16 characters in length.\n\ +account.methods.offline.name.special_characters=Recommended to use English letters, numbers, and underscores +account.methods.offline.name.invalid=Generally, game usernames only allow English letters, numbers, and underscores and cannot exceed 16 characters in length.\n\ \n\ \ · Some legitimate usernames: HuangYu, huang_Yu, Huang_Yu_123;\n\ \ · Some illegal usernames: Huang Yu, Huang-Yu_%%%, Huang_Yu_hello_world_hello_world.\n\ @@ -137,7 +137,7 @@ account.methods.offline.uuid.malformed=Invalid format. account.methods.forgot_password=Forgot Password account.missing=No Accounts account.missing.add=Click here to add one. -account.move_to_global=Convert to Global Account\nThe account information will be saved in a config file of the user directory. +account.move_to_global=Convert to Global Account\nThe account information will be saved in a config file of the current user directory of the system. account.move_to_portable=Convert to Portable Account\nThe account information will be saved in a config file in the same directory as HMCL. account.not_logged_in=Not Logged in account.password=Password @@ -253,7 +253,7 @@ curse.category.430=Thaumcraft curse.category.422=Adventure and RPG curse.category.413=Processing curse.category.417=Energy -curse.category.415=Energy, Fluid and Item Transport +curse.category.415=Energy, Fluid, and Item Transport curse.category.433=Forestry curse.category.425=Miscellaneous curse.category.4545=Applied Energistics 2 @@ -320,14 +320,14 @@ curse.sort.popularity=Popularity curse.sort.total_downloads=Total Downloads download=Download -download.hint=Install games and modpacks or download mods, resource packs and worlds. +download.hint=Install games and modpacks or download mods, resource packs, and worlds. download.code.404=File not found on the remote server: %s download.content=Addons -download.curseforge.unavailable=HMCL Nightly channel build does not support access to CurseForge, please use Release or Beta channel builds to download. -download.existing=The file cannot be saved due to it already exists. You can click "Save As" to save the file elsewhere. +download.curseforge.unavailable=HMCL Nightly channel build does not support access to CurseForge. Please use Release or Beta channel builds to download. +download.existing=The file cannot be saved because it already exists. You can click "Save As" to save the file elsewhere. download.external_link=Visit Download Website download.failed=Failed to download "%1$s", response code: %2$d. -download.failed.empty=No versions are available, please click here to go back. +download.failed.empty=No versions are available. Please click here to go back. download.failed.no_code=Failed to download "%s". download.failed.refresh=Unable to fetch version list. Please click here to retry. download.game=New Game @@ -337,43 +337,46 @@ download.provider.official=From Official Sources download.provider.balanced=From Fastest Available download.provider.mirror=From Mirror download.java=Downloading Java -download.java.override=This Java version already exists, do you want to uninstall and reinstall it? +download.java.override=This Java version already exists. Do you want to uninstall and reinstall it? download.javafx=Downloading dependencies for the launcher... download.javafx.notes=We are currently downloading dependencies for HMCL from the Internet.\n\ \n\ - You can click "Change Download Source" to choose download source or\nclick "Cancel" to stop and exit.\n\ + You can click "Change Download Source" to choose the download source, or\nclick "Cancel" to stop and exit.\n\ Note: If your download speed is too slow, you can try switching to another mirror. download.javafx.component=Downloading module "%s" download.javafx.prepare=Preparing to download -exception.access_denied=HMCL is unable to access the file "%s", it may be locked by another process.\n\ + +exception.access_denied=HMCL is unable to access the file "%s". It may be locked by another process.\n\ \n\ For Windows users, you can open "Resource Monitor" to check if another process is currently using it. If so, you can try again after closing that process.\n\ If not, please check if your account has enough permissions to access it. exception.artifact_malformed=Cannot verify the integrity of the downloaded files. -exception.ssl_handshake=Unable to establish SSL connection due to missing SSL certificates in current Java installation. You can try opening HMCL in another Java, then try again. +exception.ssl_handshake=Unable to establish an SSL connection due to the lack of an SSL certificate in the current Java installation. You can try opening HMCL in another Java and try again. + extension.bat=Windows Batch File (.bat) extension.mod=Mod File extension.png=Image File extension.ps1=Windows PowerShell Script (.ps1) extension.sh=Shell Script (.sh) + fatal.javafx.incompatible=Missing JavaFX environment.\n\ Hello Minecraft! Launcher cannot automatically install JavaFX on Java <11.\n\ Please update your Java to version 11 or later. fatal.javafx.incomplete=The JavaFX environment is incomplete.\n\ Please try replacing your Java or reinstalling OpenJFX. -fatal.javafx.missing=Missing JavaFX environment. Please open Hello Minecraft! Launcher with a Java which includes OpenJFX. -fatal.config_change_owner_root=You are using the root account to open Hello Minecraft! Launcher, this may cause you to fail to open HMCL with other account in the future.\n\ +fatal.javafx.missing=Missing JavaFX environment. Please open Hello Minecraft! Launcher with Java, which includes OpenJFX. +fatal.config_change_owner_root=You are using the root account to open Hello Minecraft! Launcher. This may cause you to fail to open HMCL with another account in the future.\n\ Do you still want to continue? -fatal.config_in_temp_dir=You are opening Hello Minecraft! Launcher in a temporary directory, your settings and game data may be lost.\n\ +fatal.config_in_temp_dir=You are opening Hello Minecraft! Launcher in a temporary directory. Your settings and game data may be lost.\n\ It is recommended to move HMCL to another location and reopen it.\n\ Do you still want to continue? fatal.config_loading_failure=Cannot load configuration files.\n\ Please make sure that Hello Minecraft! Launcher has read and write access to "%s" and the files in it.\n\ - For macOS, try putting HMCL somewhere with permissions other than "Desktop", "Downloads" and "Documents" and try again. -fatal.config_loading_failure.unix=Hello Minecraft! Launcher could not load the profile due to it was created by user %1$s.\n\ + For macOS, try putting HMCL somewhere with permissions other than "Desktop", "Downloads", and "Documents" and try again. +fatal.config_loading_failure.unix=Hello Minecraft! Launcher could not load the configuration file because it was created by user "%1$s".\n\ Please open HMCL as root user (not recommended), or execute the following command in the terminal to change the ownership of the configuration file to the current user:\n%2$s fatal.mac_app_translocation=Due to macOS security mechanisms, Hello Minecraft! Launcher is isolated to a temporary directory by the OS.\n\ - Please move HMCL to a different directory before attempting to open, otherwise your settings and game data may be lost after restarting.\n\ + Please move HMCL to a different directory before attempting to open. Otherwise, your settings and game data may be lost after restarting.\n\ Do you still want to continue? fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher has been upgraded. Please restart the launcher. fatal.apply_update_failure=We are sorry, but Hello Minecraft! Launcher is unable to update automatically.\n\ @@ -383,19 +386,19 @@ fatal.apply_update_failure=We are sorry, but Hello Minecraft! Launcher is unable fatal.apply_update_need_win7=Hello Minecraft! Launcher cannot automatically update on Windows XP/Vista.\n\ \n\ You can update manually by downloading a newer launcher version from %s. -fatal.samba=If you opened Hello Minecraft! Launcher from a Samba network drive, some features might not be working. Please try updating your Java or copy and open the launcher in a local directory. -fatal.illegal_char=Your user path contains an illegal character "=", you will not be able to use authlib-injector or change the skin of your offline account. -fatal.unsupported_platform=Minecraft is not yet fully supported for your platform, so you may experience missing functionality, or even be unable to launch the game.\n\ +fatal.samba=If you opened Hello Minecraft! Launcher from a Samba network drive, some features might not be working. Please try updating your Java or moving the launcher to another directory. +fatal.illegal_char=Your user path contains an illegal character "=". You will not be able to use authlib-injector or change the skin of your offline account. +fatal.unsupported_platform=Minecraft is not yet fully supported for your platform, so you may experience missing functionality or even be unable to launch the game.\n\ \n\ If you cannot launch Minecraft 1.17 and later, you can try switching the "Renderer" to "Software" in "Global/Instance-specific Settings → Advanced Settings" to use CPU rendering for better compatibility. -fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher has provided support for Loongson platform.\n\ - If you encounter problems when playing game, you can visit https://docs.hmcl.net/groups.html for help. -fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher has provided support for Apple silicon platform, using native ARM java to launch games to get a smoother game experience.\n\ - If you encounter problems when playing game, launching the game with Java based on x86-64 architecture may have better compatibility. -fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher has provided native support for the Windows on Arm platform. If you encounter problems when playing game, please try launching the game with Java based on x86 architecture.\n\ +fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher has provided support for the Loongson platform.\n\ + If you encounter problems when playing a game, you can visit https://docs.hmcl.net/groups.html for help. +fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher has provided support for the Apple silicon platform, using native ARM Java to launch games to get a smoother game experience.\n\ + If you encounter problems when playing a game, launching the game with Java based on x86-64 architecture may have better compatibility. +fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher has provided native support for the Windows on Arm platform. If you encounter problems when playing a game, please try launching the game with Java based on x86 architecture.\n\ \n\ If you are using the Qualcomm platform, you may need to install the OpenGL Compatibility Pack before playing games.\n\ - Click the link to navigate to Microsoft Store and install the compatibility pack. + Click the link to navigate to the Microsoft Store and install the compatibility pack. feedback=Feedback feedback.channel=Feedback Channel @@ -418,14 +421,14 @@ folder.saves=Saves folder.screenshots=Screenshots game=Games -game.crash.feedback=Please do not share screenshots of this interface with others! If you ask for help from others, please click to export the game crash information in the lower left corner and send the exported file to others for analysis. +game.crash.feedback=Please do not share screenshots of this interface with others! If you ask for help from others, please click "Export Crash Logs" and send the exported file to others for analysis. game.crash.info=Crash Info game.crash.reason=Crash Cause game.crash.reason.analyzing=Analyzing... game.crash.reason.multiple=Several reasons detected:\n\n -game.crash.reason.block=The game crashed due to a block in world.\n\ +game.crash.reason.block=The game crashed due to a block in the world.\n\ \n\ - You can try removing this block using MCEdit or delete that mod that added it.\n\ + You can try removing this block using MCEdit or deleting the mod that added it.\n\ \n\ Block Type: %1$s\n\ Location: %2$s @@ -433,26 +436,26 @@ game.crash.reason.bootstrap_failed=The game crashed due to mod "%1$s".\n\ \n\ You can try deleting or updating it. game.crash.reason.config=The game crashed due to a mod "%1$s" cannot parse its config file "%2$s". -game.crash.reason.debug_crash=The game crashed due to you manually triggered it. So, you probably know why. +game.crash.reason.debug_crash=The game crashed due to you triggering it manually. So you probably know why. game.crash.reason.duplicated_mod=The game cannot continue to run due to duplicate mods "%1$s".\n\ \n\ %2$s\n\ \n\ - Each mod can only be installed once, please delete the duplicate mod and try again. -game.crash.reason.entity=The game crashed due to an entity in world.\n\ + Each mod can only be installed once. Please delete the duplicate mod and try again. +game.crash.reason.entity=The game crashed due to an entity in the world.\n\ \n\ - You can try removing this entity using MCEdit or delete that mod that added it.\n\ + You can try removing the entity using MCEdit or deleting the mod that added it.\n\ \n\ Entity Type: %1$s\n\ Location: %2$s -game.crash.reason.modmixin_failure=The game crashed due to some mod injection failed.\n\ +game.crash.reason.modmixin_failure=The game crashed due to some mod injection failure.\n\ \n\ This generally means that the mod has a bug or is incompatible with the current environment.\n\ \n\ You can check the log to find the error mod. game.crash.reason.mod_repeat_installation=The game crashed due to duplicate mods.\n\ \n\ - Each mod can only be installed once, please delete the duplicate mod and then relaunch the game. + Each mod can only be installed once. Please delete the duplicate mod and then relaunch the game. game.crash.reason.forge_error=Forge/NeoForge may have provided error information.\n\ \n\ You can view the log and make corresponding processing according to the log information in the error report.\n\ @@ -460,12 +463,12 @@ game.crash.reason.forge_error=Forge/NeoForge may have provided error information If you do not see the error message, you can view the error report to understand how the error occurred.\n\ %1$s game.crash.reason.mod_resolution0=The game crashed due to some mod problems. You can check the log to find the error mod(s). -game.crash.reason.mixin_apply_mod_failed=The game crashed due to mixin failed to apply the "%1$s" mod.\n\ +game.crash.reason.mixin_apply_mod_failed=The game crashed due to the mixin could not be applied to the "%1$s" mod.\n\ \n\ You can try deleting or updating the mod to resolve the problem. -game.crash.reason.java_version_is_too_high=The game crashed due to the Java version is too high to continue running.\n\ +game.crash.reason.java_version_is_too_high=The game crashed due to the Java version being too high to continue running.\n\ \n\ - Please use an older Java version in "Global/Instance-specific Settings → Java", and then launch the game.\n\ + Please use an earlier Java version in "Global/Instance-specific Settings → Java" and then launch the game.\n\ \n\ If not, you can download it from java.com (Java 8) or BellSoft Liberica Full JRE (Java 17) and other distributions to download and install one (restart the launcher after installation). game.crash.reason.need_jdk11=The game crashed due to an inappropriate Java VM version.\n\ @@ -479,27 +482,27 @@ game.crash.reason.mod_name=The game crashed due to mod file name problems.\n\ game.crash.reason.incomplete_forge_installation=The game cannot continue to run due to an incomplete installation of Forge/NeoForge.\n\ \n\ Please reinstall Forge/NeoForge in "Edit Instance → Loaders". -game.crash.reason.fabric_version_0_12=Fabric Loader 0.12 or later are incompatible with currently installed mods. You need to downgrade it to 0.11.7. +game.crash.reason.fabric_version_0_12=Fabric Loader 0.12 or later is incompatible with currently installed mods. You need to downgrade it to 0.11.7. game.crash.reason.fabric_warnings=The Fabric warned:\n\ \n\ %1$s game.crash.reason.file_already_exists=The game crashed due to file "%1$s" already exists.\n\ \n\ - You can try backing up and delete that file, then relaunch the game. + You can try backing up and deleting that file, then relaunching the game. game.crash.reason.file_changed=The game crashed due to file "%1$s" already exists.\n\ \n\ - You can try backing up and delete that file, then relaunch the game. + You can try backing up and deleting that file, then relaunching the game. game.crash.reason.gl_operation_failure=The game crashed due to some mods, shaders, or resource packs.\n\ \n\ - Please disable the mods, shaders or resource packs you are using and then try again. -game.crash.reason.graphics_driver=The game crashed due to an problem with your graphics driver.\n\ + Please disable the mods, shaders, or resource packs you are using and then try again. +game.crash.reason.graphics_driver=The game crashed due to a problem with your graphics driver.\n\ \n\ Please try again after updating your graphics driver to the latest version.\n\ \n\ If your PC has a discrete graphics card, you need to check whether the game uses integrated/core graphics. If so, please open the launcher using your discrete graphics card. If the problem persists, you probably should consider using a new graphics card or a new PC.\n\ \n\ - If you are using your integrated graphics card, please notice that Minecraft 1.16.5 or older requires Java 1.8.0_51 or older for Intel(R) Core(TM) 3000 processor series or earlier. -game.crash.reason.macos_failed_to_find_service_port_for_display=The current game cannot continue due to a failure to initialize the OpenGL window on the Apple silicon platform.\n\ + If you are using your integrated graphics card, please notice that Minecraft 1.16.5 or earlier requires Java 1.8.0_51 or earlier for Intel(R) Core(TM) 3000 processor series or earlier. +game.crash.reason.macos_failed_to_find_service_port_for_display=The game cannot continue due to a failure to initialize the OpenGL window on the Apple silicon platform.\n\ \n\ For this problem, HMCL does not have direct solutions at the moment. Please try opening any browser and going fullscreen, then return to HMCL, launch the game, and quickly return to the browser page before the game window pops up, wait for the game window to appear, and then switch back to the game window. game.crash.reason.illegal_access_error=The game crashed due to some mod(s).\n\ @@ -507,49 +510,49 @@ game.crash.reason.illegal_access_error=The game crashed due to some mod(s).\n\ If you know this: "%1$s", you can update or delete the mod(s) and then try again. game.crash.reason.install_mixinbootstrap=The game crashed due to missing MixinBootstrap.\n\ \n\ - You can try installing MixinBootstrap to resolve the problem. If it crashes after installation, try adding an exclamation mark (!) in front of the file name of this mod. in front of the file name of the mod to try to resolve the problem. + You can try installing MixinBootstrap to resolve the problem. If it crashes after installation, try adding an exclamation mark (!) in front of the file name of this mod to try to resolve the problem. game.crash.reason.optifine_is_not_compatible_with_forge=The game crashes due to OptiFine being incompatible with the currently installed Forge.\n\ \n\ Please navigate tothe official website of OptiFine, check whether the Forge version is compatible with OptiFine, and reinstall the instance in strict accordance with the corresponding version, or change the OptiFine version in "Edit Instance → Loaders".\n\ \n\ After testing, we believe that too high or too low OptiFine versions may cause crashes. -game.crash.reason.mod_files_are_decompressed=The game crashed due to the mod file has been extracted.\n\ +game.crash.reason.mod_files_are_decompressed=The game crashed due to the mod file having been extracted.\n\ \n\ Please put the entire mod file directly into the mod directory!\n\ \n\ - If extract will cause errors in the game, please delete the extracted mod in the mod directory, and then launch the game. -game.crash.reason.shaders_mod=The game crashed due to both OptiFine and Shaders mod are installed.\n\ + If extract will cause errors in the game, please delete the extracted mod in the mod directory and then launch the game. +game.crash.reason.shaders_mod=The game crashed due to both OptiFine and Shaders mods being installed.\n\ \n\ - Just remove Shaders mod due to OptiFine has built-in support for shaders. -game.crash.reason.rtss_forest_sodium=The game crashed due to RivaTuner Statistics Server (RTSS) is incompatible with Sodium.\n\ + Just remove Shaders mod due to OptiFine having built-in support for shaders. +game.crash.reason.rtss_forest_sodium=The game crashed due to RivaTuner Statistics Server (RTSS) being incompatible with Sodium.\n\ \n\ Click here for more details. -game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=The game crashed due to you have installed too many mods, which exceeds the ID limit of the game.\n\ +game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=The game crashed due to you having installed too many mods, which exceeds the ID limit of the game.\n\ \n\ - Please try installingJEID, or delete some large mods. + Please try installingJEID or deleting some large mods. game.crash.reason.night_config_fixes=The game crashed due to some problems with Night Config.\n\ \n\ - You can try to install the Night Config Fixes mod, which may help you this problem.\n\ + You can try installing the Night Config Fixes mod, which may help you with this problem.\n\ \n\ For more information, visit the GitHub repository of this mod. game.crash.reason.optifine_causes_the_world_to_fail_to_load=The game may not continue to run due to OptiFine.\n\ \n\ - This problem only occurs in a specific OptiFine version. You can try changing OptiFine version in "Edit Instance → Loaders". -game.crash.reason.jdk_9=The game crashed due to the Java version is too new for this instance.\n\ + This problem only occurs in a specific OptiFine version. You can try changing the OptiFine version in "Edit Instance → Loaders". +game.crash.reason.jdk_9=The game crashed due to the Java version being too new for this instance.\n\ \n\ You need to download and install Java 8 and choose it in "Global/Instance-specific Settings → Java". -game.crash.reason.jvm_32bit=The game crashed due to the current memory allocation exceeds the limit of the 32-bit Java VM.\n\ +game.crash.reason.jvm_32bit=The game crashed due to the current memory allocation exceeding the limit of the 32-bit Java VM.\n\ \n\ If your OS is 64-bit, please install and use a 64-bit Java version. Otherwise, you may need to reinstall a 64-bit OS or get a moderner PC.\n\ \n\ - Or, you can disable the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory", and set the maximum memory allocation size to 1024 MB or below. + Or, you can disable the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory" and set the maximum memory allocation size to 1024 MB or below. game.crash.reason.loading_crashed_forge=The game crashed due to mod "%1$s" (%2$s).\n\ \n\ You can try deleting or updating it. game.crash.reason.loading_crashed_fabric=The game crashed due to mod "%1$s".\n\ \n\ You can try deleting or updating it. -game.crash.reason.mac_jdk_8u261=The game crashed due to your current Forge or OptiFine version is not compatible with your Java installation.\n\ +game.crash.reason.mac_jdk_8u261=The game crashed due to your current Forge or OptiFine version not being compatible with your Java installation.\n\ \n\ Please try updating Forge and OptiFine, or try using Java 8u251 or earlier versions. game.crash.reason.forge_repeat_installation=The game crashed due to a duplicate installation of Forge. This is a known problem\n\ @@ -562,24 +565,24 @@ game.crash.reason.optifine_repeat_installation=The game crashed due to repeated Please delete OptiFine in the mod directory or uninstall it in "Edit Instance → Loaders". game.crash.reason.memory_exceeded=The game crashed due to too much memory allocated for a small page file.\n\ \n\ - You can try disable the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory", and adjust the value till the game launches.\n\ + You can try disabling the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory" and adjust the value till the game launches.\n\ \n\ You can also try increasing the page file size in system settings. game.crash.reason.mod=The game crashed due to the mod "%1$s".\n\ \n\ You may update or delete the mod and then try again. -game.crash.reason.mod_resolution=The game crashed due to mod resolution failure.\n\ +game.crash.reason.mod_resolution=The game cannot continue to run due to mod dependency problems.\n\ \n\ Fabric provided the following details:\n\ \n\ %1$s -game.crash.reason.forgemod_resolution=The game crashed due to mod resolution failure.\n\ +game.crash.reason.forgemod_resolution=The game cannot continue to run due to mod dependency problems.\n\ \n\ Forge/NeoForge provided the following details:\n\ %1$s game.crash.reason.forge_found_duplicate_mods=The game crashed due to a duplicate mods problem. Forge/NeoForge provides the following information:\n\ %1$s -game.crash.reason.mod_resolution_collection=The game crashed due to the mod version is not compatible.\n\ +game.crash.reason.mod_resolution_collection=The game crashed because the mod version is not compatible.\n\ \n\ "%1$s" requires "%2$s".\n\ \n\ @@ -587,12 +590,12 @@ game.crash.reason.mod_resolution_collection=The game crashed due to the mod vers game.crash.reason.mod_resolution_conflict=The game crashed due to conflicting mods.\n\ \n\ "%1$s" is incompatible with "%2$s". -game.crash.reason.mod_resolution_missing=The game crashed due to some dependency mods are not installed.\n\ +game.crash.reason.mod_resolution_missing=The game crashed due to some dependency mods not being installed.\n\ \n\ "%1$s" requires mod "%2$s".\n\ \n\ This means that you have to download and install "%2$s" first to continue playing. -game.crash.reason.mod_resolution_missing_minecraft=The game crashed due to a mod is incompatible with the current Minecraft version.\n\ +game.crash.reason.mod_resolution_missing_minecraft=The game crashed due to a mod being incompatible with the current Minecraft version.\n\ \n\ "%1$s" requires Minecraft version %2$s.\n\ \n\ @@ -601,10 +604,10 @@ game.crash.reason.mod_resolution_missing_minecraft=The game crashed due to a mod Otherwise, you should install a version that is compatible with this Minecraft version. game.crash.reason.mod_resolution_mod_version=%1$s (Version: %2$s) game.crash.reason.mod_resolution_mod_version.any=%1$s (Any Version) -game.crash.reason.modlauncher_8=The game crashed due to your current Forge version is not compatible with your Java installation, please try updating Forge. +game.crash.reason.modlauncher_8=The game crashed due to your current Forge version not being compatible with your Java installation. Please try updating Forge. game.crash.reason.no_class_def_found_error=The game cannot continue to run due to incomplete code.\n\ \n\ - Your game instance is missing %1$s, this might be due to a mod missing, an incompatible mod installed, or some files might be corrupted.\n\ + Your game instance is missing %1$s. This might be due to a mod missing, an incompatible mod installed, or some files being corrupted.\n\ \n\ You may need to reinstall the game and all mods or ask someone for help. game.crash.reason.no_such_method_error=The game cannot continue to run due to incomplete code.\n\ @@ -612,38 +615,38 @@ game.crash.reason.no_such_method_error=The game cannot continue to run due to in Your game instance might be missing a mod, installed an incompatible mod, or some files might be corrupted.\n\ \n\ You may need to reinstall the game and all mods or ask someone for help. -game.crash.reason.opengl_not_supported=The game crashed due to OpenGL is not supported by your graphics driver.\n\ +game.crash.reason.opengl_not_supported=The game crashed due to OpenGL not being supported by your graphics driver.\n\ \n\ If you are streaming the game over the Internet or using a remote desktop environment, please play the game on your local one.\n\ \n\ Or, you can try updating your driver to the latest version and then try again.\n\ \n\ If your PC has a discrete graphics card, please make sure the game is actually using it for rendering. If the problem persists, please consider getting a new graphics card or a new PC. -game.crash.reason.openj9=The game is unable to run on an OpenJ9 VM. Please switch to a Java that uses the Hotspot VM in "Global/Instance-specific Settings → Java" and relaunch the game. If do not have one, you can download one online. -game.crash.reason.out_of_memory=The game crashed due to it ran out of memory.\n\ +game.crash.reason.openj9=The game is unable to run on an OpenJ9 VM. Please switch to a Java that uses the Hotspot VM in "Global/Instance-specific Settings → Java" and relaunch the game. If you do not have one, you can download one online. +game.crash.reason.out_of_memory=The game crashed due to it running out of memory.\n\ \n\ - Maybe because there is not enough memory available, or too many mods installed. You can try resolving it by increasing the allocated memory in "Global/Instance-specific Settings → Memory".\n\ + Maybe because there is not enough memory available or too many mods installed. You can try resolving it by increasing the allocated memory in "Global/Instance-specific Settings → Memory".\n\ \n\ If you still encounter these problems, you may need a better PC. game.crash.reason.resolution_too_high=The game crashed due to the resource pack resolution being too high.\n\ \n\ - You should switch to a resource pack with lower resolution, or consider buying a better graphics card with more VRAM. + You should switch to a resource pack with lower resolution or consider buying a better graphics card with more VRAM. game.crash.reason.stacktrace=The crash reason is unknown. You can view its details by clicking "Logs".\n\ \n\ There are some keywords that might contain some mod names. You can search them online to figure out the problem yourself.\n\ \n\ %s -game.crash.reason.too_old_java=The game crashed due to you are using an outdated Java VM version.\n\ +game.crash.reason.too_old_java=The game crashed due to you using an outdated Java VM version.\n\ \n\ You need to switch to a newer version (%1$s) of Java in "Global/Instance-specific Settings → Java" and then relaunch the game. You can download Java from here. -game.crash.reason.unknown=We are not able to figure out why the game crashed, please refer to the game logs. +game.crash.reason.unknown=We are not able to figure out why the game crashed. Please refer to the game logs. game.crash.reason.unsatisfied_link_error=Unable to launch Minecraft due to missing libraries: %1$s.\n\ \n\ - If you have edited native library path, please make sure these libraries do exist. Or, please try launching again after reverting it to default.\n\ + If you have edited the native library path, please make sure these libraries do exist. Or, please try launching again after reverting it to default.\n\ \n\ If you did not, please check if you have missing dependency mods.\n\ \n\ - Otherwise, if you believe this is caused by HMCL, please feedback to us. + Otherwise, if you believe this is caused by HMCL, please provide feedback to us. game.crash.title=Game Crashed game.directory=Game Path game.version=Game Version @@ -667,24 +670,24 @@ install.failed.downloading.timeout=Download timeout when fetching: %s install.failed.install_online=Unable to identify the provided file. If you are installing a mod, navigate to the "Mods" page. install.failed.malformed=The downloaded files are corrupted. You can try resolving this problem by switching to another download source in "Settings → Download → Download Source". install.failed.optifine_conflict=Cannot install both OptiFine and Fabric on Minecraft 1.13 or later. -install.failed.optifine_forge_1.17=For Minecraft 1.17.1, Forge only compatible with OptiFine H1 pre2 or later. You can install them by checking "Snapshots" when choosing an OptiFine version in HMCL. +install.failed.optifine_forge_1.17=For Minecraft 1.17.1, Forge is only compatible with OptiFine H1 pre2 or later. You can install them by checking "Snapshots" when choosing an OptiFine version in HMCL. install.failed.version_mismatch=This loader requires the game version %s, but the installed one is %s. install.installer.change_version=%s Incompatible install.installer.choose=Choose Your %s Version install.installer.depend=Requires %s install.installer.fabric=Fabric install.installer.fabric-api=Fabric API -install.installer.fabric-api.warning=Warning: Fabric API is a mod, and will be installed into the mod directory of the game instance. Please do not change the working directory of the game, or the Fabric API will not work. If you do want to change these settings, you should reinstall it. +install.installer.fabric-api.warning=Warning: Fabric API is a mod and will be installed into the mod directory of the game instance. Please do not change the working directory of the game, or the Fabric API will not work. If you do want to change these settings, you should reinstall it. install.installer.forge=Forge install.installer.neoforge=NeoForge install.installer.game=Minecraft install.installer.incompatible=Incompatible with %s install.installer.install=Install %s -install.installer.install_offline=Install/Update From Local File +install.installer.install_offline=Install/Update from Local File install.installer.install_offline.extension=(Neo)Forge/OptiFine installer install.installer.install_offline.tooltip=We support using the local (Neo)Forge/OptiFine installer. install.installer.install_online=Online Install -install.installer.install_online.tooltip=We currently support Forge, NeoForge, OptiFine, Fabric, Quilt and LiteLoader. +install.installer.install_online.tooltip=We currently support Forge, NeoForge, OptiFine, Fabric, Quilt, and LiteLoader. install.installer.liteloader=LiteLoader install.installer.not_installed=Do not install install.installer.optifine=OptiFine @@ -733,30 +736,30 @@ java.uninstall.confirm=Are you sure you want to uninstall this Java? This action lang=English lang.default=Use System Locales 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 cause unable to launch the game or affect the game experience.\nDo you still want to continue to launch? -launch.advice.java.auto=The current Java VM version does not compatible with the instance.\n\nClick "Yes" to automatically choose the most compatible Java VM 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 older versions require Java 7 or earlier. +launch.advice.multi=The following problems were detected:\n\n%s\n\nThese problems may cause you to be unable to launch the game or affect the game experience. \nDo you still want to continue to launch? +launch.advice.java.auto=The current Java VM version is not compatible with the instance.\n\nClick "Yes" to automatically choose the most compatible Java VM 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 earlier versions require Java 7 or earlier. launch.advice.corrected=We have resolved the Java VM problem. If you still want to use your choice of Java version, you can disable the "Do not check Java VM 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 the "Do not check Java VM 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. -launch.advice.forge2760_liteloader=Forge version 2760 is not compatible with LiteLoader, please consider upgrading Forge to version 2773 or later. +launch.advice.forge2760_liteloader=Forge version 2760 is not compatible with LiteLoader. Please consider upgrading Forge to version 2773 or later. launch.advice.forge28_2_2_optifine=Forge version 28.2.2 or later is not compatible with OptiFine. Please consider downgrading Forge to version 28.2.1 or earlier. launch.advice.forge37_0_60=Forge versions earlier than 37.0.60 are not compatible with Java 17. Please update Forge to 37.0.60 or later, or launch the game with Java 16. launch.advice.java8_1_13=Minecraft 1.13 and later can only be run on Java 8 or later. Please use Java 8 or later versions. launch.advice.java8_51_1_13=Minecraft 1.13 may crash on Java 8 versions earlier than 1.8.0_51. Please install the latest Java 8 version. -launch.advice.java9=You cannot launch Minecraft 1.12 or earlier with Java 9 or later, please use Java 8 instead. +launch.advice.java9=You cannot launch Minecraft 1.12 or earlier with Java 9 or later. Please use Java 8 instead. launch.advice.modded_java=Some mods may not be compatible with newer versions of Java. It is recommended to use Java %s to launch Minecraft %s. -launch.advice.modlauncher8=The Forge version you are using is not compatible with the current Java version, please try updating Forge. +launch.advice.modlauncher8=The Forge version you are using is not compatible with the current Java version. Please try updating Forge. launch.advice.newer_java=You are using the old Java to launch the game. It is recommended to update to Java 8, otherwise some mods may cause the game to crash. -launch.advice.not_enough_space=You have allocated a memory size larger than the actual %d MB of memory installed on your PC. You may experience degraded performance, or even be unable to launch the game. -launch.advice.require_newer_java_version=Current game version requires Java %s, but we could not find one. Do you want to download one now? +launch.advice.not_enough_space=You have allocated a memory size larger than the actual %d MB of memory installed on your PC. You may experience degraded performance or even be unable to launch the game. +launch.advice.require_newer_java_version=The current game version requires Java %s, but we could not find one. Do you want to download one now? launch.advice.too_large_memory_for_32bit=You have allocated a memory size larger than the memory limitation of the 32-bit Java installation. You may be unable to launch the game. -launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 or before only supports Java 8 for the Linux x86-64 platform, due to the later versions cannot load 32-bit native libraries like liblwjgl.so\n\nPlease download it from java.com, or install OpenJDK 8. -launch.advice.vanilla_x86.translation=Minecraft is not fully supported for your platform, so you may experience missing functionality, or even be unable to launch the game.\nYou can download Java for the x86-64 architecture here for a full gaming experience. +launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 or earlier only supports Java 8 for the Linux x86-64 platform because the later versions cannot load 32-bit native libraries like liblwjgl.so\n\nPlease download it from java.com or install OpenJDK 8. +launch.advice.vanilla_x86.translation=Minecraft is not fully supported for your platform, so you may experience missing functionality or even be unable to launch the game.\nYou can download Java for the x86-64 architecture here for a full gaming experience. launch.advice.unknown=The game cannot be launched due to the following reasons: launch.failed=Failed to launch launch.failed.cannot_create_jvm=We are unable to create a Java VM. It may be caused by incorrect Java VM arguments. You can try resolving it by removing all arguments you added in "Global/Instance-specific Settings → Advanced Settings → Java VM Options". -launch.failed.creating_process=We are unable to create a new process, please check your Java path.\n +launch.failed.creating_process=We are unable to create a new process. Please check your Java path.\n launch.failed.command_too_long=The command length exceeds the maximum length of a bat script. Please try exporting it as a PowerShell script. launch.failed.decompressing_natives=Unable to extract native libraries.\n launch.failed.download_library=Unable to download libraries "%s". @@ -765,7 +768,7 @@ launch.failed.execution_policy=Set Execution Policy launch.failed.execution_policy.failed_to_set=Unable to set execution policy launch.failed.execution_policy.hint=The current execution policy prevents the execution of PowerShell scripts.\n\nClick "OK" to allow the current user to execute PowerShell scripts, or click "Cancel" to keep it as it is. launch.failed.exited_abnormally=Game crashed. Please refer to the crash log for more details. -launch.failed.java_version_too_low=The Java version you specified is too low, please reset the Java version. +launch.failed.java_version_too_low=The Java version you specified is too low. Please reset the Java version. launch.failed.no_accepted_java=Unable to find a compatible Java version, do you want to launch the game with the default Java?\nClick "Yes" to launch the game with the default Java.\nOr, you can navigate to "Global/Instance-specific Settings → Java" to choose one yourself. launch.failed.sigkill=Game was forcibly terminated by the user or system. launch.state.dependencies=Resolving dependencies @@ -774,7 +777,7 @@ launch.state.java=Checking Java version launch.state.logging_in=Logging in launch.state.modpack=Downloading required files launch.state.waiting_launching=Waiting for the game to launch -launch.invalid_java=Invalid Java path, please reset the Java path. +launch.invalid_java=Invalid Java path. Please reset the Java path. launcher=Launcher launcher.agreement=ToS and EULA @@ -792,10 +795,10 @@ launcher.cache_directory.clean=Clear Cache launcher.cache_directory.choose=Choose cache directory launcher.cache_directory.default=Default ("%APPDATA%/.minecraft" or "~/.minecraft") launcher.cache_directory.disabled=Disabled -launcher.cache_directory.invalid=Unable to create cache directory, falling back to default. +launcher.cache_directory.invalid=Unable to create a cache directory, falling back to default. launcher.contact=Contact Us -launcher.crash=Hello Minecraft! Launcher has encountered a fatal error! Please copy the following log and ask for help on our Discord, QQ group, GitHub or other Minecraft Forum. -launcher.crash.java_internal_error=Hello Minecraft! Launcher has encountered a fatal error due to your Java is broken. Please uninstall your Java, and download a suitable Java here. +launcher.crash=Hello Minecraft! Launcher has encountered a fatal error! Please copy the following log and ask for help on our Discord, QQ group, GitHub, or other Minecraft forum. +launcher.crash.java_internal_error=Hello Minecraft! Launcher has encountered a fatal error due to your Java being broken. Please uninstall your Java and download a suitable Java here. launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher has encountered a fatal error! Your launcher is outdated. Please update your launcher! launcher.update_java=Please update your Java version. @@ -813,7 +816,7 @@ logwindow.export_dump.no_dependency=Your Java does not contain the dependencies main_page=Home -message.cancelled=Operation was cancelled +message.cancelled=Operation was canceled message.confirm=Confirm message.copied=Copied to clipboard message.default=Default @@ -828,11 +831,11 @@ message.warning=Warning modpack=Modpacks modpack.choose=Choose Modpack -modpack.choose.local=Import From Local File +modpack.choose.local=Import from Local File modpack.choose.local.detail=You can drag the modpack file here. -modpack.choose.remote=Download From URL +modpack.choose.remote=Download from URL modpack.choose.remote.detail=A direct download link to the remote modpack file is required. -modpack.choose.repository=Download Modpack From CurseForge or Modrinth +modpack.choose.repository=Download Modpack from CurseForge or Modrinth modpack.choose.repository.detail=Remember to go back to this page and drop the modpack file here after the modpack is downloaded. modpack.choose.remote.tooltip=Please enter your modpack URL modpack.completion=Downloading dependencies @@ -871,17 +874,17 @@ modpack.scan=Parsing Modpack Index modpack.task.install=Import Modpack modpack.task.install.error=Unable to identify this modpack. We currently only support Curse, Modrinth, MultiMC, and MCBBS modpacks. modpack.type.curse=Curse -modpack.type.curse.error=Unable to download dependencies, please try again or use a proxy server. -modpack.type.curse.not_found=Some dependencies are no longer available, please try installing a newer modpack version. -modpack.type.manual.warning=The modpack is manually packaged by the publisher, which may already contain a launcher. It is recommended to try extracting the modpack and running the game with its own launcher. HMCL can still import it, with no guarantee of its usability, still continue? +modpack.type.curse.error=Unable to download dependencies. Please try again or use a proxy server. +modpack.type.curse.not_found=Some dependencies are no longer available. Please try installing a newer modpack version. +modpack.type.manual.warning=The modpack is manually packaged by the publisher, which may already contain a launcher. It is recommended to try extracting the modpack and running the game with its own launcher. HMCL can still import it, with no guarantee of its usability. Still continue? modpack.type.mcbbs=MCBBS modpack.type.mcbbs.export=Can be imported by Hello Minecraft! Launcher modpack.type.modrinth=Modrinth modpack.type.multimc=MultiMC modpack.type.multimc.export=Can be imported by Hello Minecraft! Launcher and MultiMC -modpack.type.server=Auto-Update Modpack From Server +modpack.type.server=Auto-Update Modpack from Server modpack.type.server.export=Allows server owner to update the game instance remotely -modpack.type.server.malformed=Invalid modpack manifest, please refer to the modpack maker to resolving this problem. +modpack.type.server.malformed=Invalid modpack manifest. Please refer to the modpack maker to resolve this problem. modpack.unsupported=Unsupported modpack format modpack.update=Updating modpack modpack.wizard=Modpack Export Guide @@ -895,7 +898,7 @@ modpack.wizard.step.initialization.exported_version=Game version to export modpack.wizard.step.initialization.force_update=Force updating the modpack to the latest version (you will need a file-hosting server) modpack.wizard.step.initialization.include_launcher=Include the launcher modpack.wizard.step.initialization.save=Export to... -modpack.wizard.step.initialization.warning=Before making a modpack, please make sure the game launches normally, and Minecraft is a release version instead of a snapshot. The launcher will save your download settings.\n\ +modpack.wizard.step.initialization.warning=Before making a modpack, please make sure the game launches normally and Minecraft is a release version instead of a snapshot. The launcher will save your download settings.\n\ \n\ Keep in mind that you are not allowed to add mods and resource packs that are explicitly said not to be distributed or put in a modpack. modpack.wizard.step.initialization.server=Click here for more tutorials for making a server modpack that can be automatically updated. @@ -989,13 +992,13 @@ mods.check_updates.target_version=Target Version mods.check_updates.update=Update mods.choose_mod=Choose mod mods.curseforge=CurseForge -mods.dependency.embedded=Built-in Pre-mod (Already packaged in the mod file by the author, no need to download separately) +mods.dependency.embedded=Built-in Pre-mod (Already packaged in the mod file by the author. No need to download separately) mods.dependency.optional=Optional Pre-mod (If missing, the game will run normally, but the mod features may be missing) -mods.dependency.required=Required Pre-mod (Must be downloaded separately, missing may cause the game to fail to launch) -mods.dependency.tool=Required Library (Must be downloaded separately, missing may cause the game to fail to launch) +mods.dependency.required=Required Pre-mod (Must be downloaded separately. Missing may cause the game to fail to launch) +mods.dependency.tool=Required Library (Must be downloaded separately. Missing may cause the game to fail to launch) mods.dependency.include=Built-in Pre-mod (Already packaged in the mod file by the author, no need to download separately) mods.dependency.incompatible=Incompatible Mod (Installing these mods at the same time will cause the game to fail to launch) -mods.dependency.broken=Broken Pre-mod (This mod existed before, but it does not exist now, try using another download source.) +mods.dependency.broken=Broken Pre-mod (This mod existed before, but it does not exist now. Try using another download source.) mods.disable=Disable mods.download=Mod Download mods.download.title=Mod Download - %1s @@ -1008,7 +1011,7 @@ mods.mcmod.page=MCMod Page mods.mcmod.search=Search in MCMod mods.modrinth=Modrinth mods.name=Name -mods.not_modded=You must install a mod loader (Forge, NeoForge, Fabric, Quilt or LiteLoader) first to manage your mods! +mods.not_modded=You must install a mod loader (Forge, NeoForge, Fabric, Quilt, or LiteLoader) first to manage your mods! mods.restore=Restore mods.url=Official Page mods.update_modpack_mod.warning=Updating mods in a modpack can lead to irreparable results, possibly corrupting the modpack so that it cannot launch. Are you sure you want to update? @@ -1037,7 +1040,7 @@ world.datapack.1_13=Only Minecraft 1.13 or later supports datapacks. world.description=%s | Last played on %s | Game Version: %s world.download=Download World world.export=Export the World -world.export.title=Choose directory for this exported world +world.export.title=Choose the directory for this exported world world.export.location=Save As world.export.wizard=Export World "%s" world.extension=World Archive @@ -1083,7 +1086,7 @@ world.show_all=Show All world.time=h\:mm\:ss a, EEE, MMM d yyyy profile=Game Directories -profile.already_exists=This name already exists, please use a different name. +profile.already_exists=This name already exists. Please use a different name. profile.default=Current profile.home=Minecraft Launcher profile.instance_directory=Game Directory @@ -1093,11 +1096,11 @@ profile.name=Name profile.new=New Directory profile.title=Game Directories profile.selected=Selected -profile.use_relative_path=Use relative path for game directory if possible +profile.use_relative_path=Use a relative path for the game directory if possible repositories.custom=Custom Maven Repository (%s) repositories.maven_central=Universal (Maven Central) -repositories.tencentcloud_mirror=Mainland China Mirror (Tencent Cloud Maven Repository) +repositories.tencentcloud_mirror=Chinese Mainland Mirror (Tencent Cloud Maven Repository) repositories.chooser=HMCL requires JavaFX to work.\n\ \n\ Please click "OK" to download JavaFX from the specified repository, or click "Cancel" to exit.\n\ @@ -1108,8 +1111,8 @@ repositories.chooser.title=Choose download source for JavaFX resourcepack=Resource Packs search=Search -search.hint.chinese=Supports Chinese and English -search.hint.english=Supports English only +search.hint.chinese=Search in English and Chinese +search.hint.english=Search in English only search.enter=Enter text here search.sort=Sort By search.first_page=First @@ -1134,12 +1137,12 @@ settings.advanced.custom_commands.hint=The following environment variables are p \ · $INST_DIR: absolute path of the instance working directory.\n\ \ · $INST_MC_DIR: absolute path of the game directory.\n\ \ · $INST_JAVA: java binary used for launch.\n\ - \ · $INST_FORGE: set if Forge installed.\n\ - \ · $INST_NEOFORGE: set if NeoForge installed.\n\ - \ · $INST_LITELOADER: set if LiteLoader installed.\n\ - \ · $INST_OPTIFINE: set if OptiFine installed.\n\ - \ · $INST_FABRIC: set if Fabric installed.\n\ - \ · $INST_QUILT: set if Quilt installed. + \ · $INST_FORGE: set if Forge is installed.\n\ + \ · $INST_NEOFORGE: set if NeoForge is installed.\n\ + \ · $INST_LITELOADER: set if LiteLoader is installed.\n\ + \ · $INST_OPTIFINE: set if OptiFine is installed.\n\ + \ · $INST_FABRIC: set if Fabric is installed.\n\ + \ · $INST_QUILT: set if Quilt is installed. settings.advanced.dont_check_game_completeness=Do not check game integrity settings.advanced.dont_check_jvm_validity=Do not check Java VM compatibility settings.advanced.dont_patch_natives=Do not attempt to automatically replace native libraries @@ -1150,8 +1153,8 @@ settings.advanced.java_permanent_generation_space=PermGen Space settings.advanced.java_permanent_generation_space.prompt=in MB settings.advanced.jvm=Java VM Options settings.advanced.jvm_args=Java VM Arguments -settings.advanced.jvm_args.prompt=\ · If the arguments entered in "Java VM arguments" is the same as the default arguments, it will not be added.\n\ - \ · Enter any GC arguments in "Java VM arguments", the G1 argument of the default arguments will be disabled.\n\ +settings.advanced.jvm_args.prompt=\ · If the arguments entered in "Java VM arguments" are the same as the default arguments, it will not be added.\n\ + \ · Enter any GC arguments in "Java VM arguments", and the G1 argument of the default arguments will be disabled.\n\ \ · Enable "Do not add default Java VM arguments" to launch the game without adding default arguments. settings.advanced.launcher_visibility.close=Close the launcher after the game launches settings.advanced.launcher_visibility.hide=Hide the launcher after the game launches @@ -1167,7 +1170,7 @@ settings.advanced.natives_directory.default=Default settings.advanced.natives_directory.hint=This option is intended only for users of Apple M1 or other not officially supported platforms. Please do not edit this option unless you know what you are doing.\n\ \n\ Before proceeding, please make sure all libraries (e.g. lwjgl.dll, libopenal.so) are provided in your desired directory.\n\ - Note: It is recommended to use a fully English letters path for the specified local library file, otherwise it may lead to game launch failure. + Note: It is recommended to use a fully English-letters path for the specified local library file. Otherwise it may lead to game launch failure. settings.advanced.no_jvm_args=Do not add default Java VM arguments settings.advanced.precall_command=Pre-launch Command settings.advanced.precall_command.prompt=Commands to execute before the game launches @@ -1182,8 +1185,8 @@ settings.advanced.post_exit_command.prompt=Commands to execute after the game ex settings.advanced.renderer=Renderer settings.advanced.renderer.default=OpenGL (Default) settings.advanced.renderer.d3d12=DirectX 12 (Poor performance and compatibility) -settings.advanced.renderer.llvmpipe=Software (Poor performance and best compatibility) -settings.advanced.renderer.zink=Vulkan (Best performance and poor compatibility) +settings.advanced.renderer.llvmpipe=Software (Poor performance, best compatibility) +settings.advanced.renderer.zink=Vulkan (Best performance, poor compatibility) settings.advanced.server_ip=Server Address settings.advanced.server_ip.prompt=Automatically join after launching the game settings.advanced.use_native_glfw=[Linux/FreeBSD Only] Use System GLFW @@ -1210,7 +1213,7 @@ settings.game.java_directory.version=Specify Java Version settings.game.java_directory.template=%s (%s) settings.game.management=Manage settings.game.working_directory=Working Directory -settings.game.working_directory.choose=Choose working directory +settings.game.working_directory.choose=Choose the working directory settings.game.working_directory.hint=Enable the "Isolated" option in "Working Directory" to allow the current instance to store its settings, saves, and mods in a separate directory.\n\ \n\ It is recommended to enable this option to avoid mod conflicts, but you will need to move your saves manually. @@ -1271,11 +1274,11 @@ settings.type.global.manage=Global Settings settings.type.global.edit=Edit Global Settings settings.type.special.enable=Enable Instance-specific Settings settings.type.special.edit=Edit Current Instance Settings -settings.type.special.edit.hint=Current instance "%s" has enabled the "Instance-specific Settings", all options on this page will NOT affect that instance. Click here to edit its own settings. +settings.type.special.edit.hint=Current instance "%s" has enabled the "Instance-specific Settings". All options on this page will NOT affect that instance. Click here to edit its own settings. sponsor=Donors -sponsor.bmclapi=Downloads for Chinese Mainland are provided by BMCLAPI. Click here for more information. -sponsor.hmcl=Hello Minecraft! Launcher is a FOSS Minecraft launcher which allows users to manage multiple Minecraft instances easily. Click here for more information. +sponsor.bmclapi=Downloads for the Chinese Mainland are provided by BMCLAPI. Click here for more information. +sponsor.hmcl=Hello Minecraft! Launcher is a FOSS Minecraft launcher that allows users to manage multiple Minecraft instances easily. Click here for more information. system.architecture=Architecture system.operating_system=Operating System @@ -1286,12 +1289,12 @@ update=Update update.accept=Update update.changelog=Changelog update.channel.dev=Beta -update.channel.dev.hint=You are currently using a Beta channel build of the launcher, which may include some extra features, but is also sometimes more unstable than the Release channel.\n\ +update.channel.dev.hint=You are currently using a Beta channel build of the launcher, which may include some extra features but is also sometimes more unstable than the Release channel.\n\ \n\ If you encounter any bugs or problems, please navigate to Settings → Feedback page to submit your feedback. update.channel.dev.title=Beta Channel Notice update.channel.nightly=Nightly -update.channel.nightly.hint=You are currently using a Nightly channel build of the launcher, which may include some extra features, but is also always more unstable than the other channels.\n\ +update.channel.nightly.hint=You are currently using a Nightly channel build of the launcher, which may include some extra features but is also always more unstable than the other channels.\n\ \n\ If you encounter any bugs or problems, please navigate to Settings → Feedback page to submit your feedback. update.channel.nightly.title=Nightly Channel Notice @@ -1302,9 +1305,9 @@ update.found=Update Available! update.newest_version=Latest version: %s update.bubble.title=Update Available: %s update.bubble.subtitle=Click here to update -update.note=Beta & Nightly channels may have more features or fixes, but is also come with more potential problems. +update.note=Beta and Nightly channels may have more features or fixes, but they also come with more potential problems. update.latest=This is the latest version -update.no_browser=Cannot open in system browser. But we copied the link to your clipboard and you can open it manually. +update.no_browser=Cannot open in system browser. But we copied the link to your clipboard, and you can open it manually. update.tooltip=Update version=Games @@ -1312,8 +1315,8 @@ version.name=Instance Name version.cannot_read=Unable to parse the game instance, installation cannot continue. version.empty=No Instances version.empty.add=Add new instance -version.empty.launch=No instances, you can install one in "Download → New Game". -version.empty.hint=There are no Minecraft instances here. You can try switching to another game directory or click here to download one. +version.empty.launch=No instances. You can install one in "Download → New Game". +version.empty.hint=There are no Minecraft instances here. You can try switching to another game directory or clicking here to download one. version.game.old=Historical version.game.release=Release version.game.releases=Releases @@ -1344,7 +1347,7 @@ version.manage.remove_assets=Delete All Assets version.manage.remove_libraries=Delete All Libraries version.manage.rename=Rename Instance version.manage.rename.message=Enter New Instance Name -version.manage.rename.fail=Unable to rename the instance, some files might be in use or the name contains an invalid character. +version.manage.rename.fail=Unable to rename the instance, some files might be in use, or the name contains an invalid character. version.settings=Settings version.update=Update Modpack From 1378d1445a6d6ef44b6e1d26d912f42c96f72c5e Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 2 Nov 2024 17:36:41 +0800 Subject: [PATCH 094/169] README & PLATFORM docs post-fixes (#3417) --- PLATFORM.md | 10 +++++----- README.md | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/PLATFORM.md b/PLATFORM.md index b60d0a9002..d82dd8a501 100644 --- a/PLATFORM.md +++ b/PLATFORM.md @@ -17,20 +17,20 @@ Legend: -* ✅: Official supported platform. +* ✅: Officially supported platform. - Fully supported by Mojang official. Problems encountered in the game should be directly reported to the Mojang. + Fully supported by Mojang officials. Problems encountered in the game should be directly reported to the Mojang. * 👌: Supported platforms. - Support is provided by HMCL, tested to work, but may have more issues than a fully supported platform. + Support is provided by HMCL, tested to work, but may have more problems than a fully supported platform. Support for versions below Minecraft 1.6 is not guaranteed. If you encounter a problem that does not exist on fully supported platforms, you can report it to HMCL. -* ❔: Low level supported platforms. +* ❔: Low-level supported platforms. HMCL can run on this platform and has some basic support. However, launching the game directly is not yet available. - If you want to start the game, you will need to get the native libraries needed by Minecraft in other way and specify the native path in the instance settings. + If you want to start the game, you will need to get the native libraries needed by Minecraft in another way and specify the native path in the instance settings. * `/`: Not applicable. diff --git a/README.md b/README.md index b0118ea253..18365ec2eb 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Introduction -HMCL is an open-source, cross-platform Minecraft launcher that supports Mod Management, Game Customizing, ModLoader Installing (Forge, NeoForge, Fabric, Quilt, LiteLoader and OptiFine), Modpack Creating, UI Customization, and more. +HMCL is an open-source, cross-platform Minecraft launcher that supports Mod Management, Game Customizing, ModLoader Installing (Forge, NeoForge, Fabric, Quilt, LiteLoader, and OptiFine), Modpack Creating, UI Customization, and more. HMCL has amazing cross-platform capabilities. Not only does it run on different operating systems like Windows, Linux, and macOS, but it also supports various CPU architectures such as x86, ARM, MIPS, and LoongArch. You can easily enjoy Minecraft across different platforms through HMCL. @@ -46,7 +46,7 @@ If you want to submit a pull request, here are some requirements: ### Compilation -Simply execute the following command in project root directory: +Simply execute the following command in the project root directory: ```bash ./gradlew clean build @@ -59,13 +59,13 @@ Make sure you have at least JavaFX 8 installed. Liberica Full JDK 8 or later is | Parameter | Description | | -------------------------------------------- | --------------------------------------------------------------------------------------------- | | `-Dhmcl.home=` | Override HMCL directory | -| `-Dhmcl.self_integrity_check.disable=true` | Bypass the self integrity check when checking for update | -| `-Dhmcl.bmclapi.override=` | Override API Root of BMCLAPI download provider, defaults to `https://bmclapi2.bangbang93.com` | +| `-Dhmcl.self_integrity_check.disable=true` | Bypass the self integrity check when checking for updates | +| `-Dhmcl.bmclapi.override=` | Override API Root of BMCLAPI download provider. Defaults to `https://bmclapi2.bangbang93.com` | | `-Dhmcl.font.override=` | Override font family | | `-Dhmcl.version.override=` | Override the version number | | `-Dhmcl.update_source.override=` | Override the update source for HMCL itself | -| `-Dhmcl.authlibinjector.location=` | Use specified authlib-injector (instead of downloading one) | -| `-Dhmcl.openjfx.repo=` | Add custom Maven repository for download OpenJFX | +| `-Dhmcl.authlibinjector.location=` | Use the specified authlib-injector (instead of downloading one) | +| `-Dhmcl.openjfx.repo=` | Add custom Maven repository for downloading OpenJFX | | `-Dhmcl.native.encoding=` | Override the native encoding | | `-Dhmcl.microsoft.auth.id=` | Override Microsoft OAuth App ID | -| `-Dhmcl.microsoft.auth.secret=` | Override Microsoft OAuth App secret | +| `-Dhmcl.microsoft.auth.secret=` | Override Microsoft OAuth App Secret | From 3ca7e3cf88863580ee79924d6024e2c0fa0fbaaa Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sun, 3 Nov 2024 17:03:41 +0800 Subject: [PATCH 095/169] Fix incorrect i18n key and line breaks in es & ja (#3404) * Fix incorrect i18n key and line breaks in es & ja * fix --- .../resources/assets/lang/I18N_es.properties | 24 +++++++++---------- .../resources/assets/lang/I18N_ja.properties | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index d889c7287e..b2d6c5f9a9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -325,7 +325,7 @@ download.javafx.prepare=Preparando la descarga exception.access_denied=HMCL no puede acceder al archivo %s, puede estar bloqueado por otro proceso.\n\ \n\ -Para los usuarios de Windows, puede abrir el 'Monitor de Recursos' para comprobar si otro proceso lo está utilizando actualmente. Si es así, puede intentarlo de nuevo después de cerrar ese proceso.\ +Para los usuarios de Windows, puede abrir el 'Monitor de Recursos' para comprobar si otro proceso lo está utilizando actualmente. Si es así, puede intentarlo de nuevo después de cerrar ese proceso.\n\ Si no es así, comprueba si tu cuenta tiene suficientes privilegios para acceder a él. exception.artifact_malformed=No se puede verificar la integridad de los archivos descargados . exception.ssl_handshake=No se puede establecer una conexión SSL debido a que faltan certificados SSL en la instalación actual de Java. Puede intentar ejecutar HMCL en otra versión de Java y luego volver a intentarlo. @@ -342,7 +342,7 @@ Por favor, intente cambiar a versiones de Java como Oracle Java 8 que tiene Java fatal.javafx.missing=No se encontró un entorno JavaFX.\n\ Si está utilizando Java 11 o superior, por favor, descargue Oracle JRE 8 (java.com), o instale BellSoft Liberica Full JRE (bell-sw.com/pages/downloads).\n\ O, si está utilizando distribuciones de OpenJDK, asegúrese de que tiene incluido OpenJFX. -fatal.config_loading_failure=No se pueden cargar los archivos de configuración.\nPara macOS, intente colocar HMCL en un lugar con permiso que no sea "Escritorio", "Descargas" y "Documentos" y vuelva a intentarlo. +fatal.config_loading_failure=No se pueden cargar los archivos de configuración.\nPara macOS, intente colocar HMCL en un lugar con permiso que no sea "Escritorio", "Descargas" y "Documentos" y vuelva a intentarlo.\n\ ¡Por favor, asegúrese de que "Hello Minecraft! Launcher" tiene acceso de lectura y escritura a "%s" y a los archivos que contiene. fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher ha sido actualizado. Por favor, reinicie el launcher. fatal.apply_update_failure=Lo sentimos, pero Hello Minecraft! Launcher no puede actualizarse.\n\ @@ -388,7 +388,7 @@ game.crash.reason.bootstrap_failed=El juego se ha bloqueado debido al mod %1$s.\ \n\ Puedes intentar borrarlo o actualizarlo. game.crash.reason.config=El juego se ha bloqueado porque un mod %1$s no puede analizar su archivo de configuración %2$s. -game.crash.reason.debug_crash=El juego se ha bloqueado porque lo has activado manualmente. +game.crash.reason.debug_crash=El juego se ha bloqueado porque lo has activado manualmente.\n\ \n\ Entonces, probablemente sabes por qué. game.crash.reason.mixin_apply_mod_failed=El juego se ha bloqueado porque Mixin no puede aplicar el mod %1$s, no se puede continuar.\n\ @@ -445,7 +445,7 @@ game.crash.reason.loading_crashed_fabric=El juego se ha bloqueado debido al mod Puedes intentar borrarlo o actualizarlo. game.crash.reason.memory_exceeded=El juego se ha bloqueado debido a que se ha asignado demasiada memoria para un pequeño archivo de paginación.\n\ \n\ -Puede intentar desactivar la opción de asignación automática de memoria en la configuración y ajustar el valor hasta que el juego se inicie. +Puede intentar desactivar la opción de asignación automática de memoria en la configuración y ajustar el valor hasta que el juego se inicie.\n\ También puede tratar de aumentar el tamaño del archivo de paginación en la configuración del sistema. game.crash.reason.mod=El juego se ha bloqueado debido al mod %1$s.\n\ \n\ @@ -486,17 +486,17 @@ game.crash.reason.optifine_repeat_installation=El juego actual no puede seguir e game.crash.reason.modmixin_failure=El juego actual no puede continuar ejecutándose debido a algunas fallas en la inyección de mods. \nEsto generalmente significa que el mod tiene un error o no es compatible con el entorno actual. \nPuede consultar el registro para ver si hay un mod incorrecto. game.crash.reason.mod_repeat_installation=El juego actual tiene múltiples Mods idénticos instalados repetidamente, y cada Mod solo puede aparecer una vez. Elimina los Mods repetidos y luego inicia el juego. game.crash.reason.forge_error=Forge puede haber proporcionado un mensaje de error.\nPuede ver el registro y realizar las acciones correspondientes de acuerdo con la información de registro en el informe de errores.\nSi no ve un mensaje de error, puede consultar el informe de errores para saber cómo ocurrió el error.\n%1$s -game.crash.reason.mod_solution0=El juego actual no puede seguir ejecutándose debido a algunos problemas de modificación.\nPuede consultar el registro para ver si hay un mod incorrecto. +game.crash.reason.mod_resolution0=El juego actual no puede seguir ejecutándose debido a algunos problemas de modificación.\nPuede consultar el registro para ver si hay un mod incorrecto. game.crash.reason.java_version_is_too_high=El juego actual se bloqueó porque la versión de Java es demasiado alta y no puede seguir ejecutándose.\nCambie a una versión anterior de Java en la pestaña Java Path de Configuración global del juego o Configuración específica del juego antes de iniciar el juego.\nSi no es así, puede descargarlo desde java.com (Java8) o BellSoft Liberica Full JRE (Java17) y otras plataformas para descargar e instalar una (reinicie el iniciador después de la instalación). game.crash.reason.mod_name=El juego actual no puede continuar ejecutándose debido a un problema con el nombre del archivo mod. El nombre del archivo de\nMod solo debe usar mayúsculas y minúsculas (Aa ~ Zz), números (0 ~ 9), líneas horizontales (-), subrayado (_) y puntos (.) en toda la mitad del inglés.\n Por favor, vaya a la carpeta mod para agregar un carácter de Cumplimiento anterior a todos los nombres de archivo mod que no cumplan. game.crash.reason.incomplete_forge_installation=O jogo atual não pode continuar devido a uma instalação incompleta do Forge / NeoForge.\nDesinstale e reinstale o Forge / NeoForge em Configurações de versão - Instalação automática. game.crash.reason.modlauncher_8=El juego se ha bloqueado porque tu versión actual de Forge no es compatible con tu instalación de Java. Por favor, intente actualizar Forge, o intente utilizar Java 8u312/11.0.13/17.0.1 o versiones anteriores.\n\ \n\ 8u312 y anteriores\:\n\ -https://oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html +https://oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html\n\ \n\ 11.0.13 y anteriores\:\n\ -https://oracle.com/java/technologies/javase/jdk11-archive-downloads.html +https://oracle.com/java/technologies/javase/jdk11-archive-downloads.html\n\ \n\ 17.0.1 y anteriores\:\n\ https://oracle.com/java/technologies/javase/jdk17-archive-downloads.html @@ -505,21 +505,21 @@ game.crash.reason.no_class_def_found_error=El juego no puede ejecutarse debido a A su instancia de juego le falta %1$s, esto puede deberse a que falta un mod, a que hay un mod incompatible instalado o a que algunos archivos pueden estar dañados.\n\ \n\ Puede que tengas que reinstalar el juego y todos los mods o pedir ayuda a alguien. -game.crash.reason.no_sethod_error=El juego no puede ejecutarse debido a un código incompleto.\n\ +game.crash.reason.no_such_method_error=El juego no puede ejecutarse debido a un código incompleto.\n\ \n\ Es posible que a su instancia de juego le falte un mod, que haya instalado un mod incompatible o que algunos archivos estén dañados.\n\ \n\ Puede que tengas que reinstalar el juego y todos los mods o pedir ayuda a alguien. game.crash.reason.opengl_not_supported=El juego se ha bloqueado porque OpenGL no es compatible con su controlador de gráficos.\n\ \n\ -Si está transmitiendo el juego a través de Internet o utilizando un entorno de escritorio remoto, por favor, intente jugar el juego en su entorno local. +Si está transmitiendo el juego a través de Internet o utilizando un entorno de escritorio remoto, por favor, intente jugar el juego en su entorno local.\n\ O bien, puede intentar actualizar su controlador a la última versión y volver a intentarlo.\n\ \n\ Si tu ordenador tiene una tarjeta gráfica discreta, por favor, asegúrate de que el juego la está utilizando para el renderizado. Si el problema persiste, considera la posibilidad de adquirir una nueva tarjeta gráfica o un nuevo ordenador. game.crash.reason.openj9=El juego no puede ejecutarse en una máquina virtual OpenJ9. Por favor, cambia a una VM Java Hotspot en la configuración del juego y vuelve a ejecutar el juego. Si no tienes una, puedes descargar una en línea. game.crash.reason.out_of_memory=El juego se ha bloqueado porque se ha quedado sin memoria.\n\ \n\ -Esto puede deberse a que no hay suficiente memoria disponible, o a que hay demasiados mods instalados. Puedes intentar solucionarlo aumentando la memoria asignada en la configuración del juego. +Esto puede deberse a que no hay suficiente memoria disponible, o a que hay demasiados mods instalados. Puedes intentar solucionarlo aumentando la memoria asignada en la configuración del juego.\n\ Si sigues encontrando estos problemas, es posible que necesites una mejor computadora. game.crash.reason.resolution_too_high=El juego se ha bloqueado porque estás utilizando un resource packs cuya resolución de textura es demasiado alta.\n\ \n\ @@ -774,7 +774,7 @@ modpack.type.mcbbs=Tipo MCBBS modpack.type.mcbbs.export=Puede ser importado por ¡Hello Minecraft! Launcher modpack.type.modrinth=Modrinth modpack.type.multimc=MultiMC -¡modpack.type.multimc.export=Puede ser importado por Hello Minecraft! Launcher y MultiMC +modpack.type.multimc.export=Puede ser importado por Hello Minecraft! Launcher y MultiMC modpack.type.server=Actualización automática del modpack desde el servidor modpack.type.server.export=Permite al propietario del servidor actualizar la instancia del juego de forma remota modpack.type.server.malformed=Manifiesto de modpack inválido, por favor, consulte al creador del modpack del servidor para solucionar este problema. @@ -791,7 +791,7 @@ modpack.wizard.step.initialization.exported_version=Versión del juego a exporta modpack.wizard.step.initialization.force_update=Forzar la actualización del modpack a la última versión (necesitarás un servicio de alojamiento de archivos) modpack.wizard.step.initialization.include_launcher=Incluir el launcher modpack.wizard.step.initialization.save=Exportar a... -modpack.wizard.step.initialization.warning=Antes de crear un modpack, por favor asegúrate de que el juego se ejecuta, y que es una versión de lanzamiento en lugar de una versión instantánea. El launcher guardará su configuración de descarga. +modpack.wizard.step.initialization.warning=Antes de crear un modpack, por favor asegúrate de que el juego se ejecuta, y que es una versión de lanzamiento en lugar de una versión instantánea. El launcher guardará su configuración de descarga.\n\ \n\ Ten en cuenta que no se te permite añadir mods y resource packs que se digan explícitamente que no se pueden distribuir o poner en un modpack. modpack.wizard.step.initialization.server=Haga clic aquí para ver más tutoriales para hacer un modpack de servidor que se pueda actualizar automáticamente. diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index d3daea14ce..7a5d28b395 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -502,8 +502,8 @@ launch.advice.forge2760_liteloader=Forge 2760以降はLiteLoaderと互換性が launch.advice.forge28_2_2_optifine=Forge28.2.2以降のバージョンはOptiFineと互換性がありません。Forgeを28.2.1以前のバージョンにダウングレードすることを検討してください。 launch.advice.java8_1_13=Minecraft 1.13以降は、Java8以降でのみ実行できます。 launch.advice.java8_51_1_13=Minecraft 1.13は、1.8.0_51より前のJava8でクラッシュする可能性があります。最新バージョンのJava8をインストールしてください。 -launch.advice.java9=Java9以降のバージョンのJavaでMinecraft1.12以前を起動することはできません。 -ゲームを高速化するには、launch.advice.newer_java=Java8をお勧めします。多くのMinecraft1.12以降、およびほとんどのModには、Java8が必要です。 +launch.advice.java9=Java9以降のバージョンのJavaでMinecraft1.12以前を起動することはできません。ゲームを高速化するには、Java8をお勧めします。 +launch.advice.newer_java=多くのMinecraft1.12以降、およびほとんどのModには、Java8が必要です。 launch.advice.not_enough_space=割り当てたメモリが多すぎます。物理メモリサイズが%dMBであるため、ゲームがクラッシュする可能性があります。 launch.advice.too_large_memory_for_32bit=32ビットJavaランタイム環境が原因で、割り当てたメモリが多すぎるため、ゲームがクラッシュする可能性があります。32ビットシステムの最大メモリ容量は1024MBです。 launch.advice.vanilla_linux_java_8=Linux x86-64の場合、Minecraft1.12.2以下はJava8でのみ実行できます。\nJava9以降のバージョンでは、liblwjgl.soなどの32ビットネイティブライブラリをロードできません。 From 3d170267b7a17761fd25e4e91f03e0cd5b6bc23b Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 4 Nov 2024 05:34:28 +0800 Subject: [PATCH 096/169] =?UTF-8?q?Fix=20#3416:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=89=93=E5=BC=80=E6=B8=B8=E6=88=8F=E8=AE=BE=E7=BD=AE=E9=A1=B5?= =?UTF-8?q?=E6=97=B6=E5=B4=A9=E6=BA=83=E7=9A=84=E9=97=AE=E9=A2=98=20(#3421?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index 6fcf3c0de0..cd025c5c62 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -685,7 +685,7 @@ private void initJavaSubtitle() { version = null; } else { gameVersionNumber = GameVersionNumber.asGameVersion(repository.getGameVersion(versionId)); - version = repository.getVersion(versionId); + version = repository.getResolvedVersion(versionId); } try { From 09e9e934d3ea215db7d3b538bd5e4071fc0e2437 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 4 Nov 2024 06:00:45 +0800 Subject: [PATCH 097/169] =?UTF-8?q?Fix=20#3412:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=82=B9=E5=87=BB=E5=89=8D=E7=BD=AE=E6=A8=A1=E7=BB=84=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E6=A8=A1=E7=BB=84=E4=B8=8B=E8=BD=BD=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=A1=86=E4=B8=8D=E4=BC=9A=E5=85=B3=E9=97=AD=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#3422)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jackhuang/hmcl/ui/versions/DownloadPage.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java index 86e1a737b7..d566567eca 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java @@ -345,7 +345,10 @@ private static final class DependencyModItem extends StackPane { pane.getChildren().setAll(FXUtils.limitingSize(imageView, 40, 40), content); RipplerContainer container = new RipplerContainer(pane); - FXUtils.onClicked(container, () -> Controllers.navigate(new DownloadPage(page, addon, version, callback))); + FXUtils.onClicked(container, () -> { + fireEvent(new DialogCloseEvent()); + Controllers.navigate(new DownloadPage(page, addon, version, callback)); + }); getChildren().setAll(container); if (addon != RemoteMod.BROKEN) { @@ -504,7 +507,6 @@ private void loadDependencies(RemoteMod.Version version, DownloadPage selfPage, dependencies.put(dependency.getType(), list); } DependencyModItem dependencyModItem = new DependencyModItem(selfPage.page, dependency.load(), selfPage.version, selfPage.callback); - FXUtils.onClicked(dependencyModItem, () -> fireEvent(new DialogCloseEvent())); dependencies.get(dependency.getType()).add(dependencyModItem); } From 898750d0586f82e9f6a0e096840ebf057d03836b Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 4 Nov 2024 18:41:14 +0800 Subject: [PATCH 098/169] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=A1=86=E6=8C=89=E9=92=AE=E8=87=AA=E8=A1=8C=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=20(#3423)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修复对话框按钮自行移动的问题 * update * update * update --- .../main/java/org/jackhuang/hmcl/setting/Theme.java | 11 +++++++---- HMCL/src/main/resources/assets/css/blue.css | 3 +++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java index e5b116ad85..a120b6640b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java @@ -153,11 +153,14 @@ public String[] getStylesheets(String overrideFontFamily) { .append("-fx-base-text-fill:").append(getColorDisplayName(getForegroundColor())).append(";") .append("-theme-thumb:").append(rgba(paint, 0.7)).append(";"); - if (fontFamily != null) { + if (fontFamily == null) + // https://github.com/HMCL-dev/HMCL/pull/3423 + themeBuilder.append("-fx-font-family: -fx-base-font-family;"); + else themeBuilder.append("-fx-font-family:\"").append(fontFamily).append("\";"); - if (fontStyle != null && !fontStyle.isEmpty()) - themeBuilder.append("-fx-font-style:\"").append(fontStyle).append("\";"); - } + + if (fontStyle != null && !fontStyle.isEmpty()) + themeBuilder.append("-fx-font-style:\"").append(fontStyle).append("\";"); themeBuilder.append('}'); diff --git a/HMCL/src/main/resources/assets/css/blue.css b/HMCL/src/main/resources/assets/css/blue.css index c02cbb1b89..4e427b9c47 100644 --- a/HMCL/src/main/resources/assets/css/blue.css +++ b/HMCL/src/main/resources/assets/css/blue.css @@ -24,5 +24,8 @@ -fx-base-disabled-text-fill: rgba(256, 256, 256, 0.7); -fx-base-text-fill: white; + /* https://github.com/HMCL-dev/HMCL/pull/3423 */ + -fx-font-family: -fx-base-font-family; + -theme-thumb: rgba(92, 107, 192, 0.7); } \ No newline at end of file From 406f36584d6dc20300900affef30dc16b17e0feb Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 4 Nov 2024 18:55:04 +0800 Subject: [PATCH 099/169] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=20FontComboBox=20?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E5=B0=8F=E5=AE=BD=E5=BA=A6=20(#3424)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java index ae50156606..7438a318fd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java @@ -35,6 +35,8 @@ public class FontComboBox extends JFXComboBox { private boolean loaded = false; public FontComboBox() { + setMinWidth(260); + styleProperty().bind(Bindings.concat("-fx-font-family: \"", valueProperty(), "\"")); setCellFactory(listView -> new JFXListCell() { From c6658771cafbf38cf3e1e0af3022ece1aa71b6d8 Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 5 Nov 2024 00:20:42 +0800 Subject: [PATCH 100/169] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20HMCLauncher=20?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8=E8=AF=86=E5=88=AB=20Window?= =?UTF-8?q?s=20on=20Arm=20=E5=B9=B3=E5=8F=B0=E7=9A=84=E9=97=AE=E9=A2=98=20?= =?UTF-8?q?(#3425)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update * update --- HMCLauncher/CMakeLists.txt | 3 +- HMCLauncher/HMCL/HMCL.rc | 4 +- HMCLauncher/HMCL/java-download.ps1 | 225 ----------------------------- HMCLauncher/HMCL/lang.h | 6 +- HMCLauncher/HMCL/main.cpp | 11 +- HMCLauncher/HMCL/os.cpp | 35 +++++ HMCLauncher/HMCL/os.h | 10 +- 7 files changed, 53 insertions(+), 241 deletions(-) delete mode 100644 HMCLauncher/HMCL/java-download.ps1 diff --git a/HMCLauncher/CMakeLists.txt b/HMCLauncher/CMakeLists.txt index c7afc7f3ba..1edf65cf65 100644 --- a/HMCLauncher/CMakeLists.txt +++ b/HMCLauncher/CMakeLists.txt @@ -1,7 +1,8 @@ cmake_minimum_required(VERSION 3.25) project(HMCLauncher) if(MSVC) - add_compile_options(/utf-8 /D_UNICODE /W4) + add_definitions(-DUNICODE -D_UNICODE) + add_compile_options(/utf-8 /W4) add_link_options(/ENTRY:wWinMainCRTStartup) else() add_compile_options(-municode -Wall -Wextra -Wpedantic) diff --git a/HMCLauncher/HMCL/HMCL.rc b/HMCLauncher/HMCL/HMCL.rc index 71fee26e9e..ecc8c147c4 100644 --- a/HMCLauncher/HMCL/HMCL.rc +++ b/HMCLauncher/HMCL/HMCL.rc @@ -82,8 +82,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,4,0,0 - PRODUCTVERSION 3,4,0,0 + FILEVERSION 3,5,0,0 + PRODUCTVERSION 3,5,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L diff --git a/HMCLauncher/HMCL/java-download.ps1 b/HMCLauncher/HMCL/java-download.ps1 deleted file mode 100644 index e2f0c6abeb..0000000000 --- a/HMCLauncher/HMCL/java-download.ps1 +++ /dev/null @@ -1,225 +0,0 @@ -param( - [string]$JavaDir, - [string]$Arch -) - -$chinese = [System.Globalization.CultureInfo]::CurrentCulture.Name -eq 'zh-CN' - -[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") -[System.Windows.Forms.Application]::EnableVisualStyles() - -# Choose Source Dialog - -$dialog = New-Object System.Windows.Forms.Form -$dialog.AutoSize = $true -$dialog.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::GrowAndShrink -if ($chinese) { - $dialog.Text = '未能在这台电脑上找到 Java' -} else { - $dialog.Text = 'Java not found' -} - -$dialogLayout = New-Object System.Windows.Forms.FlowLayoutPanel -$dialogLayout.AutoSize = $true -$dialogLayout.FlowDirection = [System.Windows.Forms.FlowDirection]::TopDown -$dialogLayout.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::GrowAndShrink - -$messageLabel = New-Object System.Windows.Forms.Label -$messageLabel.AutoSize = $true -$messageLabel.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -if ($chinese) { - $messageLabel.Text = "HMCL 需要 Java 运行时环境才能正常运行,是否自动下载安装 Java?" -} else { - $messageLabel.Text = "Running HMCL requires a Java runtime environment. `nDo you want to download and install Java automatically?" -} - -$useMirrorCheckBox = New-Object System.Windows.Forms.CheckBox -$useMirrorCheckBox.AutoSize = $true -$useMirrorCheckBox.Anchor = [System.Windows.Forms.AnchorStyles]::Right -$useMirrorCheckBox.Checked = $false -if ($chinese) { - $useMirrorCheckBox.Text = '使用备用下载源(如果无法正常下载,请打开它再试一次)' -} else { - $useMirrorCheckBox.Text = 'Use the alternate download source' -} - -$selectButtonPanel = New-Object System.Windows.Forms.FlowLayoutPanel -$selectButtonPanel.AutoSize = $true -$selectButtonPanel.Anchor = [System.Windows.Forms.AnchorStyles]::Right -$selectButtonPanel.FlowDirection = [System.Windows.Forms.FlowDirection]::LeftToRight -$selectButtonPanel.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::GrowAndShrink - -$yesButton = New-Object System.Windows.Forms.Button -$noButton = New-Object System.Windows.Forms.Button -$yesButton.DialogResult = [System.Windows.Forms.DialogResult]::Yes -$noButton.DialogResult = [System.Windows.Forms.DialogResult]::No - -if ($chinese) { - $yesButton.Text = '是' - $noButton.Text = '否' -} else { - $yesButton.Text = 'Yes' - $noButton.Text = 'No' -} -$selectButtonPanel.Controls.Add($yesButton) -$selectButtonPanel.Controls.Add($noButton) - -$dialogLayout.Controls.Add($messageLabel) -$dialogLayout.Controls.Add($useMirrorCheckBox) -$dialogLayout.Controls.Add($selectButtonPanel) - -$dialog.Controls.Add($dialogLayout) - -$result = $dialog.ShowDialog() - -if ($result -ne [System.Windows.Forms.DialogResult]::Yes) { - exit 0 -} - -if ($useMirrorCheckBox.Checked) { - switch ($Arch) { - 'x86-64' { - $script:url = 'https://download.bell-sw.com/java/17.0.2+9/bellsoft-jre17.0.2+9-windows-amd64-full.zip' - } - 'x86' { - $script:url = 'https://download.bell-sw.com/java/17.0.2+9/bellsoft-jre17.0.2+9-windows-i586-full.zip' - } - default { exit 1 } - } -} else { - switch ($Arch) { - 'x86-64' { - $script:url = 'https://cdn.azul.com/zulu/bin/zulu17.32.13-ca-fx-jre17.0.2-win_x64.zip' - } - 'x86' { - $script:url = 'https://cdn.azul.com/zulu/bin/zulu17.32.13-ca-fx-jre17.0.2-win_i686.zip' - } - default { exit 1 } - } -} - -$securityProtocol = [System.Net.ServicePointManager]::SecurityProtocol.value__ -if (($securityProtocol -ne 0) -and (($securityProtocol -band 0x00000C00) -eq 0)) { # Try using HTTP when the platform does not support TLS 1.2 - $script:url = $script:url -replace '^https:', 'http:' -} - -# Download Winodw - -do { - $tempFileName = "hmcl-java-$(Get-Random).zip" - $script:tempFile = Join-Path ([System.IO.Path]::GetTempPath()) $tempFileName -} while (Test-Path $script:tempFile) - -$form = New-Object System.Windows.Forms.Form -$form.AutoSize = $true -$form.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::GrowAndShrink -if ($chinese) { - $form.Text = '正在下载 Java 中' -} else { - $form.Text = 'Downloading Java' -} - -$tip = New-Object System.Windows.Forms.Label -$tip.AutoSize = $true -if ($chinese) { - $tip.Text = '正在下载 Java。这需要一段时间,请耐心等待。' -} else { - $tip.Text = 'Downloading Java. Please wait patiently for the download to complete.' -} - -$layout = New-Object System.Windows.Forms.FlowLayoutPanel -$layout.AutoSize = $true -$layout.FlowDirection = [System.Windows.Forms.FlowDirection]::TopDown -$layout.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::GrowAndShrink - -$progressBar = New-Object System.Windows.Forms.ProgressBar -$progressBar.Maximum = 100 - -$label = New-Object System.Windows.Forms.Label -$label.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom - -if ($chinese) { - $label.Text = '准备下载' -} else { - $label.Text = 'In preparation' -} - -$box = New-Object System.Windows.Forms.FlowLayoutPanel -$box.AutoSize = $true -$box.FlowDirection = [System.Windows.Forms.FlowDirection]::LeftToRight -$box.AutoSizeMode = [System.Windows.Forms.AutoSizeMode]::GrowAndShrink -$box.Controls.Add($progressBar) -$box.Controls.Add($label) - -$cancelButton = New-Object System.Windows.Forms.Button -$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel -$cancelButton.Anchor = [System.Windows.Forms.AnchorStyles]::Right -if ($chinese) { - $cancelButton.Text = '取消' -} else { - $cancelButton.Text = 'Cancel' -} - -$layout.Controls.Add($tip) -$layout.Controls.Add($box) -$box.Controls.Add($cancelButton) - -$form.Controls.Add($layout) - -[System.Net.DownloadProgressChangedEventHandler]$progressChangedEventHandler = { - param($sender, [System.Net.DownloadProgressChangedEventArgs]$ChangedEventArgs) - $bytesReceived = $ChangedEventArgs.BytesReceived - $totalBytes = $ChangedEventArgs.TotalBytesToReceive - - $percentage = ([double]$bytesReceived)/([double]$totalBytes) * 100 - - $progressBar.Value = [int][System.Math]::Truncate($percentage) - $label.Text = [string]::Format("{0:0.00}%", $percentage) -} - -[System.ComponentModel.AsyncCompletedEventHandler]$downloadFileCompletedEventHandler = { - param($sender, [System.ComponentModel.AsyncCompletedEventArgs]$CompletedEventArgs) - if (!$form.IsDisposed) { - $label.Refresh() - if ($CompletedEventArgs.Cancelled) { - $form.DialogResult = [System.Windows.Forms.DialogResult]::Cancel - } elseif ($CompletedEventArgs.Error -ne $null) { - if ($chinese) { - [System.Windows.Forms.MessageBox]::Show($CompletedEventArgs.Error.Message, '下载失败', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Exclamation) - } else { - [System.Windows.Forms.MessageBox]::Show($CompletedEventArgs.Error.Message, 'Download failed', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Exclamation) - } - $form.DialogResult = [System.Windows.Forms.DialogResult]::Cancel - } else { - $form.DialogResult = [System.Windows.Forms.DialogResult]::OK - } - } -} - -$client = New-Object System.Net.WebClient -$client.Headers.Add('User-Agent', 'Wget/1.20.3 (linux-gnu)') -$client.add_DownloadProgressChanged($progressChangedEventHandler) -$client.add_DownloadFileCompleted($downloadFileCompletedEventHandler) - -$client.DownloadFileAsync($script:url, $script:tempFile) - -$result = $form.ShowDialog() -$client.CancelAsync() -$form.Dispose() - -if ($result -eq [System.Windows.Forms.DialogResult]::OK) { - $null = New-Item -Type Directory -Force $JavaDir - $app = New-Object -ComObject Shell.Application - $items = $app.NameSpace($script:tempFile).items() - foreach ($item in $items) { - $app.NameSpace($JavaDir).copyHere($item) - } -} - -if ([System.IO.File]::Exists($script:tempFile)) { - try { - [System.IO.File]::Delete($script:tempFile) - } catch { - Write-Error $_ - } -} \ No newline at end of file diff --git a/HMCLauncher/HMCL/lang.h b/HMCLauncher/HMCL/lang.h index 8301c5e0ba..b6207594e2 100644 --- a/HMCLauncher/HMCL/lang.h +++ b/HMCLauncher/HMCL/lang.h @@ -6,9 +6,7 @@ #define ERROR_PROMPT L"The Java runtime environment is required to run HMCL and Minecraft,\n"\ L"Click 'OK' to start downloading java.\n"\ - L"Please restart HMCL after installing Java.\n"\ - L"Click 'Help' go for help." + L"Please restart HMCL after installing Java." #define ERROR_PROMPT_ZH L"运行 HMCL 以及 Minecraft 需要 Java 运行时环境,点击“确定”开始下载。\n"\ - L"请在安装 Java 完成后重新启动 HMCL。\n"\ - L"点击“帮助”寻求帮助。" + L"请在安装 Java 完成后重新启动 HMCL。" diff --git a/HMCLauncher/HMCL/main.cpp b/HMCLauncher/HMCL/main.cpp index 78bdc48f47..ba20558911 100644 --- a/HMCLauncher/HMCL/main.cpp +++ b/HMCLauncher/HMCL/main.cpp @@ -75,12 +75,11 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, bool useChinese = GetUserDefaultUILanguage() == 2052; // zh-CN - SYSTEM_INFO systemInfo; - GetNativeSystemInfo(&systemInfo); - // TODO: check whether the bundled JRE is valid. + MyArchitecture architecture = MyGetArchitecture(); + // First try the Java packaged together. - bool isX64 = (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64); - bool isARM64 = (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64); + bool isX64 = architecture == MyArchitecture::X86_64; + bool isARM64 = architecture == MyArchitecture::ARM64; if (isARM64) { RawLaunchJVM(L"jre-arm64\\bin\\javaw.exe", workdir, exeName, jvmOptions); @@ -143,7 +142,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, if (isARM64) { downloadLink = L"https://docs.hmcl.net/downloads/windows/arm64.html"; - } if (isX64) { + } else if (isX64) { downloadLink = L"https://docs.hmcl.net/downloads/windows/x86_64.html"; } else { downloadLink = L"https://docs.hmcl.net/downloads/windows/x86.html"; diff --git a/HMCLauncher/HMCL/os.cpp b/HMCLauncher/HMCL/os.cpp index d632b422c8..b10718586e 100644 --- a/HMCLauncher/HMCL/os.cpp +++ b/HMCLauncher/HMCL/os.cpp @@ -1,6 +1,41 @@ #include "stdafx.h" #include "os.h" +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS2) (HANDLE, PUSHORT, PUSHORT); + +MyArchitecture MyGetArchitecture() { + LPFN_ISWOW64PROCESS2 fnIsWow64Process2 = (LPFN_ISWOW64PROCESS2)GetProcAddress( + GetModuleHandle(L"Kernel32.dll"), "IsWow64Process2"); + if (NULL != fnIsWow64Process2) { + USHORT uProcessMachine = 0; + USHORT uNativeMachine = 0; + if (fnIsWow64Process2(GetCurrentProcess(), &uProcessMachine, &uNativeMachine)) { + if (uNativeMachine == 0xAA64) { + return MyArchitecture::ARM64; + } + + if (uNativeMachine == 0x8664) { + return MyArchitecture::X86_64; + } + + return MyArchitecture::X86; + } + } + + SYSTEM_INFO systemInfo; + GetNativeSystemInfo(&systemInfo); + + if (systemInfo.wProcessorArchitecture == 12) { // PROCESSOR_ARCHITECTURE_ARM64 + return MyArchitecture::ARM64; + } + + if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { + return MyArchitecture::X86_64; + } + + return MyArchitecture::X86; +} + LSTATUS MyRegQueryValue(HKEY hKey, LPCWSTR subKey, DWORD dwType, std::wstring &out) { DWORD dwSize = 0; diff --git a/HMCLauncher/HMCL/os.h b/HMCLauncher/HMCL/os.h index d0c2fcd63e..e44743a9f0 100644 --- a/HMCLauncher/HMCL/os.h +++ b/HMCLauncher/HMCL/os.h @@ -8,9 +8,13 @@ const int MAX_KEY_LENGTH = 255; const int MAX_VALUE_NAME = 16383; -#ifndef PROCESSOR_ARCHITECTURE_ARM64 - #define PROCESSOR_ARCHITECTURE_ARM64 12 -#endif +enum MyArchitecture { + X86, + X86_64, + ARM64 +}; + +MyArchitecture MyGetArchitecture(); // Query registry value of class root hKey, key path subKey, stores result in // parameter out. From 13856b71a09ad497c6567f20dbab03f6639b6004 Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 5 Nov 2024 03:43:18 +0800 Subject: [PATCH 101/169] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20HMCLauncher.exe=20?= =?UTF-8?q?(#3427)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/assets/HMCLauncher.exe | Bin 99840 -> 147968 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/HMCL/src/main/resources/assets/HMCLauncher.exe b/HMCL/src/main/resources/assets/HMCLauncher.exe index 12780645513dd2aa56cf00ff41741456063769d9..12ccc5216720e0cac79c99e4e7d0b0b6474a0c64 100644 GIT binary patch literal 147968 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
    RAj?)&{c9r>|V-R#rkDCskf-JM%?BUEPE|yt=!^ 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

    eTE^fHta>i_?G3r%UFHpu0L0C<9r+ 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 literal 99840 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%0DbxaHWhxvQEl9B2Ng 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„p`VfZM^>z&&6sXyASTP=|glC~NxW4!&OkzKA{ttV2Ii5dCk#X7DFq z4(6AG9q1Q>pQDIp8F)7%TzxI!Gib{bP5o z>ZkO0y-@W@TAiozNvrc!8`0{;YCP5IA{8gCUZU!^Ru`+Z`qisD!;(3ZKiuW2J!v~X z4ltM1irUS)}qu!c8Q1q--_cAWx0wdM+&P{X7J{kE_k)uisoG zTf5ZKH)!64oZpfbCUY`b@7$sKK|K%4Regw7FI4f+YR&EPt0hiat>dTFi&fZKU8KrD ztCt1%Q=;mDHrJdQt(LuIzn{7eY4bZ(+3R_ml#qWODN=}j^&&O?X*(jb*=62kUt|vb z=6au8+t>N7)pw{o)#^f3W?H>ejSE`6Oy#LoYYvlNE&1+OcZFM`>V!6z6{6pcE5Lk( zm2a}f%(v9CJ{MPhzQ$secFh~o97D}t&|EUT_R*XU98Gln=e&! zL%mkl;c6a%uDhD|q-6v&FT-yx>pH2^^l$i_sQ!vt;;%WFn*Wlk>VxL{XilQ=H518A zNuyqa>w2u!n%k-OGK*CIqIoMK)2exZiL?gkZ#ADn$H&iK&^q}hJgp@v&6#ODi$zS2wNITKK>Q$5G5(@9I%Uri_Y3q75wp5j|=J&{7KOatW zYBjGxmzh>;POj!V`0a?Fx;<$AjgEun;b~5<=HV?=Y1C@X`Sq{gbxY~urRdtgWGyZn5V7X^yex@#t_he?Zqit=93>YWXYcCE;CZ?y~0LiR8ClZ%W_i=Tpo2Q}o)E z{w}gr#{~dZZCvqNG;mqdpDbR|~&XbKNz+QJ1&oooX(;=IQD3(EL)7 z=Fz-)k@%K6s(DEIZ(y1O%>&b*d88{;Kc{({I$XW}m9{7?)4#tVda1!(da38yZlMZa ztL0>g-@HtTtv_e&x{r{ElmYZ~R(i>dmh;B`H*^{HS$Z zf90O5@A#Gb&A51hpWX1IGOs$O{Rg9YyvXPK*?2$ly&Qveow(|EnHNlaD`n2#`wqV5 z)4}7q`>TDGzkYL#UGeX3?$?c&pjCcswcNL^3sN7t@QcI0IuKJaDs|lYEAk?KX{(yG zVN_B1!C_Tzj(YHTaM8Jx_Fu=|^}E0HPaXBwmB-KAd1kLI?W(=SciyJc=MPTOBq@>~ zsXP9scb?l=@Z-PsN>wK0O|R7U>n22Py{PShuPv9&DIxi*WTK~kY*QY2E7f@S?NsAE zDCi%l{x2GNmYuCtTCp`%qud*&f7GGQdL)r9S-#T9En6&A*2rD7TvhC{AD8M1t(>%`OkmY1 z{JUAKlH#;C-}CoW&+Q>=QUaY;%u@vF-JdSJi5r#x`SeWB&=b1`Vn zE9IB}@|l#+A7A+Tj{TfAE^nD%7Pc$pcWWOV`bN!#_&23;<&xbgcP`u3*9;ki`%||> zzP%^q?y0vN`p_Ufsd1M+lk|MbsM&XnEcxs@-2Z9jt_NO7sl8=I-2C2Gj5C^Bf-n2{ z#gx}xyXx*Mj(Eo!+ls578UJ!h%e2bR?H_WoIj88aVU>GR{!jVN&Qdg@_Qs>nd_aEH|MS!LvJa+w*zCJA*bzs3-kdzR zj_>-Xz@L`pRzOwUn|y=S^LFmheixSo6`Q*HTKi zt-5rmkNir#>iG}C52dVmY1ZrgUX%PQKKjVd52cju_~`ygyLyi^wp@_=RiD>WA|HI} z=f_447-vL({g>?Dy`EB5{LYI*e?t6n?z(kc|HCP#etFfI#gAM={DY4V|IOi)dp}#h z<=X&;7E9`nY{a);0Imr#$uf-nH-M62Cn~7ytM`eaf}fBPyq~klyWY zzTW7oPbq)ov$o!&sPC)xy?k}*krdDKmyUOgB|cjgU-YXxkEHy1ZsL&D|4)1010Gdz z^?d^YBO(Tg5-{KbfdmNQ{@c6%?(W@?gd~uJB?(D@KoYVW63jo64FrrD0TmS$HEKkZ z06|b`#fmLfUKGz) z%SPCQ_J@tI2_qYfunFrjjIaqiCmCTAwsA(-gxz~#58zDLQfq`wXqjS!P1t$-O+CE{ zOSTwc6LJfTun9L_V}wn}|MCqzzX>}ZGQuYG%{Rg(>>h1|O<3~DVLiVIPjwh!6V_E5 zVH0xGjj#z@{`$I}--KMJ5$=Utw-zj|p~q~l6hBNT;s;GTXv#t8vVeYEf-A48)h`n% zFI}R~MXGE4v^30B`Hd-7ahVZOT(PRI7PFLcB%t{6`kwezJXgF*fUn_-G1;N@nBtm1 zQ?RrgH)&8xth2(?*F?qu(swsT1JVaaXbrOq@LIsm*~S|1A;576r_VCh)K4Iu*5c{Y z9#;VRfTvkkA>bguGr-eYV+q1n0{Q_hfE9p40jmHn0}KMvnsGBAt#Pgc90j-mkk-^& z0iyvo1JYV?2OzBx?*<$XxEF8&;66Z_lkEqb2-pcY3GfggvZc=ewmPD&Li^!O4Oh zxBz(4I$SNDDck1-PdBo(yBkLJf}lWS$fSV&-qx~(n7by1Z!(8Rkbxsx%N!#$H2$JpMhSH%uQaz zBMYS|)5}9=<4MjO_Ekv&RlSm@bPG@uV}*(XcUt4CgoNlh+k$qh)$2*?qUH%=%0oK> zB*!4iOzRpr)dUI8rYO*+b0>5*g;qj2UB4`N@?HiS^`J@mHeT0aJzC#eE5h0qJ*5}v zsYo|gLW}6cv>~tQ`VPW{Tj|a8P2Vf69jU*aZZhgvgu0W)(aJKd z{85V;H#Icq68mRqEZF&Lg61gL(Jq4QsErKibC7=pC>m?NCZ2@c_iQ<>1etO;KhB_C ztk?WPd5w6Ap|wm}eIdbV(5 z_f*)BvVVztNJVtB{9eLM88C=9MTHmCP)WSw^bil%+Q=;d3l~ zY{V?clG@vXo>B|xTfoEY@rG2eA9hdXdP}dxvT&bfzm`jD)B8YgKUSr-e(J#_Q! z=jdDXoPP;C-LSTBD0{x{?{i};HBFlqjY{^0a14wwg{a zT2S^{9ZyuwakHRaHG2H{bxpvIf3j{V=>`Z3_W9<(`o;CqGVWZUyDcoBK=)Ui(_E6< zQsB?E(Gc`vy1S$l<)fNWxk4$J^`{b%q{+5YZRjmMTJ0pAFsYhSNz|LKvStOYWb@;4 zGJWi*t8Ktde>n3>eVyF>Ipt*p2f)vTmkYu;SqmdnZye1tXpXZUaqIiV(cI-MGH*uQ z=6-R*5Ets&Lj&LQcX%D5|e3b4&^g{CzJr(I> zsc_=;)>6%06P(3#wycs^U4Jh4($`zWI=rtqV;ShS1=NQ5# z;LY}=G#6@v(0oMeSTf$9PQiNsd3Xl^)0}5u(5t_K4#EE!KJsgvmCQ}a-L>GC4SW1A zCGESkwC=0RfA*0s3ujS7ZDTzy`YKvhx}vlwJu5j=|5MsnQ&thEFUrAPi@1_36qi`% zUqXDzz0>0d0lopBmYkPK4;~xwI}z8m1!Mg*yl@+V+xd}+tJa^lY$)65-gHg)6~+~z zP>DDKA1sZfS0@k-W<`=(n! zxTZe144qzcKO7-j`r#mQZXIyvcw`WY+t@dq&ZD&t&ZqNe11>lDQ|n#Bk^g^UG>XI;hEa|~Xg!2IxqCYa>=ze1l(KmETAskm1#&uxN zDY2)n9V>B9GSGS$Vrg#*PWd!ao%DG!Y;@1)!IY51JINO#nV_oF0@=;hgYXV_^uGTYh7OM zL3nZ|-_ZCcQoUR^d}#cUko<(dw9HF@>s;dHUV}I3bo5JSDfJ>1p3zFYToB#}=_u}H z#F^zap%FvY+3>zaSnGk#P}`T_H{t65LmlBv{-NcZQ0V32;K`Zsq4hk1xT8JsrhHF> zHu2&X8+t}RX>25CmXY*qL$Q}o-0`0J9_@i9pBrk7_yAxdyov9h?yKcSIx{}Bd_@1y z>b~*)^FMd}x5p1|HsUW-&cC#Hxxc}ayBPoWwcj4Ud(F4UU;a<>7xs(qU%z3Gd^`Q0 zJx(66np}zn zxdeFAK?J&u+kmk)49EdJz6s$L8js;OW1MV<-;Ccc!IL$h`C`vhF)`2-;F7BSzS@<6 z`ocQg+})59SdROSg6Wk@D|~@^TU`@g!eA+?6?#-^*DsT`XzR-5jR z_?;OR##LZUH(i%M3~SF}Tx&?W)4-)59gY2_%MTc3TOX2cJ#coUyO8_e?@5IHk9|*K z5Z%N$v$86XAES)~ovaVH2{S-vWyu;4L~=w#zk_7#ELRSmcviz>lI5jLyV z-&hqO*4elc5@`nzHWOFlr`FfghS9Mwgi~v9yLoL5>3M!>eI@C90p7Sz#)Z+rK+iSH z$U8eVCp$G$67{NbR}IKQ4?H;;h1FKRIS3zN2W>hdB zL2C}-QfnHkd(!X}*2Mw@SJRtAmogFIlJHpU%P@J256i6xR8^%m1oknz|#P_KT7jY+O;tRdzvolhM%fgTLO z=IQr#1IewTwli8dud+Ij)IjY@zqro^oVznLH?tBJ4Oe~Rf~1Uwl)#e4rAr}_o|2U5 zG=inL%)X9VqkxM(rzh#UfFQZ(@SI@Pyqc9zX6~7RIi-~ifnKR$|B>VsqC;PBsWoM_ z{(!HxQm@k=5k}qmeQX2Y>mHaHC|%M2BODygMy2Qyj`6nUza$Dfuccl_Wq-m*n@;sDSsY24>cl z;^i1UUe~@+VWC%!kL)iqJ&oUxt=|wM`sJVkd~ZbWecaN4S@^<1<&0H9T+CWf=?^4V zl-6^@2bn+fYJ20cHh}UZCHt_$GcfbqJ+Ek&*9V|s>yq>jqvUXUcj;mFmL8*5j+6UZ zA-!xvpbL;mr9YV(icE}+N;@Yti}=**`sUN^#;yAA+G-4ikU&iUXY=}D3b+pl6Jj-t zi)b5A!ctwb7mB)#v?e#$E1j>2hOWW5WuB`vWJim)bn84Q%_2-shoV|zuUW4nS!b;4 z=)ZFUhAaxgW>z&eR1mcpjpgMqBkxH}{avj`eXsYH~gM{(&Q-B_c| zV0I~A0nX>)M!^u>zNg13QZ^Lwg6^47KTFB}o%aQrvlt_N-(==o#>9qx(}!?0w+VG- z`i&#bt+$2F6heQ8=8ImQ6dL6I-LOf_x8fY#$g6RtXC&^jyXG9uOlQJEtZ7?<##z&$ zK+?KW*nsee4m|LdtXZ{YTu;KsKQw-9-C@9+w{+982j{)9MTfhP{-y07Y_}NE=l#9; z9|p?X1E2ej>63cW{}}1t+ID=~XztT(C$=rTIQ<*9>N(~P!d}7$i$B0N&j-ssIDd)d z=6Ab(+x-pR54h1R*?A5Hm|<=fB75R`eyKFq3-bO;M?Fk;19!}fG1kyqXs1DnG&_6 z{3WISVtml3w#-TV7m` zhrWPGAT*vny;WR^NqWCB>E)&G>)-{wmBj{^3+1PD{mb81QvVzJpO?U3eO=#+Ejrq3 zDFnO}5YyQfdT#*xNG)WX+X15i_W=TgIAgu*$OZ7&BH~V50AEeHu`EX5oD0*>R7GC^ zPyKuXcZ{#%hcQu9oGT*qFg%P90B>x2O++QVT``N%jm#~3@FJUp( znJhZd^Zv*Lt$cW_j28Uwb)yoL$b_uo)$wTyKA)Vnkfl`L$>!Yf7z@870)7aap1+(~ zJh^OSLJ}K3(fWDRWM}i`qb6MW@0KEFx;hp#?in@B{ z#G+f+j@>_DaqbKjHeetN8#suK5>r{+%u+TnrIHB+LEVq$y*mGEgc)qSmdm21I9Yh4 z<%MAuKBXU94tkuIkX7==v^jp3m{Y@2f*V=RnjMVKE@#}3E7_#91x!P|?PaUk72^fg zeA5~>J?)(QCnPU~>{Hk%A(>5>QOKtHDp)UnDV0r~yNpfoEn{QsK6YiigGEl1-@?OV zzF7`x$K>kUnX_UolNPox-%Z=t+?MT(&qV#hBiLBmOqMt|z@)-jwrbtoY)kt#X7v^K zw*M4gB}>SyW0TTLS+tPCqNb{BxFtcafAn+@n~FM3o>Rf5)HHlyxNHc`#gX^gebU`aI_SX$#l?5XE|#vb4K1XFw^J^Y90 z^_6q{EUoA|mY7?^;%6;k!(t}sc}Gm-*~IiB7B{LIO@nM_lr*uT zvSlnmO=T(hes<-AX*&PmmMLr$WH81ti^Yh!Xs0wbB|FfM|0OKF;eKW-YGhM07BDrt zkcs(KY*NZR#zhQ+UgfjY6|Kw)`9Iq6B-^^JgT=Yh81zQBL8JI2HqMsLG7Fb5NBTTA zcR?Au?5eRk|B(p}HaTl48}H3$mkb-jBFBqt@+^NJ{v?Yjvlg?d@To;rtZB_1%(1wM zP0b82?((bIl-Xs>y>uPhwCh>+(#r>R{;qiyz5S1L-lFEPsrDJHY*{_Crp#dxBSsng zr#V@CW*OukVAtA<*jQ(dt{>39KJrgr@eo^7b3NO-<4K*rb>VWf*L=PHqY|Cy+w<7H z54W?YpV`au7oaV@KE3@1!Uj&tSj@)Asci7jNH#%mv&+X$WtT?9==?{EDbW8acC9Om zP0k3QA6%#FYXA11wc;+e?(TOY8?{6{7@*=684YPy$QIy{;UjUK1-j~p8Z+nfjezmDfn7~n zdJBsj9S0p)sO!Sy)CCL|6remaS(aCde$axgF!oR>seP{e%6z)-@Y?Gn);c zAhNMaI?HH$K(~+K=zF^ThyIZcT$P~dWgMfVv8aiHUjJx}1LHlVunE_(>GPKBd7j`nl{+Ltt@^<9({L+S(H?kTy+P_x}lx9%5P%nD<9V7qw`1o z6X(^jc=WNc&TPyDd~8B;A&b0rvLXLTBD+S+Vqk{)ZE6b#jDul z%w;GiJnZclYqDYgVbeXZ&FQN)>EocUWgE+0`2ZUqH|h-J+8v--!LXZ2h5vy6omY`Q0nO-`H7#=0_L`x7DG zD?$Hi*gV*~+2t4`)7X`9b{1pL*84)J{*fJvPhW_(sbcctRZK2wW_(^18#FwQ4Y?+b z#igud6J5p3ma&Y@DqhX<8y;p0njd4u>vpoDmK|*V^;>{zW3v%A&8D%@v353MTsHVm zVqsyC>{`ccHZ5;C+9sXF*k+@TYA9b{`$IbKt-XWUidV9f<@cd3UVs>YPS5AEnfR9%U%93%Uixl|6SAmTh{RS7p!{IuUO8qJK1y_>Knzg zsPS3s>UfpK!~RXg+=#{}nxoL%;hg+0(e)`c*vg#cHy}+Vi?uCao}6_of912R=CO}i z{o|jriieJ(-cPYi|7~n;?KZY-)5olF*YDYa>z`n=ftwFl+4e3A?);q9p^W*9);`ac-2NiVscpmWy)3t33rj1#hvi?tpB1ipg5}k3W`T{b zg4O|+y>u0;dfyBL&h&IF`;GYo6=i<4E;OKDmQ(|{C6K@`N7B7oXUGx zVbcy){U~tv|C;&gw(Gdu`bSvF9WUwSYd}9KL7OD!F8v0ywh+yW@w*rv?K0Zx)Nc2r z<$bwu^>)_K@jK|_308jpVd&#lHn$EkU$z-~@fa)H_zPX%D9u9X8}j@KvbAu~NvmAh?OSQs;gu+tncD`L6W8 zYdTqR4u(7y!@oUu=?b=b_v@_b$=8?xc>_O@*hMa zTwk%m8x1{BLvC{6_-Al1!t^(Ym5VUYqg#cHlR4(OybPS$G42xc>1lYJ?c#A-jQkRP zy~c?X!C^REL}$zBE~*;bZ8Rw1YEGV5jD$r|WoNB^`GRhng!ZTk_ zO{de0FU4`VvoR4T*o<>-JkpD}{WS~{rW0F4xdxo7LTYH9b_zZJS%Op0c(V-Ym+GlW zI&|Y3Ntfh6FQT1~qtlJaIN4|cPaa;tuXEB{h5Avb5_z3^ndbD+qZXqwnQcZPL;4pg zTOLk)<4rc?rEh&VLSp!)UvCb)yNptQKUw1(mM+u2H2X`ozg%e%A`F^L=P}KapVKz% z;X_aHb~9p0d+5e6^CYaHJK+&~C_z6L-h2A)Ttr`-sx?(tSymV?in-&2L_W?Epf_Le z(tOtYa43IgVV}ttDU6{)rl*FI1Apss4T~;i9K(68Qeh1Vo`(j_!1($s?kGj z{6C>4jo0%bX9HfA!W${8dcwfe8!tcx{J#3i6?mm#X`rDuGBnzF&kFCyWd>FRsw`FX z*Bw{dkWsUu_PRiQoTafcsSJm7P`C2Zs)j(EWqL0ib^67*sMGtDNuAzXIb>I-n{q?o zT%-Kw|AHlMMJb2yBY7)7gD>H$`Fr{8{EPgTe1fo2Xcuf^uILwo;yQ7&_(O57R4=_F zl`4a5BW=@d^K8ww?Y7J86YT5kJMC}Se`8wZ_a zD^b`fAF04{KFHj4c8`UyEGUC{ci5#!k>f~ zF<)FG{Y1K69_M_^`L*-^I1^lw>tWX$t|@A^TBNq9C)6l+yxZ!Yn!VB>v8MlN>JIN>{XsuUQ|9* zjw^psrrJtu1MTDNQ|wl|YA>=cu~*n@>_Pi#`_1Oysy+JHJes2)+@SO1`Xt&Vlax@Wm_-SgcxPl2b@ z)9U$==PS<{k5|jkvb9pJQCqFurES$-q=C=NaV-EGKa8Ku%lsk!ZT@}!Dq*s~3nfCO zP%pFyw+jynablWykGNCZEsm5Plb)6`t*==RD8EwvtPHe0V?Sa4(tg^0#(vh$Ir1Hk zINBW@j$Mx3juf>(ZB*B)f~Ue$>j`?AJk6dK&o4dKXcjG2i`Nn~m|IvfjyouH2|lq| z+Ah5*+2zABXN|Cqw#HdAtb>&}#j3cJeC0;vKIMnXKILWQi1K^otP)`>u$9}=?2XQc z)#2_%+GcI9_EYU6jVr>kwsP@7AmF6t;$yA zY2^jwRpr-c!I3tvE!}pb?Md6yw!OBuY{zV$+P<)TX&YjXvRmvE(Xy%bIrfG25_`bD z)_#}$Vf$nD?e+uqqxNI=kL)MyS2)Hwra5d5)sf@a?AYNL;2h?>)w$jIwDU68H)yFy zHCdgf-lA?(f1t*=C!mEExmUTLaPM=!=|1lMyL*6Vm}i`4l1KE|Jn3k$=RL1`j(TFW zL`~7COJU9U#m0R z3($|8p1Gd4JR`J;+Cr^FtJYR&_h{R+_q5~M=i1*iQnaCAC^UZ=KY}02$MVx*Ka%-O zelEY5FN5a&kzXlXC%zz_6l0{NQklF`{#xE`eb(A-{mdGpOjFX)asj1A*^a*VCbaLk z@<%1oHqMr4OS1)S*V}Hjwb~xBZME&Uy<+>7?L*r&cC35aXW5tA??8L)K<|6c{+azN z^t!Y5k!UZsBi)gO_NsQQbli{HZim*s;&{XHx#KkI{SQZsbCPq0Gs~IdEO0hC*E>7V zntPqkJ5M?zT?sCm3pcW(FRpRj<=W(W+VxY{o33|VU9P{mBGi$pOU+W}tM{vw?gsaR z?sl~C7w#h3rf~MM0-+HB4 zxeJ=VQ~5yoNI9W=sa$G{wvC4+b=Wdc*Y|CwZG)YXGtW8S=|?HoIyX6AbAAXr`WLj+ z5?7n+DVJMauC}S4s1Ldyac^}$j*?9A9QORqGfA^*$!Mtx?Ov@7z2^n(9qoiho3;4Q zP2i{StNFY6*Z6^gBxJ)5bPDeX5#m(w7V!bGQ+!7}F8)P~kVZ=hl1K7MOQfK5tJEev zFTF1PM*30;lW(#fv}P+M%HNbU+qJNRKSEDQbF?@fbo|6I-T9*PAnfyRVeb`JscWt4 zN!KCB&j*{aSPiK4>a%L6`iA;}`X_at+v@Rn@?k|D@Vw%o%gSlqKUjE2ihz#XE4Rx( zlz%G!Ts|rvm%ouCt&%m{y3kr_U1?ooZL{u%#V%7eDxaZ`AGX~HE8JzD;#lO^=I}a~ zJ9oLxy4I-8ZjUF$v)%KA=UvZdo|j=oey4Gr*n0(^P5ci2IsP+#u}~+h5%vqe5snLg z6C%Yi;&_o4e=L43{zJS%dO&(g`n`0CJW0-%KbFI+PHU;P%GzxG+B!waP>PjGWxeva za+S?vTWY%nV?}~}9`y2W_ISs9M?7?u9 zQxM%^hFB@?5kC+=78y!=jWk6{geBN2cgcU2FSSOYw4Ymj7^7F&9<)7f`@8L|eW+uM zW1_?Amo)eCFXt2ZMf{J1lj0@P7)g>`QmgWiZI><4 z`JnR=P<|a6{HgOL*PmSpX#ZjEk1^KkH-w$S^B(FtSXd*zi@f6{1Tb4(2fI=v_=O6g z3a!+PQEQ#BUf3YC37at=*(2-~_6bLXqZnmQ3a5nA!WrSLfDcNF5#mrWQj8L##Td~d z#)|P`idZ35iFKH}tQR+kd!)V6K54(yDIJgwNr$B)(ov~PIwo~X$E6d}N$HeyS~?@0 zmGDtYIYJ&PN6Jxhv>YQ_+s5XQwL(D5$$7-l2KP3NP%z0eB=kfKc72sWWLGBml z+@&7F?C?0opp)t;^|X3MJ*#r=aCd}zs5{af<&Jj8xGk6u#k&*SyjynL-KyJ*K9%my zbo<<$o&%mku!KXkC@lsvk_1iGR4oPlDo-oY{1|bATC=uJ+n}{#cG02jhK<~>9ncPI zN3~-Z)lO=swX>Le;!G6uFPtCBNAWQj*Ag(3Qu!2&Y8aA~L%CB;awu;;R*N-0vNlqVHQeyIwUy;)i(ZID`} z%~FT78@*ybdc7yRpz)89JL{&9vrOi>!Xw(I718I_m~&t97%r0~UR+ zb-(q1^|1A*^%$)CN$Y9rS!=j56r*O0601NT`7rJX+9aOmc{}gr(|I3Xh$oc_zK(C= zTln?-M!t=2=XddY_(T`4vR>E-+tM!Vf^FG{aq$qWOPA0soPc#X1IrQts}c>15|0tWE_%gu(I*y)C9o}Z zVw2bc+pU|%|6TaLi4bi<~cf<572OCn)MEU+Ow?1vY&!)GnDmRKvSb=D?p zi*>zqBSzMC>n`ga>pp9z^^o<5wF~pK6V_AKGgeNCP$HFR#iGP3JZ3Ro%-noRA!Y&< zN}bZAv|udUsI)2V$}VLOX7ruPAk&<~)vB*lFikXSi#qE6Nq)ip7jf#*8e*mFdcJ6}kKvk%F#f*E-h*SF3BY ztHZV1wb!-Z<#Xq`3*AMy^_BDCjvVL+S?6@!){>Py41FYoKNM+4s2ixenur?}Y0VtgB&LBVorAV8d0FY-uJe zH`(m Date: Thu, 7 Nov 2024 21:37:59 +0800 Subject: [PATCH 102/169] Revise i18n translation before releases (#3428) - Fix some English grammar and text style - Revise `Allow Cheats` to `Allow Commands/Cheats` - Due to the change from `Allow Cheats` to `Allow Commands` by Mojang in 24w04a. - https://minecraft.wiki/w/Java_Edition_24w04a --- .../resources/assets/lang/I18N.properties | 78 +++++++++---------- .../resources/assets/lang/I18N_ru.properties | 2 +- .../resources/assets/lang/I18N_zh.properties | 2 +- .../assets/lang/I18N_zh_CN.properties | 2 +- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 43b6d4256f..afa765ec70 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -58,18 +58,18 @@ account.create.microsoft=Add a Microsoft Account account.create.offline=Add an Offline Account account.create.authlibInjector=Add an authlib-injector Account account.email=Email -account.failed=Account refresh failed. +account.failed=Failed to refresh account. account.failed.character_deleted=The player has already been deleted. -account.failed.connect_authentication_server=Unable to connect to the authentication server, your network connection may be down. -account.failed.connect_injector_server=Unable to connect to the authentication server. Please check your network and make sure you entered the correct URL. -account.failed.injector_download_failure=Unable to download the authlib-injector. Please check your network, or try switching to a different download source. +account.failed.connect_authentication_server=Failed to connect to the authentication server, your network connection may be down. +account.failed.connect_injector_server=Failed to connect to the authentication server. Please check your network and make sure you entered the correct URL. +account.failed.injector_download_failure=Failed to download the authlib-injector. Please check your network, or try switching to a different download source. account.failed.invalid_credentials=Incorrect password or rate limited. Please try again later. account.failed.invalid_password=Invalid password. account.failed.invalid_token=Please try logging in again. -account.failed.migration=Your account needs to be migrated to a Microsoft account. If you already did, you should re-login to your migrated Microsoft account instead. +account.failed.migration=Your account needs to be migrated to a Microsoft account. If you already did, you should log in to your migrated Microsoft account again. account.failed.no_character=There are no characters linked to this account. -account.failed.server_disconnected=Unable to connect to the authentication server. You can log in offline mode or try logging in again.\n\ - If you try several times and still fail, please try adding the account again. +account.failed.server_disconnected=Failed to connect to the authentication server. You can log in using offline mode or try logging in again.\n\ + If you try several times and still fail, please try logging in to the account again. account.failed.server_response_malformed=Invalid server response. The authentication server may not be working. account.failed.ssl=An SSL error occurred while connecting to the server. Please try updating your Java. account.failed.wrong_account=You have logged in to the wrong account. @@ -82,12 +82,12 @@ account.injector.link.register=Register account.injector.server=Authentication Server account.injector.server_url=Server URL account.injector.server_name=Server Name -account.login=Login +account.login=Log in account.login.hint=We never store your password. -account.login.skip=Login offline +account.login.skip=Log in offline account.login.retry=Retry -account.login.refresh=Re-login -account.login.refresh.microsoft.hint=You need to re-add your Microsoft account because the account authorization is invalid. +account.login.refresh=Log in again +account.login.refresh.microsoft.hint=You need to log in to your Microsoft account again because the account authorization is invalid. account.logout=Logout account.register=Register account.manage=Account List @@ -108,12 +108,12 @@ account.methods.microsoft.error.no_character=Your account does not own the Minec account.methods.microsoft.error.unknown=Failed to log in, error code: %d. account.methods.microsoft.error.wrong_verify_method=Please log in using your password on the Microsoft account login page, and do not use a verification code to log in. account.methods.microsoft.logging_in=Logging in... -account.methods.microsoft.hint=Please click "Login" and copy the code displayed here to complete the login process in the browser window that opens.\n\ +account.methods.microsoft.hint=Please click "Log in" and copy the code displayed here to complete the login process in the browser window that opens.\n\ \n\ If the token used to log in to the Microsoft account is leaked, you can click "Deauthorize" to deauthorize it. account.methods.microsoft.manual=Your device code is %1$s. Please click here to copy.\n\ \n\ - After clicking "Login", you should complete the login process in the opened browser window. If it did not show, you can navigate to %2$s manually.\n\ + After clicking "Log in", you should complete the login process in the opened browser window. If it did not show, you can navigate to %2$s manually.\n\ \n\ If the token used to log in to the Microsoft account is leaked, you can click "Deauthorize" to deauthorize it. account.methods.microsoft.makegameidsettings=Create Profile / Edit Profile Name @@ -154,7 +154,7 @@ account.skin.type.little_skin=LittleSkin account.skin.type.little_skin.hint=You need to create a player with the same player name as your offline account on your skin provider site. Your skin will now be set to the skin assigned to your player on the skin provider site. account.skin.type.local_file=Local Skin File account.skin.upload=Upload/Edit Skin -account.skin.upload.failed=Unable to upload skin. +account.skin.upload.failed=Failed to upload skin. account.skin.invalid_skin=Invalid skin file. account.username=Username @@ -329,7 +329,7 @@ download.external_link=Visit Download Website download.failed=Failed to download "%1$s", response code: %2$d. download.failed.empty=No versions are available. Please click here to go back. download.failed.no_code=Failed to download "%s". -download.failed.refresh=Unable to fetch version list. Please click here to retry. +download.failed.refresh=Failed to fetch version list. Please click here to retry. download.game=New Game download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) download.provider.mojang=Official (OptiFine is provided by BMCLAPI) @@ -351,7 +351,7 @@ exception.access_denied=HMCL is unable to access the file "%s". It may be locked For Windows users, you can open "Resource Monitor" to check if another process is currently using it. If so, you can try again after closing that process.\n\ If not, please check if your account has enough permissions to access it. exception.artifact_malformed=Cannot verify the integrity of the downloaded files. -exception.ssl_handshake=Unable to establish an SSL connection due to the lack of an SSL certificate in the current Java installation. You can try opening HMCL in another Java and try again. +exception.ssl_handshake=Failed to establish an SSL connection due to the lack of an SSL certificate in the current Java installation. You can try opening HMCL in another Java and try again. extension.bat=Windows Batch File (.bat) extension.mod=Mod File @@ -640,7 +640,7 @@ game.crash.reason.too_old_java=The game crashed due to you using an outdated Jav \n\ You need to switch to a newer version (%1$s) of Java in "Global/Instance-specific Settings → Java" and then relaunch the game. You can download Java from here. game.crash.reason.unknown=We are not able to figure out why the game crashed. Please refer to the game logs. -game.crash.reason.unsatisfied_link_error=Unable to launch Minecraft due to missing libraries: %1$s.\n\ +game.crash.reason.unsatisfied_link_error=Failed to launch Minecraft due to missing libraries: %1$s.\n\ \n\ If you have edited the native library path, please make sure these libraries do exist. Or, please try launching again after reverting it to default.\n\ \n\ @@ -663,11 +663,11 @@ input.url=The input must be a valid URL. install=New Instance install.change_version=Change Version install.change_version.confirm=Are you sure you want to switch %s from version %s to %s? -install.failed=Installation Failed +install.failed=Failed to install install.failed.downloading=We are unable to download some required files. -install.failed.downloading.detail=Unable to download file: %s +install.failed.downloading.detail=Failed to download file: %s install.failed.downloading.timeout=Download timeout when fetching: %s -install.failed.install_online=Unable to identify the provided file. If you are installing a mod, navigate to the "Mods" page. +install.failed.install_online=Failed to identify the provided file. If you are installing a mod, navigate to the "Mods" page. install.failed.malformed=The downloaded files are corrupted. You can try resolving this problem by switching to another download source in "Settings → Download → Download Source". install.failed.optifine_conflict=Cannot install both OptiFine and Fabric on Minecraft 1.13 or later. install.failed.optifine_forge_1.17=For Minecraft 1.17.1, Forge is only compatible with OptiFine H1 pre2 or later. You can install them by checking "Snapshots" when choosing an OptiFine version in HMCL. @@ -761,15 +761,15 @@ launch.failed=Failed to launch launch.failed.cannot_create_jvm=We are unable to create a Java VM. It may be caused by incorrect Java VM arguments. You can try resolving it by removing all arguments you added in "Global/Instance-specific Settings → Advanced Settings → Java VM Options". launch.failed.creating_process=We are unable to create a new process. Please check your Java path.\n launch.failed.command_too_long=The command length exceeds the maximum length of a bat script. Please try exporting it as a PowerShell script. -launch.failed.decompressing_natives=Unable to extract native libraries.\n -launch.failed.download_library=Unable to download libraries "%s". -launch.failed.executable_permission=Unable to make the launch script executable. +launch.failed.decompressing_natives=Failed to extract native libraries.\n +launch.failed.download_library=Failed to download libraries "%s". +launch.failed.executable_permission=Failed to make the launch script executable. launch.failed.execution_policy=Set Execution Policy -launch.failed.execution_policy.failed_to_set=Unable to set execution policy +launch.failed.execution_policy.failed_to_set=Failed to set execution policy launch.failed.execution_policy.hint=The current execution policy prevents the execution of PowerShell scripts.\n\nClick "OK" to allow the current user to execute PowerShell scripts, or click "Cancel" to keep it as it is. launch.failed.exited_abnormally=Game crashed. Please refer to the crash log for more details. launch.failed.java_version_too_low=The Java version you specified is too low. Please reset the Java version. -launch.failed.no_accepted_java=Unable to find a compatible Java version, do you want to launch the game with the default Java?\nClick "Yes" to launch the game with the default Java.\nOr, you can navigate to "Global/Instance-specific Settings → Java" to choose one yourself. +launch.failed.no_accepted_java=Failed to find a compatible Java version, do you want to launch the game with the default Java?\nClick "Yes" to launch the game with the default Java.\nOr, you can navigate to "Global/Instance-specific Settings → Java" to choose one yourself. launch.failed.sigkill=Game was forcibly terminated by the user or system. launch.state.dependencies=Resolving dependencies launch.state.done=Launched @@ -795,7 +795,7 @@ launcher.cache_directory.clean=Clear Cache launcher.cache_directory.choose=Choose cache directory launcher.cache_directory.default=Default ("%APPDATA%/.minecraft" or "~/.minecraft") launcher.cache_directory.disabled=Disabled -launcher.cache_directory.invalid=Unable to create a cache directory, falling back to default. +launcher.cache_directory.invalid=Failed to create a cache directory, falling back to default. launcher.contact=Contact Us launcher.crash=Hello Minecraft! Launcher has encountered a fatal error! Please copy the following log and ask for help on our Discord, QQ group, GitHub, or other Minecraft forum. launcher.crash.java_internal_error=Hello Minecraft! Launcher has encountered a fatal error due to your Java being broken. Please uninstall your Java and download a suitable Java here. @@ -816,7 +816,7 @@ logwindow.export_dump.no_dependency=Your Java does not contain the dependencies main_page=Home -message.cancelled=Operation was canceled +message.cancelled=Operation canceled message.confirm=Confirm message.copied=Copied to clipboard message.default=Default @@ -872,9 +872,9 @@ modpack.origin.mcbbs=MCBBS modpack.origin.mcbbs.prompt=Post ID modpack.scan=Parsing Modpack Index modpack.task.install=Import Modpack -modpack.task.install.error=Unable to identify this modpack. We currently only support Curse, Modrinth, MultiMC, and MCBBS modpacks. +modpack.task.install.error=Failed to identify this modpack. We currently only support Curse, Modrinth, MultiMC, and MCBBS modpacks. modpack.type.curse=Curse -modpack.type.curse.error=Unable to download dependencies. Please try again or use a proxy server. +modpack.type.curse.error=Failed to download dependencies. Please try again or use a proxy server. modpack.type.curse.not_found=Some dependencies are no longer available. Please try installing a newer modpack version. modpack.type.manual.warning=The modpack is manually packaged by the publisher, which may already contain a launcher. It is recommended to try extracting the modpack and running the game with its own launcher. HMCL can still import it, with no guarantee of its usability. Still continue? modpack.type.mcbbs=MCBBS @@ -1019,8 +1019,8 @@ mods.install=Install mods.save_as=Save As nbt.entries=%s entries -nbt.open.failed=Fail to open file -nbt.save.failed=Fail to save file +nbt.open.failed=Failed to open file +nbt.save.failed=Failed to save file nbt.title=View File - %s datapack=Datapacks @@ -1029,7 +1029,7 @@ datapack.choose_datapack=Choose datapack to import datapack.extension=Datapack datapack.title=World [%s] - Datapacks -web.failed=Page loading failed +web.failed=Failed to load page web.open_in_browser=Do you want to open this address in a browser:\n%s web.view_in_browser=View in browser @@ -1048,10 +1048,10 @@ world.game_version=Game Version world.import.already_exists=This world already exists. world.import.choose=Choose world archive you want to import world.import.failed=Failed to import this world: %s -world.import.invalid=Unable to import the save. +world.import.invalid=Failed to parse the world. world.info.title=World [%s] - Information world.info.basic=Basic Information -world.info.allow_cheats=Allow Cheats +world.info.allow_cheats=Allow Commands/Cheats world.info.dimension.the_nether=The Nether world.info.dimension.the_end=The End world.info.difficulty=Difficulty @@ -1236,7 +1236,7 @@ settings.launcher.general=General settings.launcher.language=Language (Applies After Restart) settings.launcher.launcher_log.export=Export Launcher Logs settings.launcher.launcher_log.reveal=Reveal Logs in Explorer -settings.launcher.launcher_log.export.failed=Unable to export logs. +settings.launcher.launcher_log.export.failed=Failed to export logs. settings.launcher.launcher_log.export.success=Logs have been exported to "%s". settings.launcher.log=Logging settings.launcher.log.font=Font @@ -1300,7 +1300,7 @@ update.channel.nightly.hint=You are currently using a Nightly channel build of t update.channel.nightly.title=Nightly Channel Notice update.channel.stable=Release update.checking=Checking for Updates -update.failed=Unable to update +update.failed=Failed to update update.found=Update Available! update.newest_version=Latest version: %s update.bubble.title=Update Available: %s @@ -1312,7 +1312,7 @@ update.tooltip=Update version=Games version.name=Instance Name -version.cannot_read=Unable to parse the game instance, installation cannot continue. +version.cannot_read=Failed to parse the game instance, installation cannot continue. version.empty=No Instances version.empty.add=Add new instance version.empty.launch=No instances. You can install one in "Download → New Game". @@ -1326,7 +1326,7 @@ version.launch=Launch Game version.launch.test=Test Launch version.switch=Switch Instance version.launch_script=Export Launch Script -version.launch_script.failed=Unable to export launch script. +version.launch_script.failed=Failed to export launch script. version.launch_script.save=Export Launch Script version.launch_script.success=Exported launch script as %s. version.manage=All Instances @@ -1347,7 +1347,7 @@ version.manage.remove_assets=Delete All Assets version.manage.remove_libraries=Delete All Libraries version.manage.rename=Rename Instance version.manage.rename.message=Enter New Instance Name -version.manage.rename.fail=Unable to rename the instance, some files might be in use, or the name contains an invalid character. +version.manage.rename.fail=Failed to rename the instance, some files might be in use, or the name contains an invalid character. version.settings=Settings version.update=Update Modpack diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 20d3c8f8c0..9a6e59b4dd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -743,7 +743,7 @@ world.import.failed=Не удаётся импортировать этот ми world.import.invalid=Не удаётся разобрать сохранение. world.info.title=Сведения о мире %s world.info.basic=Основные сведения -world.info.allow_cheats=Разрешить читы +world.info.allow_cheats=Разрешить команды/читы world.info.dimension.the_nether=Нижний мир world.info.dimension.the_end=Край world.info.difficulty=Сложность diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 030bcbf524..f8ff29377d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -855,7 +855,7 @@ world.import.failed=無法匯入此世界: %s world.import.invalid=無法識別的存檔壓縮檔 world.info.title=世界 [%s] - 世界資訊 world.info.basic=基本資訊 -world.info.allow_cheats=允許指令 +world.info.allow_cheats=允許指令(作弊) world.info.dimension.the_nether=地獄 world.info.dimension.the_end=末地 world.info.difficulty=難易度 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 8354f852f2..f4357d2d26 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -867,7 +867,7 @@ world.import.failed=无法导入此世界:%s world.import.invalid=无法识别该存档压缩包 world.info.title=世界 [%s] - 世界信息 world.info.basic=基本信息 -world.info.allow_cheats=允许作弊 +world.info.allow_cheats=允许命令(作弊) world.info.dimension.the_nether=下界 world.info.dimension.the_end=末地 world.info.difficulty=难度 From 3dde2d19e2f4e6a7f0b390f2bfeda1ccdc4432fe Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Fri, 8 Nov 2024 05:59:02 +0800 Subject: [PATCH 103/169] Fix extra "=" in zh_CN `launch.advice` translation (#3430) Closes #3429 --- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f4357d2d26..0e7440269c 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -561,7 +561,7 @@ java.uninstall.confirm=你确定要卸载此 Java 吗?此操作无法撤销! lang=简体中文 lang.default=跟随系统语言 -launch.advice==%s 是否继续启动? +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 及更低版本。 From 1d0ae427bf56341c4653e1c0bcd51d08437addc3 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 9 Nov 2024 19:39:09 +0800 Subject: [PATCH 104/169] Update JavaVersionConstraint: 1.20.5 requires Java 21 (#3434) --- .../java/org/jackhuang/hmcl/game/LauncherHelper.java | 3 +++ .../org/jackhuang/hmcl/game/JavaVersionConstraint.java | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) 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 61725887c7..79205c479d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -522,6 +522,9 @@ else if (violatedMandatoryConstraints.contains(JavaVersionConstraint.VANILLA)) case MODDED_JAVA_17: suggestions.add(i18n("launch.advice.modded_java", 17, gameVersion)); break; + case MODDED_JAVA_21: + suggestions.add(i18n("launch.advice.modded_java", 21, gameVersion)); + break; case VANILLA_JAVA_8_51: suggestions.add(i18n("launch.advice.java8_51_1_13")); break; 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 dc7abb453c..ed1889fccc 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java @@ -62,7 +62,14 @@ protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nul return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE); } }, - MODDED_JAVA_17(false, GameVersionNumber.atLeast("1.18"), VersionNumber.between("17", "17.999")) { + 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) { From c1ae5875baf0c63e5887d0de364b940b81dc0425 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 10 Nov 2024 13:01:50 +0800 Subject: [PATCH 105/169] =?UTF-8?q?=E5=B0=86=20VERSION=5FROOT=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E8=87=B3=203.6=20(#3431)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/build.gradle.kts b/HMCL/build.gradle.kts index 011620e2b0..645a055d09 100644 --- a/HMCL/build.gradle.kts +++ b/HMCL/build.gradle.kts @@ -25,7 +25,7 @@ val buildNumber = System.getenv("BUILD_NUMBER")?.toInt().let { number -> if (!shortCommit.isNullOrEmpty()) "$prefix-$shortCommit" else "SNAPSHOT" } } -val versionRoot = System.getenv("VERSION_ROOT") ?: "3.5" +val versionRoot = System.getenv("VERSION_ROOT") ?: "3.6" val versionType = System.getenv("VERSION_TYPE") ?: if (isOfficial) "nightly" else "unofficial" val microsoftAuthId = System.getenv("MICROSOFT_AUTH_ID") ?: "" From 9a0db56ac37a49fcba8894077e0dde304faf1e57 Mon Sep 17 00:00:00 2001 From: Wulian <1055917385@qq.com> Date: Sun, 10 Nov 2024 19:02:59 +0800 Subject: [PATCH 106/169] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20Copyright=20=C2=A9?= =?UTF-8?q?=20=E6=98=BE=E7=A4=BA=E4=B8=BA=E2=80=9C=E6=BC=8F=E2=80=9D?= =?UTF-8?q?=E7=9A=84bug=20(#3437)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #3436 Specify UTF-8 charset when reading `deps.json` file in `AboutPage.java`. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/HMCL-dev/HMCL/issues/3436?shareId=XXXX-XXXX-XXXX-XXXX). --- HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java index 9d84d53996..f250384566 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java @@ -36,6 +36,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.nio.charset.StandardCharsets; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -116,7 +117,7 @@ private static ComponentList loadIconedTwoLineList(String path) { return componentList; } - try (Reader reader = new InputStreamReader(input)) { + try (Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) { JsonArray array = JsonUtils.GSON.fromJson(reader, JsonArray.class); for (JsonElement element : array) { From 2ca7e7c830a9be0363dd0b583c1882f74f8a796b Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Sun, 10 Nov 2024 21:27:36 +0800 Subject: [PATCH 107/169] =?UTF-8?q?Fix=20#3200:=20=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E6=97=B6=E4=B8=8D=E5=BA=94=E8=A1=A5=E5=85=A8=20Modrinth=20?= =?UTF-8?q?=E6=95=B4=E5=90=88=E5=8C=85=E4=B8=AD=E5=B7=B2=E7=A6=81=E7=94=A8?= =?UTF-8?q?=E7=9A=84=20mod=20(#3308)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update ModrinthCompletionTask.java * Update ModrinthCompletionTask.java * Update ModrinthCompletionTask.java * Update ModrinthCompletionTask.java * Update ModrinthCompletionTask.java * update * update * update * update * update * update * update --------- Co-authored-by: Glavo --- .../mod/modrinth/ModrinthCompletionTask.java | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthCompletionTask.java index 3150a34578..c0fa257f64 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthCompletionTask.java @@ -19,6 +19,7 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.game.DefaultGameRepository; +import org.jackhuang.hmcl.mod.ModManager; import org.jackhuang.hmcl.mod.ModpackCompletionException; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Task; @@ -27,6 +28,7 @@ import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -41,6 +43,7 @@ public class ModrinthCompletionTask extends Task { private final DefaultDependencyManager dependency; private final DefaultGameRepository repository; + private final ModManager modManager; private final String version; private ModrinthManifest manifest; private final List> dependencies = new ArrayList<>(); @@ -69,6 +72,7 @@ public ModrinthCompletionTask(DefaultDependencyManager dependencyManager, String public ModrinthCompletionTask(DefaultDependencyManager dependencyManager, String version, ModrinthManifest manifest) { this.dependency = dependencyManager; this.repository = dependencyManager.getGameRepository(); + this.modManager = repository.getModManager(version); this.version = version; this.manifest = manifest; @@ -99,18 +103,28 @@ public void execute() throws Exception { if (manifest == null) return; - Path runDirectory = repository.getRunDirectory(version).toPath(); + Path runDirectory = repository.getRunDirectory(version).toPath().toAbsolutePath().normalize(); + Path modsDirectory = runDirectory.resolve("mods"); for (ModrinthManifest.File file : manifest.getFiles()) { if (file.getEnv() != null && file.getEnv().getOrDefault("client", "required").equals("unsupported")) continue; - Path filePath = runDirectory.resolve(file.getPath()); - if (!Files.exists(filePath) && !file.getDownloads().isEmpty()) { - FileDownloadTask task = new FileDownloadTask(file.getDownloads().get(0), filePath.toFile()); - task.setCacheRepository(dependency.getCacheRepository()); - task.setCaching(true); - dependencies.add(task.withCounter("hmcl.modpack.download")); - } + if (file.getDownloads().isEmpty()) + continue; + + Path filePath = runDirectory.resolve(file.getPath()).toAbsolutePath().normalize(); + if (!filePath.startsWith(runDirectory)) + throw new IOException("Unsecure path: " + file.getPath()); + + if (Files.exists(filePath)) + continue; + if (modsDirectory.equals(filePath.getParent()) && this.modManager.hasSimpleMod(FileUtils.getName(filePath))) + continue; + + FileDownloadTask task = new FileDownloadTask(file.getDownloads(), filePath.toFile()); + task.setCacheRepository(dependency.getCacheRepository()); + task.setCaching(true); + dependencies.add(task.withCounter("hmcl.modpack.download")); } if (!dependencies.isEmpty()) { From 70ecbc734ee247499cce3584d3cbcf6b3f6408c3 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 10 Nov 2024 23:19:14 +0800 Subject: [PATCH 108/169] =?UTF-8?q?Fix=20#3438:=20=E4=BF=AE=E5=A4=8D=20Min?= =?UTF-8?q?ecraft=201.20.2+Forge=20=E9=BB=98=E8=AE=A4=E5=9B=BE=E6=A0=87?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98=20(#3439)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java index d7ac46571e..e88e140397 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java @@ -170,6 +170,7 @@ public static boolean isModded(VersionProvider provider, Version version) { Version resolvedVersion = version.resolve(provider); String mainClass = resolvedVersion.getMainClass(); return mainClass != null && (LAUNCH_WRAPPER_MAIN.equals(mainClass) + || mainClass.startsWith("net.minecraftforge") || mainClass.startsWith("net.fabricmc") || mainClass.startsWith("org.quiltmc") || mainClass.startsWith("cpw.mods")); From 861223e909f79dcc91aeab75c30cebedc5c268d5 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 11 Nov 2024 02:30:41 +0800 Subject: [PATCH 109/169] =?UTF-8?q?=E6=B8=85=E7=90=86=20GameJavaVersion=20?= =?UTF-8?q?(#3441)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 清理 GameJavaVersion * update --- .../jackhuang/hmcl/game/GameJavaVersion.java | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) 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 5f5afda69c..e02f9eafe0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameJavaVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameJavaVersion.java @@ -33,7 +33,7 @@ public final class GameJavaVersion { public static final GameJavaVersion LATEST = JAVA_21; public static GameJavaVersion getMinimumJavaVersion(GameVersionNumber gameVersion) { - if (gameVersion.compareTo("1.21") >= 0) + if (gameVersion.compareTo("1.20.5") >= 0) return JAVA_21; if (gameVersion.compareTo("1.18") >= 0) return JAVA_17; @@ -59,21 +59,6 @@ public static GameJavaVersion get(int major) { } } - public static boolean isSupportedPlatform(Platform platform) { - OperatingSystem os = platform.getOperatingSystem(); - Architecture arch = platform.getArchitecture(); - switch (arch) { - case X86: - return os == OperatingSystem.WINDOWS || os == OperatingSystem.LINUX; - case X86_64: - return os == OperatingSystem.WINDOWS || os == OperatingSystem.LINUX || os == OperatingSystem.OSX; - case ARM64: - return os == OperatingSystem.WINDOWS || os == OperatingSystem.OSX; - default: - return false; - } - } - public static List getSupportedVersions(Platform platform) { OperatingSystem operatingSystem = platform.getOperatingSystem(); Architecture architecture = platform.getArchitecture(); From c7cc2d073359d576ead4f6f6ad85f72cf2b9e04c Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Mon, 11 Nov 2024 19:20:28 +0800 Subject: [PATCH 110/169] Fix missing i18n when checking for updates fails (#3444) * Fix missing i18n when checking for updates fails * Revise translation --- .../java/org/jackhuang/hmcl/ui/versions/ModListPage.java | 2 +- .../java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java | 2 +- HMCL/src/main/resources/assets/lang/I18N.properties | 5 +++-- HMCL/src/main/resources/assets/lang/I18N_es.properties | 3 ++- HMCL/src/main/resources/assets/lang/I18N_ja.properties | 3 ++- HMCL/src/main/resources/assets/lang/I18N_ru.properties | 3 ++- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 3 ++- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 3 ++- 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index cdbb333503..5ce5eddbd1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -192,7 +192,7 @@ public void checkUpdates() { }) .whenComplete(Schedulers.javafx(), (result, exception) -> { if (exception != null || result == null) { - Controllers.dialog("Failed to check updates", "failed", MessageDialogPane.MessageType.ERROR); + Controllers.dialog(i18n("mods.check_updates.failed_check"), i18n("message.failed"), MessageDialogPane.MessageType.ERROR); } else if (result.isEmpty()) { Controllers.dialog(i18n("mods.check_updates.empty")); } else { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java index 791ba21c4d..fcd2841046 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java @@ -139,7 +139,7 @@ private void updateMods() { task.whenComplete(Schedulers.javafx(), exception -> { fireEvent(new PageCloseEvent()); if (!task.getFailedMods().isEmpty()) { - Controllers.dialog(i18n("mods.check_updates.failed") + "\n" + + Controllers.dialog(i18n("mods.check_updates.failed_download") + "\n" + task.getFailedMods().stream().map(LocalModFile::getFileName).collect(Collectors.joining("\n")), i18n("install.failed"), MessageDialogPane.MessageType.ERROR); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index afa765ec70..cdb2ba7c55 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -816,7 +816,7 @@ logwindow.export_dump.no_dependency=Your Java does not contain the dependencies main_page=Home -message.cancelled=Operation canceled +message.cancelled=Operation Canceled message.confirm=Confirm message.copied=Copied to clipboard message.default=Default @@ -985,7 +985,8 @@ mods.channel.release=Release mods.check_updates=Check for Updates mods.check_updates.current_version=Current Version mods.check_updates.empty=All mods are up-to-date -mods.check_updates.failed=Failed to download some files. +mods.check_updates.failed_check=Failed to check for updates. +mods.check_updates.failed_download=Failed to download some files. mods.check_updates.file=File mods.check_updates.source=Source mods.check_updates.target_version=Target Version diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index b2d6c5f9a9..551a0c4dd6 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -830,7 +830,8 @@ mods.add.success=%s fue instalado con éxito. mods.category=Categoría mods.check_updates=Comprobar actualizaciones mods.check_updates.current_version=Versión actual -mods.check_updates.failed=No se han podido descargar algunos de los archivos. +mods.check_updates.failed_check=No se ha podido comprobar si hay actualizaciones. +mods.check_updates.failed_download=No se han podido descargar algunos de los archivos. mods.check_updates.file=Archivo mods.check_updates.source=Fuente mods.check_updates.target_version=Versión de destino diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 7a5d28b395..a630f26e82 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -665,7 +665,8 @@ mods.add.success=mods %s が正常に追加されました。 mods.category=Category mods.check_updates=更新を確認 mods.check_updates.current_version=Current -mods.check_updates.failed=一部のファイルのダウンロードに失敗しました +mods.check_updates.failed_check=更新のチェックに失敗しました +mods.check_updates.failed_download=一部のファイルのダウンロードに失敗しました mods.check_updates.file=ファイル mods.check_updates.source=Source mods.check_updates.target_version=Target diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 9a6e59b4dd..e0d58deb40 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -696,7 +696,8 @@ mods.add.success=%s был успешно установлен. mods.category=Категория mods.check_updates=Проверить обновления mods.check_updates.current_version=Текущая версия -mods.check_updates.failed=Не удаётся скачать некоторые файлы. +mods.check_updates.failed_check=Не удалось проверить обновления. +mods.check_updates.failed_download=Не удаётся скачать некоторые файлы. mods.check_updates.file=Файл mods.check_updates.source=Источник mods.check_updates.target_version=Целевая версия diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index f8ff29377d..9cee9c7870 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -790,7 +790,8 @@ mods.channel.release=Release mods.check_updates=檢查模組更新 mods.check_updates.current_version=目前版本 mods.check_updates.empty=沒有需要更新的模組 -mods.check_updates.failed=部分檔案下載失敗 +mods.check_updates.failed_check=檢查更新失敗 +mods.check_updates.failed_download=部分檔案下載失敗 mods.check_updates.file=檔案 mods.check_updates.source=來源 mods.check_updates.target_version=目標版本 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 0e7440269c..c1f2d25f9b 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -801,7 +801,8 @@ mods.channel.release=稳定版本 mods.check_updates=检查模组更新 mods.check_updates.current_version=当前版本 mods.check_updates.empty=没有需要更新的模组 -mods.check_updates.failed=部分文件下载失败 +mods.check_updates.failed_check=检查更新失败 +mods.check_updates.failed_download=部分文件下载失败 mods.check_updates.file=文件 mods.check_updates.source=来源 mods.check_updates.target_version=目标版本 From b400a9a3ef14a791a66e05e7635db633a09e3ba2 Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 12 Nov 2024 14:24:15 +0800 Subject: [PATCH 111/169] =?UTF-8?q?=E4=BD=BF=E6=9C=80=E5=B0=8F=E5=8C=96?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E5=B1=85=E4=B8=AD=20(#3450)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修复最小化按钮未居中的问题 * update --- HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java | 1 + .../jackhuang/hmcl/ui/decorator/DecoratorSkin.java | 13 +------------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java index 618eb270ad..f0efac676a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java @@ -59,6 +59,7 @@ public enum SVG { ALERT_OUTLINE("M12,2L1,21H23M12,6L19.53,19H4.47M11,10V14H13V10M11,16V18H13V16"), PLUS("M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z"), PLUS_CIRCLE_OUTLINE("M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M13,7H11V11H7V13H11V17H13V13H17V11H13V7Z"), + MINUS("M19 13H5V11H19V13Z"), IMPORT_ICON("M14,12L10,8V11H2V13H10V16M20,18V6C20,4.89 19.1,4 18,4H6A2,2 0 0,0 4,6V9H6V6H18V18H6V15H4V18A2,2 0 0,0 6,20H18A2,2 0 0,0 20,18Z"), EXPORT("M23,12L19,8V11H10V13H19V16M1,18V6C1,4.89 1.9,4 3,4H15A2,2 0 0,1 17,6V9H15V6H3V18H15V15H17V18A2,2 0 0,1 15,20H3A2,2 0 0,1 1,18Z"), OPEN_IN_NEW("M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z"), diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index 161bb51be0..5bc5e1b50d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -18,10 +18,8 @@ package org.jackhuang.hmcl.ui.decorator; import com.jfoenix.controls.JFXButton; -import com.jfoenix.svg.SVGGlyph; import javafx.beans.binding.Bindings; import javafx.collections.ListChangeListener; -import javafx.css.PseudoClass; import javafx.geometry.Bounds; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -44,13 +42,8 @@ import org.jackhuang.hmcl.ui.animation.ContainerAnimations; import org.jackhuang.hmcl.ui.animation.TransitionPane; import org.jackhuang.hmcl.ui.wizard.Navigation; -import org.jackhuang.hmcl.util.Lang; public class DecoratorSkin extends SkinBase { - private static final PseudoClass TRANSPARENT = PseudoClass.getPseudoClass("transparent"); - private static final SVGGlyph minus = Lang.apply(new SVGGlyph(0, "MINUS", "M804.571 420.571v109.714q0 22.857-16 38.857t-38.857 16h-694.857q-22.857 0-38.857-16t-16-38.857v-109.714q0-22.857 16-38.857t38.857-16h694.857q22.857 0 38.857 16t16 38.857z", Color.WHITE), - glyph -> { glyph.setSize(12, 2); glyph.setTranslateY(4); }); - private final StackPane root, parent; private final StackPane titleContainer; private final Stage primaryStage; @@ -69,8 +62,6 @@ public DecoratorSkin(Decorator control) { primaryStage = control.getPrimaryStage(); - minus.fillProperty().bind(Theme.foregroundFillBinding()); - Decorator skinnable = getSkinnable(); root = new StackPane(); root.getStyleClass().add("window"); @@ -202,9 +193,7 @@ public DecoratorSkin(Decorator control) { btnHelp.setOnAction(e -> FXUtils.openLink("https://docs.hmcl.net/help.html")); JFXButton btnMin = new JFXButton(); - StackPane pane = new StackPane(minus); - pane.setAlignment(Pos.CENTER); - btnMin.setGraphic(pane); + btnMin.setGraphic(SVG.MINUS.createIcon(Theme.foregroundFillBinding(), -1, -1)); btnMin.getStyleClass().add("jfx-decorator-button"); btnMin.setOnAction(e -> skinnable.minimize()); From 60ac16a3eaf1ad594f1ada8efb8201f1ed4af21f Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Wed, 13 Nov 2024 22:14:55 +0800 Subject: [PATCH 112/169] Revise Chinese (#3454) * Revise Chinese - Simplified Chinese only - Minor revision * oops... --- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c1f2d25f9b..ca68a515c7 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -434,7 +434,7 @@ game.crash.reason.jdk_9=当前游戏由于 Java 版本过高,无法继续运 game.crash.reason.jvm_32bit=当前游戏由于内存分配过大,超过了 32 位 Java 内存限制,无法继续运行。\n如果你的电脑是 64 位系统,请下载安装并更换 64 位 Java。下载 Java\n如果你的电脑是 32 位系统,你或许可以重新安装 64 位系统,或换一台新电脑。\n或者,你可以在“(全局/版本特定) 游戏设置 → 游戏内存”中关闭“自动分配内存”,并且把内存限制调节为 1024 MB 或以下。 game.crash.reason.loading_crashed_forge=当前游戏由于模组“%1$s (%2$s)”错误,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 game.crash.reason.loading_crashed_fabric=当前游戏由于模组“%1$s”错误,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 -game.crash.reason.memory_exceeded=当前游戏由于分配的内存过大,无法继续运行。\n该问题是由于系统页面文件太小导致的。\n你需要在全局(特定)游戏设置中关闭游戏内存的自动分配,并将游戏内存调低至游戏能正常启动为止。\n你还可以尝试将 虚拟内存 设置调整至「自动管理所有驱动器分页文件大小」,详情。 +game.crash.reason.memory_exceeded=当前游戏由于分配的内存过大,无法继续运行。\n该问题是由于系统页面文件太小导致的。\n你需要在全局(特定)游戏设置中关闭游戏内存的自动分配,并将游戏内存调低至游戏能正常启动为止。\n你还可以尝试将虚拟内存设置调整为“自动管理所有驱动器分页文件大小”,详情。 game.crash.reason.mac_jdk_8u261=当前游戏由于你所使用的 Forge/OptiFine 与 Java 冲突而崩溃。\n请尝试更新 Forge/OptiFine,或使用 Java 8u251 及更早版本启动。 game.crash.reason.mod=当前游戏由于“%1$s”的问题,无法继续运行。\n你可以更新或删除已经安装的“%1$s”再试。 game.crash.reason.mod_resolution=当前游戏由于模组依赖问题,无法继续运行。Fabric 提供了如下信息:\n%1$s From dd1829d8cada2d80441798d518fcf67b323f1033 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Thu, 14 Nov 2024 09:27:45 +0800 Subject: [PATCH 113/169] =?UTF-8?q?Check=20word=20=E5=85=B6=E5=AE=83=20?= =?UTF-8?q?=E2=86=92=20=E5=85=B6=E4=BB=96=20when=20checking=20translation?= =?UTF-8?q?=20(#3455)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is some controversy over the use of this word. In order to ensure consistency in formal texts, we should unify them to more tried-and-true and commonly used usages. By checking at build time, it lets the translator or proofreader correct the word on his/her own without any special attention from the reviewer. --- build.gradle.kts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index deccd9e5c6..2317dbc93c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -94,6 +94,13 @@ tasks.create("checkTranslations") { } } + zh_CN.forEach { + if (it.value.toString().contains("其它")) { + project.logger.warn("The misspelled '其它' in '${it.key}' should be replaced by '其他'") + success = false + } + } + if (!success) { throw GradleException("Part of the translation is missing") } From e3c7278759bbc354a57698b52f923ba844823088 Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Thu, 14 Nov 2024 09:42:43 +0800 Subject: [PATCH 114/169] Update check-update.yml (#3452) --- .github/workflows/check-update.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check-update.yml b/.github/workflows/check-update.yml index 65cab990ed..db7cc514fc 100644 --- a/.github/workflows/check-update.yml +++ b/.github/workflows/check-update.yml @@ -69,6 +69,7 @@ jobs: target_commitish: ${{ env.HMCL_COMMIT_SHA }} name: ${{ env.HMCL_TAG_NAME }} tag_name: ${{ env.HMCL_TAG_NAME }} + prerelease: ture stable-check-update: if: ${{ github.repository_owner == 'HMCL-dev' }} needs: dev-check-update From 6e48dbd6c6d2ed98c3dea31b725ae208a476bbd8 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Thu, 14 Nov 2024 09:58:14 +0800 Subject: [PATCH 115/169] Fix dialog title when modpack download fails (#3451) * Fix dialog title when modpack download fails * Update --- .../main/java/org/jackhuang/hmcl/ui/versions/Versions.java | 4 ++-- HMCL/src/main/resources/assets/lang/I18N.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java index 2b6277d427..94bdc1cd18 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java @@ -83,7 +83,7 @@ public static void downloadModpackImpl(Profile profile, String version, RemoteMo } catch (IOException e) { Controllers.dialog( i18n("install.failed.downloading.detail", file.getFile().getUrl()) + "\n" + StringUtils.getStackTrace(e), - i18n("download.failed.no_code", file.getFile().getUrl()), MessageDialogPane.MessageType.ERROR); + i18n("download.failed.no_code"), MessageDialogPane.MessageType.ERROR); return; } Controllers.taskDialog( @@ -96,7 +96,7 @@ public static void downloadModpackImpl(Profile profile, String version, RemoteMo } else { Controllers.dialog( i18n("install.failed.downloading.detail", file.getFile().getUrl()) + "\n" + StringUtils.getStackTrace(e), - i18n("download.failed.no_code", file.getFile().getUrl()), MessageDialogPane.MessageType.ERROR); + i18n("download.failed.no_code"), MessageDialogPane.MessageType.ERROR); } }).executor(true), i18n("message.downloading"), diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index cdb2ba7c55..08f2be0300 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -328,7 +328,7 @@ download.existing=The file cannot be saved because it already exists. You can cl download.external_link=Visit Download Website download.failed=Failed to download "%1$s", response code: %2$d. download.failed.empty=No versions are available. Please click here to go back. -download.failed.no_code=Failed to download "%s". +download.failed.no_code=Failed to download download.failed.refresh=Failed to fetch version list. Please click here to retry. download.game=New Game download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) @@ -664,7 +664,7 @@ install=New Instance install.change_version=Change Version install.change_version.confirm=Are you sure you want to switch %s from version %s to %s? install.failed=Failed to install -install.failed.downloading=We are unable to download some required files. +install.failed.downloading=Failed to download some required files. install.failed.downloading.detail=Failed to download file: %s install.failed.downloading.timeout=Download timeout when fetching: %s install.failed.install_online=Failed to identify the provided file. If you are installing a mod, navigate to the "Mods" page. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 9cee9c7870..310e93e71a 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -328,7 +328,7 @@ download.existing=檔案已存在,無法儲存。你可以將檔案儲存至 download.external_link=打開下載網站 download.failed=下載失敗:%1$s\n錯誤碼:%2$d download.failed.empty=沒有可供安裝的版本,按一下此處返回。 -download.failed.no_code=下載失敗:%s +download.failed.no_code=下載失敗 download.failed.refresh=載入版本清單失敗,按一下此處重試。 download.game=新遊戲 download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) 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 ca68a515c7..319c525ed9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -337,7 +337,7 @@ download.existing=文件已存在,无法保存。你可以将文件保存至 download.external_link=打开下载网站 download.failed=下载失败: %1$s,\n错误码:%2$d\n你可以点击右上角帮助按钮进行求助。 download.failed.empty=[没有可供安装的版本,点击此处返回]\n(你可以点击右上角帮助按钮进行求助) -download.failed.no_code=下载失败: %s +download.failed.no_code=下载失败 download.failed.refresh=[加载版本列表失败,点击此处重试]\n(你可以点击右上角帮助按钮进行求助) download.game=新游戏 download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com) From fa66549f5383b24670fb7850dcae0f44b4c58e13 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Thu, 14 Nov 2024 09:59:15 +0800 Subject: [PATCH 116/169] Revise English (#3453) - Adjust some translation styles again - Fix some missed mistakes --- .../resources/assets/lang/I18N.properties | 158 +++++++++--------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 08f2be0300..f531eb1f45 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -193,7 +193,7 @@ color.recent=Recommended color.custom=Custom Color crash.NoClassDefFound=Please verify the integrity of this software, or try updating your Java. -crash.user_fault=The launcher crashed due to a corrupted Java or system environment. Please make sure your Java or OS is installed properly. +crash.user_fault=The launcher crashed because of corrupted Java or system environment. Please make sure your Java or OS is installed properly. curse.category.0=All @@ -351,7 +351,7 @@ exception.access_denied=HMCL is unable to access the file "%s". It may be locked For Windows users, you can open "Resource Monitor" to check if another process is currently using it. If so, you can try again after closing that process.\n\ If not, please check if your account has enough permissions to access it. exception.artifact_malformed=Cannot verify the integrity of the downloaded files. -exception.ssl_handshake=Failed to establish an SSL connection due to the lack of an SSL certificate in the current Java installation. You can try opening HMCL in another Java and try again. +exception.ssl_handshake=Failed to establish an SSL connection because the SSL certificate is missing from the current Java installation. You can try opening HMCL with another Java and try again. extension.bat=Windows Batch File (.bat) extension.mod=Mod File @@ -375,7 +375,7 @@ fatal.config_loading_failure=Cannot load configuration files.\n\ For macOS, try putting HMCL somewhere with permissions other than "Desktop", "Downloads", and "Documents" and try again. fatal.config_loading_failure.unix=Hello Minecraft! Launcher could not load the configuration file because it was created by user "%1$s".\n\ Please open HMCL as root user (not recommended), or execute the following command in the terminal to change the ownership of the configuration file to the current user:\n%2$s -fatal.mac_app_translocation=Due to macOS security mechanisms, Hello Minecraft! Launcher is isolated to a temporary directory by the OS.\n\ +fatal.mac_app_translocation=Hello Minecraft! Launcher is isolated to a temporary directory by the OS because of macOS security mechanisms.\n\ Please move HMCL to a different directory before attempting to open. Otherwise, your settings and game data may be lost after restarting.\n\ Do you still want to continue? fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher has been upgraded. Please restart the launcher. @@ -426,34 +426,34 @@ game.crash.info=Crash Info game.crash.reason=Crash Cause game.crash.reason.analyzing=Analyzing... game.crash.reason.multiple=Several reasons detected:\n\n -game.crash.reason.block=The game crashed due to a block in the world.\n\ +game.crash.reason.block=The game crashed because of a block in the world.\n\ \n\ You can try removing this block using MCEdit or deleting the mod that added it.\n\ \n\ Block Type: %1$s\n\ Location: %2$s -game.crash.reason.bootstrap_failed=The game crashed due to mod "%1$s".\n\ +game.crash.reason.bootstrap_failed=The game crashed because of the "%1$s" mod.\n\ \n\ You can try deleting or updating it. -game.crash.reason.config=The game crashed due to a mod "%1$s" cannot parse its config file "%2$s". -game.crash.reason.debug_crash=The game crashed due to you triggering it manually. So you probably know why. -game.crash.reason.duplicated_mod=The game cannot continue to run due to duplicate mods "%1$s".\n\ +game.crash.reason.config=The game crashed because the mod "%1$s" could not parse its config file "%2$s". +game.crash.reason.debug_crash=The game crashed because you triggered it manually. So you probably know why :) +game.crash.reason.duplicated_mod=The game cannot continue to run because of duplicate mods "%1$s".\n\ \n\ %2$s\n\ \n\ Each mod can only be installed once. Please delete the duplicate mod and try again. -game.crash.reason.entity=The game crashed due to an entity in the world.\n\ +game.crash.reason.entity=The game crashed because of an entity in the world.\n\ \n\ You can try removing the entity using MCEdit or deleting the mod that added it.\n\ \n\ Entity Type: %1$s\n\ Location: %2$s -game.crash.reason.modmixin_failure=The game crashed due to some mod injection failure.\n\ +game.crash.reason.modmixin_failure=The game crashed because some mods failed to inject.\n\ \n\ This generally means that the mod has a bug or is incompatible with the current environment.\n\ \n\ You can check the log to find the error mod. -game.crash.reason.mod_repeat_installation=The game crashed due to duplicate mods.\n\ +game.crash.reason.mod_repeat_installation=The game crashed because of duplicate mods.\n\ \n\ Each mod can only be installed once. Please delete the duplicate mod and then relaunch the game. game.crash.reason.forge_error=Forge/NeoForge may have provided error information.\n\ @@ -462,140 +462,140 @@ game.crash.reason.forge_error=Forge/NeoForge may have provided error information \n\ If you do not see the error message, you can view the error report to understand how the error occurred.\n\ %1$s -game.crash.reason.mod_resolution0=The game crashed due to some mod problems. You can check the log to find the error mod(s). -game.crash.reason.mixin_apply_mod_failed=The game crashed due to the mixin could not be applied to the "%1$s" mod.\n\ +game.crash.reason.mod_resolution0=The game crashed because of some mod problems. You can check the logs to find the faulty mod(s). +game.crash.reason.mixin_apply_mod_failed=The game crashed because the mixin could not be applied to the mod "%1$s".\n\ \n\ You can try deleting or updating the mod to resolve the problem. -game.crash.reason.java_version_is_too_high=The game crashed due to the Java version being too high to continue running.\n\ +game.crash.reason.java_version_is_too_high=The game crashed because the Java version is too new to continue running.\n\ \n\ - Please use an earlier Java version in "Global/Instance-specific Settings → Java" and then launch the game.\n\ + Please use the previous major Java version in "Global/Instance-specific Settings → Java" and then launch the game.\n\ \n\ If not, you can download it from java.com (Java 8) or BellSoft Liberica Full JRE (Java 17) and other distributions to download and install one (restart the launcher after installation). -game.crash.reason.need_jdk11=The game crashed due to an inappropriate Java VM version.\n\ +game.crash.reason.need_jdk11=The game crashed because of an inappropriate Java VM version.\n\ \n\ You need to download and install Java 11, and set it in "Global/Instance-specific Settings → Java". -game.crash.reason.mod_name=The game crashed due to mod file name problems.\n\ +game.crash.reason.mod_name=The game crashed because of mod filename problems.\n\ \n\ Mod file names should use only English letters (Aa~Zz), numbers (0~9), hyphens (-), underscores (_), and dots (.) in half-width.\n\ \n\ Please navigate to the mod directory and add all non-compliant mod file names with one of the above compliant characters. -game.crash.reason.incomplete_forge_installation=The game cannot continue to run due to an incomplete installation of Forge/NeoForge.\n\ +game.crash.reason.incomplete_forge_installation=The game cannot continue to run because of an incomplete Forge/NeoForge installation.\n\ \n\ Please reinstall Forge/NeoForge in "Edit Instance → Loaders". game.crash.reason.fabric_version_0_12=Fabric Loader 0.12 or later is incompatible with currently installed mods. You need to downgrade it to 0.11.7. game.crash.reason.fabric_warnings=The Fabric warned:\n\ \n\ %1$s -game.crash.reason.file_already_exists=The game crashed due to file "%1$s" already exists.\n\ +game.crash.reason.file_already_exists=The game crashed because the file "%1$s" already exists.\n\ \n\ You can try backing up and deleting that file, then relaunching the game. -game.crash.reason.file_changed=The game crashed due to file "%1$s" already exists.\n\ +game.crash.reason.file_changed=The game crashed because the file "%1$s" already exists.\n\ \n\ You can try backing up and deleting that file, then relaunching the game. -game.crash.reason.gl_operation_failure=The game crashed due to some mods, shaders, or resource packs.\n\ +game.crash.reason.gl_operation_failure=The game crashed because of some mods, shaders, or resource packs.\n\ \n\ Please disable the mods, shaders, or resource packs you are using and then try again. -game.crash.reason.graphics_driver=The game crashed due to a problem with your graphics driver.\n\ +game.crash.reason.graphics_driver=The game crashed because of a problem with your graphics driver.\n\ \n\ Please try again after updating your graphics driver to the latest version.\n\ \n\ - If your PC has a discrete graphics card, you need to check whether the game uses integrated/core graphics. If so, please open the launcher using your discrete graphics card. If the problem persists, you probably should consider using a new graphics card or a new PC.\n\ + If your computer has a discrete graphics card, you need to check whether the game uses integrated/core graphics. If so, please open the launcher using your discrete graphics card. If the problem persists, you probably should consider using a new graphics card or a new computer.\n\ \n\ - If you are using your integrated graphics card, please notice that Minecraft 1.16.5 or earlier requires Java 1.8.0_51 or earlier for Intel(R) Core(TM) 3000 processor series or earlier. -game.crash.reason.macos_failed_to_find_service_port_for_display=The game cannot continue due to a failure to initialize the OpenGL window on the Apple silicon platform.\n\ + If you are using your integrated graphics card, please notice that Minecraft 1.16.5 or previous requires Java 1.8.0_51 or previous for Intel(R) Core(TM) 3000 processor series or previous. +game.crash.reason.macos_failed_to_find_service_port_for_display=The game cannot continue because the OpenGL window on the Apple silicon platform failed to initialize.\n\ \n\ For this problem, HMCL does not have direct solutions at the moment. Please try opening any browser and going fullscreen, then return to HMCL, launch the game, and quickly return to the browser page before the game window pops up, wait for the game window to appear, and then switch back to the game window. -game.crash.reason.illegal_access_error=The game crashed due to some mod(s).\n\ +game.crash.reason.illegal_access_error=The game crashed because of some mod(s).\n\ \n\ If you know this: "%1$s", you can update or delete the mod(s) and then try again. -game.crash.reason.install_mixinbootstrap=The game crashed due to missing MixinBootstrap.\n\ +game.crash.reason.install_mixinbootstrap=The game crashed because of the missing MixinBootstrap.\n\ \n\ You can try installing MixinBootstrap to resolve the problem. If it crashes after installation, try adding an exclamation mark (!) in front of the file name of this mod to try to resolve the problem. -game.crash.reason.optifine_is_not_compatible_with_forge=The game crashes due to OptiFine being incompatible with the currently installed Forge.\n\ +game.crash.reason.optifine_is_not_compatible_with_forge=The game crashed because OptiFine is not compatible with the current Forge installation.\n\ \n\ Please navigate tothe official website of OptiFine, check whether the Forge version is compatible with OptiFine, and reinstall the instance in strict accordance with the corresponding version, or change the OptiFine version in "Edit Instance → Loaders".\n\ \n\ After testing, we believe that too high or too low OptiFine versions may cause crashes. -game.crash.reason.mod_files_are_decompressed=The game crashed due to the mod file having been extracted.\n\ +game.crash.reason.mod_files_are_decompressed=The game crashed because the mod file was extracted.\n\ \n\ Please put the entire mod file directly into the mod directory!\n\ \n\ If extract will cause errors in the game, please delete the extracted mod in the mod directory and then launch the game. -game.crash.reason.shaders_mod=The game crashed due to both OptiFine and Shaders mods being installed.\n\ +game.crash.reason.shaders_mod=The game crashed because of both OptiFine and Shaders mod installed at the same time.\n\ \n\ - Just remove Shaders mod due to OptiFine having built-in support for shaders. -game.crash.reason.rtss_forest_sodium=The game crashed due to RivaTuner Statistics Server (RTSS) being incompatible with Sodium.\n\ + Just remove the Shader mod because OptiFine has built-in support for shaders. +game.crash.reason.rtss_forest_sodium=The game crashed because the RivaTuner Statistical Server (RTSS) is not compatible with Sodium.\n\ \n\ Click here for more details. -game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=The game crashed due to you having installed too many mods, which exceeds the ID limit of the game.\n\ +game.crash.reason.too_many_mods_lead_to_exceeding_the_id_limit=The game crashed because you installed too many mods and exceeded the game ID limit.\n\ \n\ Please try installingJEID or deleting some large mods. -game.crash.reason.night_config_fixes=The game crashed due to some problems with Night Config.\n\ +game.crash.reason.night_config_fixes=The game crashed because of some problems with Night Config.\n\ \n\ You can try installing the Night Config Fixes mod, which may help you with this problem.\n\ \n\ For more information, visit the GitHub repository of this mod. -game.crash.reason.optifine_causes_the_world_to_fail_to_load=The game may not continue to run due to OptiFine.\n\ +game.crash.reason.optifine_causes_the_world_to_fail_to_load=The game may not continue to run because of the OptiFine.\n\ \n\ This problem only occurs in a specific OptiFine version. You can try changing the OptiFine version in "Edit Instance → Loaders". -game.crash.reason.jdk_9=The game crashed due to the Java version being too new for this instance.\n\ +game.crash.reason.jdk_9=The game crashed because the Java version is too new for this instance.\n\ \n\ You need to download and install Java 8 and choose it in "Global/Instance-specific Settings → Java". -game.crash.reason.jvm_32bit=The game crashed due to the current memory allocation exceeding the limit of the 32-bit Java VM.\n\ +game.crash.reason.jvm_32bit=The game crashed because the current memory allocation exceeded the 32-bit Java VM limit.\n\ \n\ - If your OS is 64-bit, please install and use a 64-bit Java version. Otherwise, you may need to reinstall a 64-bit OS or get a moderner PC.\n\ + If your OS is 64-bit, please install and use a 64-bit Java version. Otherwise, you may need to reinstall a 64-bit OS or get a moderner computer.\n\ \n\ Or, you can disable the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory" and set the maximum memory allocation size to 1024 MB or below. -game.crash.reason.loading_crashed_forge=The game crashed due to mod "%1$s" (%2$s).\n\ +game.crash.reason.loading_crashed_forge=The game crashed because of the mod "%1$s" (%2$s).\n\ \n\ You can try deleting or updating it. -game.crash.reason.loading_crashed_fabric=The game crashed due to mod "%1$s".\n\ +game.crash.reason.loading_crashed_fabric=The game crashed because of the mod "%1$s".\n\ \n\ You can try deleting or updating it. -game.crash.reason.mac_jdk_8u261=The game crashed due to your current Forge or OptiFine version not being compatible with your Java installation.\n\ +game.crash.reason.mac_jdk_8u261=The game crashed because your current Forge or OptiFine version is incompatible with your Java installation.\n\ \n\ - Please try updating Forge and OptiFine, or try using Java 8u251 or earlier versions. -game.crash.reason.forge_repeat_installation=The game crashed due to a duplicate installation of Forge. This is a known problem\n\ + Please try updating Forge and OptiFine, or try using Java 8u251 or previous versions. +game.crash.reason.forge_repeat_installation=The game crashed because of a duplicate Forge installation. This is a known problem\n\ \n\ It is recommended to upload the log feedback to GitHub so that we can find more clues and resolve this problem.\n\ \n\ Currently you can uninstall Forge and reinstall it in "Edit Instance → Loaders". -game.crash.reason.optifine_repeat_installation=The game crashed due to repeated installation of OptiFine.\n\ +game.crash.reason.optifine_repeat_installation=The game crashed because of a duplicate OptiFine installation.\n\ \n\ Please delete OptiFine in the mod directory or uninstall it in "Edit Instance → Loaders". -game.crash.reason.memory_exceeded=The game crashed due to too much memory allocated for a small page file.\n\ +game.crash.reason.memory_exceeded=The game crashed because too much memory was allocated for a small page file.\n\ \n\ You can try disabling the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory" and adjust the value till the game launches.\n\ \n\ You can also try increasing the page file size in system settings. -game.crash.reason.mod=The game crashed due to the mod "%1$s".\n\ +game.crash.reason.mod=The game crashed because of the mod "%1$s".\n\ \n\ You may update or delete the mod and then try again. -game.crash.reason.mod_resolution=The game cannot continue to run due to mod dependency problems.\n\ +game.crash.reason.mod_resolution=The game cannot continue to run because of mod dependency problems.\n\ \n\ Fabric provided the following details:\n\ \n\ %1$s -game.crash.reason.forgemod_resolution=The game cannot continue to run due to mod dependency problems.\n\ +game.crash.reason.forgemod_resolution=The game cannot continue to run because of mod dependency problems.\n\ \n\ Forge/NeoForge provided the following details:\n\ %1$s -game.crash.reason.forge_found_duplicate_mods=The game crashed due to a duplicate mods problem. Forge/NeoForge provides the following information:\n\ +game.crash.reason.forge_found_duplicate_mods=The game crashed because of a duplicate mod problem. Forge/NeoForge provided the following information:\n\ %1$s game.crash.reason.mod_resolution_collection=The game crashed because the mod version is not compatible.\n\ \n\ "%1$s" requires "%2$s".\n\ \n\ You need to upgrade or downgrade %3$s before continuing. -game.crash.reason.mod_resolution_conflict=The game crashed due to conflicting mods.\n\ +game.crash.reason.mod_resolution_conflict=The game crashed because of conflicting mods.\n\ \n\ "%1$s" is incompatible with "%2$s". -game.crash.reason.mod_resolution_missing=The game crashed due to some dependency mods not being installed.\n\ +game.crash.reason.mod_resolution_missing=The game crashed because some dependent mods were not installed.\n\ \n\ "%1$s" requires mod "%2$s".\n\ \n\ This means that you have to download and install "%2$s" first to continue playing. -game.crash.reason.mod_resolution_missing_minecraft=The game crashed due to a mod being incompatible with the current Minecraft version.\n\ +game.crash.reason.mod_resolution_missing_minecraft=The game crashed because a mod is incompatible with the current Minecraft version.\n\ \n\ "%1$s" requires Minecraft version %2$s.\n\ \n\ @@ -604,31 +604,31 @@ game.crash.reason.mod_resolution_missing_minecraft=The game crashed due to a mod Otherwise, you should install a version that is compatible with this Minecraft version. game.crash.reason.mod_resolution_mod_version=%1$s (Version: %2$s) game.crash.reason.mod_resolution_mod_version.any=%1$s (Any Version) -game.crash.reason.modlauncher_8=The game crashed due to your current Forge version not being compatible with your Java installation. Please try updating Forge. -game.crash.reason.no_class_def_found_error=The game cannot continue to run due to incomplete code.\n\ +game.crash.reason.modlauncher_8=The game crashed because your current Forge version is not compatible with your Java installation. Please try updating Forge. +game.crash.reason.no_class_def_found_error=The game cannot continue to run because of incomplete code.\n\ \n\ - Your game instance is missing %1$s. This might be due to a mod missing, an incompatible mod installed, or some files being corrupted.\n\ + Your game instance is missing %1$s. This might be because a mod is missing, an incompatible mod is installed, or some files are corrupted.\n\ \n\ You may need to reinstall the game and all mods or ask someone for help. -game.crash.reason.no_such_method_error=The game cannot continue to run due to incomplete code.\n\ +game.crash.reason.no_such_method_error=The game cannot continue to run because of incomplete code.\n\ \n\ Your game instance might be missing a mod, installed an incompatible mod, or some files might be corrupted.\n\ \n\ You may need to reinstall the game and all mods or ask someone for help. -game.crash.reason.opengl_not_supported=The game crashed due to OpenGL not being supported by your graphics driver.\n\ +game.crash.reason.opengl_not_supported=The game crashed because your graphics driver does not support OpenGL.\n\ \n\ If you are streaming the game over the Internet or using a remote desktop environment, please play the game on your local one.\n\ \n\ Or, you can try updating your driver to the latest version and then try again.\n\ \n\ - If your PC has a discrete graphics card, please make sure the game is actually using it for rendering. If the problem persists, please consider getting a new graphics card or a new PC. + If your computer has a discrete graphics card, please make sure the game is actually using it for rendering. If the problem persists, please consider getting a new graphics card or a new computer. game.crash.reason.openj9=The game is unable to run on an OpenJ9 VM. Please switch to a Java that uses the Hotspot VM in "Global/Instance-specific Settings → Java" and relaunch the game. If you do not have one, you can download one online. -game.crash.reason.out_of_memory=The game crashed due to it running out of memory.\n\ +game.crash.reason.out_of_memory=The game crashed because the computer ran out of memory.\n\ \n\ Maybe because there is not enough memory available or too many mods installed. You can try resolving it by increasing the allocated memory in "Global/Instance-specific Settings → Memory".\n\ \n\ - If you still encounter these problems, you may need a better PC. -game.crash.reason.resolution_too_high=The game crashed due to the resource pack resolution being too high.\n\ + If you still encounter these problems, you may need a better computer. +game.crash.reason.resolution_too_high=The game crashed because the resource pack resolution is too high.\n\ \n\ You should switch to a resource pack with lower resolution or consider buying a better graphics card with more VRAM. game.crash.reason.stacktrace=The crash reason is unknown. You can view its details by clicking "Logs".\n\ @@ -636,11 +636,11 @@ game.crash.reason.stacktrace=The crash reason is unknown. You can view its detai There are some keywords that might contain some mod names. You can search them online to figure out the problem yourself.\n\ \n\ %s -game.crash.reason.too_old_java=The game crashed due to you using an outdated Java VM version.\n\ +game.crash.reason.too_old_java=The game crashed because you are using an outdated Java VM version.\n\ \n\ - You need to switch to a newer version (%1$s) of Java in "Global/Instance-specific Settings → Java" and then relaunch the game. You can download Java from here. + You need to switch to a newer Java version (%1$s) in "Global/Instance-specific Settings → Java" and then relaunch the game. You can download Java from here. game.crash.reason.unknown=We are not able to figure out why the game crashed. Please refer to the game logs. -game.crash.reason.unsatisfied_link_error=Failed to launch Minecraft due to missing libraries: %1$s.\n\ +game.crash.reason.unsatisfied_link_error=Failed to launch Minecraft because of missing libraries: %1$s.\n\ \n\ If you have edited the native library path, please make sure these libraries do exist. Or, please try launching again after reverting it to default.\n\ \n\ @@ -701,7 +701,7 @@ install.new_game.already_exists=This instance name already exists. Please use an install.new_game.current_game_version=Current Instance Version install.new_game.malformed=Invalid name. install.select=Choose operation -install.success=Installed successfully. +install.success=Successfully installed. java.add=Add Java java.add.failed=This Java is invalid or incompatible with the current platform. @@ -738,25 +738,25 @@ lang.default=Use System Locales 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 cause you to be unable to launch the game or affect the game experience. \nDo you still want to continue to launch? launch.advice.java.auto=The current Java VM version is not compatible with the instance.\n\nClick "Yes" to automatically choose the most compatible Java VM 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 earlier versions require Java 7 or earlier. +launch.advice.java.modded_java_7=Minecraft 1.7.2 and previous versions require Java 7 or previous. launch.advice.corrected=We have resolved the Java VM problem. If you still want to use your choice of Java version, you can disable the "Do not check Java VM 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 the "Do not check Java VM 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. launch.advice.forge2760_liteloader=Forge version 2760 is not compatible with LiteLoader. Please consider upgrading Forge to version 2773 or later. -launch.advice.forge28_2_2_optifine=Forge version 28.2.2 or later is not compatible with OptiFine. Please consider downgrading Forge to version 28.2.1 or earlier. -launch.advice.forge37_0_60=Forge versions earlier than 37.0.60 are not compatible with Java 17. Please update Forge to 37.0.60 or later, or launch the game with Java 16. +launch.advice.forge28_2_2_optifine=Forge version 28.2.2 or later is not compatible with OptiFine. Please consider downgrading Forge to version 28.2.1 or previous. +launch.advice.forge37_0_60=Forge versions previous to 37.0.60 are not compatible with Java 17. Please update Forge to 37.0.60 or later, or launch the game with Java 16. launch.advice.java8_1_13=Minecraft 1.13 and later can only be run on Java 8 or later. Please use Java 8 or later versions. -launch.advice.java8_51_1_13=Minecraft 1.13 may crash on Java 8 versions earlier than 1.8.0_51. Please install the latest Java 8 version. -launch.advice.java9=You cannot launch Minecraft 1.12 or earlier with Java 9 or later. Please use Java 8 instead. -launch.advice.modded_java=Some mods may not be compatible with newer versions of Java. It is recommended to use Java %s to launch Minecraft %s. +launch.advice.java8_51_1_13=Minecraft 1.13 may crash on Java 8 versions previous to 1.8.0_51. Please install the latest Java 8 version. +launch.advice.java9=You cannot launch Minecraft 1.12 or previous with Java 9 or later. Please use Java 8 instead. +launch.advice.modded_java=Some mods may not be compatible with newer Java versions. It is recommended to use Java %s to launch Minecraft %s. launch.advice.modlauncher8=The Forge version you are using is not compatible with the current Java version. Please try updating Forge. launch.advice.newer_java=You are using the old Java to launch the game. It is recommended to update to Java 8, otherwise some mods may cause the game to crash. -launch.advice.not_enough_space=You have allocated a memory size larger than the actual %d MB of memory installed on your PC. You may experience degraded performance or even be unable to launch the game. +launch.advice.not_enough_space=You have allocated a memory size larger than the actual %d MB of memory installed on your computer. You may experience degraded performance or even be unable to launch the game. launch.advice.require_newer_java_version=The current game version requires Java %s, but we could not find one. Do you want to download one now? launch.advice.too_large_memory_for_32bit=You have allocated a memory size larger than the memory limitation of the 32-bit Java installation. You may be unable to launch the game. -launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 or earlier only supports Java 8 for the Linux x86-64 platform because the later versions cannot load 32-bit native libraries like liblwjgl.so\n\nPlease download it from java.com or install OpenJDK 8. +launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 or previous only supports Java 8 for the Linux x86-64 platform because the later versions cannot load 32-bit native libraries like liblwjgl.so\n\nPlease download it from java.com or install OpenJDK 8. launch.advice.vanilla_x86.translation=Minecraft is not fully supported for your platform, so you may experience missing functionality or even be unable to launch the game.\nYou can download Java for the x86-64 architecture here for a full gaming experience. -launch.advice.unknown=The game cannot be launched due to the following reasons: +launch.advice.unknown=The game cannot be launched for the following reasons: launch.failed=Failed to launch launch.failed.cannot_create_jvm=We are unable to create a Java VM. It may be caused by incorrect Java VM arguments. You can try resolving it by removing all arguments you added in "Global/Instance-specific Settings → Advanced Settings → Java VM Options". launch.failed.creating_process=We are unable to create a new process. Please check your Java path.\n @@ -798,7 +798,7 @@ launcher.cache_directory.disabled=Disabled launcher.cache_directory.invalid=Failed to create a cache directory, falling back to default. launcher.contact=Contact Us launcher.crash=Hello Minecraft! Launcher has encountered a fatal error! Please copy the following log and ask for help on our Discord, QQ group, GitHub, or other Minecraft forum. -launcher.crash.java_internal_error=Hello Minecraft! Launcher has encountered a fatal error due to your Java being broken. Please uninstall your Java and download a suitable Java here. +launcher.crash.java_internal_error=Hello Minecraft! Launcher has encountered a fatal error because your Java is corrupted. Please uninstall your Java and download a suitable Java here. launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher has encountered a fatal error! Your launcher is outdated. Please update your launcher! launcher.update_java=Please update your Java version. @@ -825,7 +825,7 @@ message.downloading=Downloading message.error=Error message.failed=Operation Failed message.info=Information -message.success=Operation completed successfully +message.success=Operation successfully completed message.unknown=Unknown message.warning=Warning @@ -884,7 +884,7 @@ modpack.type.multimc=MultiMC modpack.type.multimc.export=Can be imported by Hello Minecraft! Launcher and MultiMC modpack.type.server=Auto-Update Modpack from Server modpack.type.server.export=Allows server owner to update the game instance remotely -modpack.type.server.malformed=Invalid modpack manifest. Please refer to the modpack maker to resolve this problem. +modpack.type.server.malformed=Invalid modpack manifest. Please contact the modpack maker to resolve this problem. modpack.unsupported=Unsupported modpack format modpack.update=Updating modpack modpack.wizard=Modpack Export Guide @@ -975,7 +975,7 @@ modrinth.category.512x+=512x+ mods=Mods mods.add=Add Mod mods.add.failed=Failed to add mod %s. -mods.add.success=%s was added successfully. +mods.add.success=%s was successfully added. mods.broken_dependency.title=Broken dependency mods.broken_dependency.desc=This dependency existed before, but it does not exist now. Try using another download source. mods.category=Category @@ -1012,7 +1012,7 @@ mods.mcmod.page=MCMod Page mods.mcmod.search=Search in MCMod mods.modrinth=Modrinth mods.name=Name -mods.not_modded=You must install a mod loader (Forge, NeoForge, Fabric, Quilt, or LiteLoader) first to manage your mods! +mods.not_modded=You must install a modloader (Forge, NeoForge, Fabric, Quilt, or LiteLoader) first to manage your mods! mods.restore=Restore mods.url=Official Page mods.update_modpack_mod.warning=Updating mods in a modpack can lead to irreparable results, possibly corrupting the modpack so that it cannot launch. Are you sure you want to update? From 355df211dbc6039afeba04746a400a008f07c84c Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 14 Nov 2024 17:49:27 +0800 Subject: [PATCH 117/169] =?UTF-8?q?=E5=9C=A8=E6=B8=B8=E6=88=8F=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E5=88=97=E8=A1=A8=E4=B8=AD=E6=B7=BB=E5=8A=A0=20Minecr?= =?UTF-8?q?aft=20Wiki=20=E9=93=BE=E6=8E=A5=20(#3435)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/construct/IconedTwoLineListItem.java | 22 +++++++++++-------- .../hmcl/ui/download/VersionsPage.java | 14 ++++++++++-- .../resources/assets/lang/I18N.properties | 4 ++++ .../resources/assets/lang/I18N_zh.properties | 4 ++++ .../assets/lang/I18N_zh_CN.properties | 4 ++++ 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedTwoLineListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedTwoLineListItem.java index f3f9f2d60e..8de2e245c7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedTwoLineListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedTwoLineListItem.java @@ -17,7 +17,6 @@ import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; -import org.jackhuang.hmcl.util.Lazy; import org.jackhuang.hmcl.util.StringUtils; public class IconedTwoLineListItem extends HBox { @@ -29,13 +28,8 @@ public class IconedTwoLineListItem extends HBox { private final ImageView imageView = new ImageView(); private final TwoLineListItem twoLineListItem = new TwoLineListItem(); - private final Lazy externalLinkButton = new Lazy<>(() -> { - JFXButton button = new JFXButton(); - button.getStyleClass().add("toggle-icon4"); - button.setGraphic(SVG.OPEN_IN_NEW.createIcon(Theme.blackFill(), -1, -1)); - button.setOnAction(e -> FXUtils.openLink(externalLink.get())); - return button; - }); + private JFXButton externalLinkButton; + @SuppressWarnings("FieldCanBeLocal") private final InvalidationListener observer; @@ -52,7 +46,7 @@ public IconedTwoLineListItem() { getChildren().clear(); if (image.get() != null) getChildren().add(imageView); getChildren().add(twoLineListItem); - if (StringUtils.isNotBlank(externalLink.get())) getChildren().add(externalLinkButton.get()); + if (StringUtils.isNotBlank(externalLink.get())) getChildren().add(getExternalLinkButton()); }, image, externalLink); } @@ -111,4 +105,14 @@ public void setImage(Image image) { public ImageView getImageView() { return imageView; } + + public JFXButton getExternalLinkButton() { + if (externalLinkButton == null) { + externalLinkButton = new JFXButton(); + externalLinkButton.getStyleClass().add("toggle-icon4"); + externalLinkButton.setGraphic(SVG.OPEN_IN_NEW.createIcon(Theme.blackFill(), -1, -1)); + externalLinkButton.setOnAction(e -> FXUtils.openLink(externalLink.get())); + } + return externalLinkButton; + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index 3d4a3c3efe..a64bf1aeae 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -178,7 +178,7 @@ public VersionsPage(Navigation navigation, String title, String gameVersion, Dow btnRefresh.setGraphic(wrap(SVG.REFRESH.createIcon(Theme.blackFill(), -1, -1))); Holder lastCell = new Holder<>(); - list.setCellFactory(listView -> new RemoteVersionListCell(lastCell)); + list.setCellFactory(listView -> new RemoteVersionListCell(lastCell, libraryId)); FXUtils.onClicked(list, () -> { if (list.getSelectionModel().getSelectedIndex() < 0) @@ -272,8 +272,12 @@ private static class RemoteVersionListCell extends ListCell { private final Holder lastCell; - RemoteVersionListCell(Holder lastCell) { + RemoteVersionListCell(Holder lastCell, String libraryId) { this.lastCell = lastCell; + if ("game".equals(libraryId)) { + content.getExternalLinkButton().setGraphic(SVG.EARTH.createIcon(Theme.blackFill(), -1, -1)); + FXUtils.installFastTooltip(content.getExternalLinkButton(), i18n("wiki.tooltip")); + } pane.getStyleClass().add("md-list-cell"); StackPane.setMargin(content, new Insets(10, 16, 10, 16)); @@ -307,14 +311,19 @@ public void updateItem(RemoteVersion remoteVersion, boolean empty) { case RELEASE: content.getTags().setAll(i18n("version.game.release")); content.setImage(VersionIconType.GRASS.getIcon()); + content.setExternalLink(i18n("wiki.version.game.release", remoteVersion.getGameVersion())); break; case SNAPSHOT: content.getTags().setAll(i18n("version.game.snapshot")); content.setImage(VersionIconType.COMMAND.getIcon()); + + + content.setExternalLink(i18n("wiki.version.game.snapshot", remoteVersion.getGameVersion())); break; default: content.getTags().setAll(i18n("version.game.old")); content.setImage(VersionIconType.CRAFT_TABLE.getIcon()); + content.setExternalLink(null); break; } } else { @@ -339,6 +348,7 @@ else if (remoteVersion instanceof QuiltRemoteVersion || remoteVersion instanceof content.setSubtitle(remoteVersion.getGameVersion()); else content.getTags().setAll(remoteVersion.getGameVersion()); + content.setExternalLink(null); } } } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index f531eb1f45..62a8348e37 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1352,6 +1352,10 @@ version.manage.rename.fail=Failed to rename the instance, some files might be in version.settings=Settings version.update=Update Modpack +wiki.tooltip=Minecraft Wiki Page +wiki.version.game.release=https://minecraft.wiki/w/Java_Edition_%s +wiki.version.game.snapshot=https://minecraft.wiki/w/Java_Edition_%s + wizard.prev=< Prev wizard.failed=Failed wizard.finish=Finish diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 310e93e71a..ce564a8e60 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1148,6 +1148,10 @@ version.manage.rename.fail=重新命名版本失敗,可能檔案被佔用或 version.settings=遊戲設定 version.update=更新模組包 +wiki.tooltip=Minecraft Wiki 頁面 +wiki.version.game.release=https://zh.minecraft.wiki/w/Java版%s?variant=zh-tw +wiki.version.game.snapshot=https://zh.minecraft.wiki/w/%s?variant=zh-tw + wizard.prev=< 上一步 wizard.failed=失敗 wizard.finish=完成 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 319c525ed9..652debe8a2 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1159,6 +1159,10 @@ version.manage.rename.fail=重命名版本失败,可能文件被占用或者 version.settings=游戏设置 version.update=更新整合包 +wiki.tooltip=Minecraft Wiki 页面 +wiki.version.game.release=https://zh.minecraft.wiki/w/Java版%s?variant=zh-cn +wiki.version.game.snapshot=https://zh.minecraft.wiki/w/%s?variant=zh-cn + wizard.prev=< 上一步 wizard.failed=失败 wizard.finish=完成 From 65bdb29e713c28d3f32f68a7469dff283deb350d Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 15 Nov 2024 18:02:59 +0800 Subject: [PATCH 118/169] =?UTF-8?q?=E5=9C=A8=20macOS=20=E4=B8=8A=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20JavaFX=2019.0.2.1=20(#3461)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assets/openjfx-dependencies.json | 24 +++++++++---------- javafx.gradle.kts | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/HMCL/src/main/resources/assets/openjfx-dependencies.json b/HMCL/src/main/resources/assets/openjfx-dependencies.json index cebc7ca4d6..f0f732944a 100644 --- a/HMCL/src/main/resources/assets/openjfx-dependencies.json +++ b/HMCL/src/main/resources/assets/openjfx-dependencies.json @@ -82,25 +82,25 @@ "module": "javafx.base", "groupId": "org.openjfx", "artifactId": "javafx-base", - "version": "17.0.13", + "version": "19.0.2.1", "classifier": "mac", - "sha1": "e1744403a6691aaa6b65a7e9b4ff9aad98831bb1" + "sha1": "73e422d8426aaa23e8c712b9f4d9bebf70d3bfb9" }, { "module": "javafx.graphics", "groupId": "org.openjfx", "artifactId": "javafx-graphics", - "version": "17.0.13", + "version": "19.0.2.1", "classifier": "mac", - "sha1": "dbe733470094abee56560067d0fea3ad24991d2b" + "sha1": "6ab6f3e23421fcfa04e692d9d26a8f55a830c114" }, { "module": "javafx.controls", "groupId": "org.openjfx", "artifactId": "javafx-controls", - "version": "17.0.13", + "version": "19.0.2.1", "classifier": "mac", - "sha1": "0d43a776d6c9e2622e3581ed04501e2cadcd6e65" + "sha1": "b7786b1b63e741c0e234829825fae5fef9d96c31" } ], "osx-arm64": [ @@ -108,25 +108,25 @@ "module": "javafx.base", "groupId": "org.openjfx", "artifactId": "javafx-base", - "version": "17.0.13", + "version": "19.0.2.1", "classifier": "mac-aarch64", - "sha1": "d4dc7d2864c07b56a27e39fa5691856ddccf0ba4" + "sha1": "1d0d887c492330ed527b0614d115a4f32d2d05a4" }, { "module": "javafx.graphics", "groupId": "org.openjfx", "artifactId": "javafx-graphics", - "version": "17.0.13", + "version": "19.0.2.1", "classifier": "mac-aarch64", - "sha1": "d6a49f19e90db56c134757d1bbab4935de075d45" + "sha1": "64db28799e61e0f8f51e471c732599b2a6961803" }, { "module": "javafx.controls", "groupId": "org.openjfx", "artifactId": "javafx-controls", - "version": "17.0.13", + "version": "19.0.2.1", "classifier": "mac-aarch64", - "sha1": "ad564497edc49f7a6135c3b52d360962e19a2539" + "sha1": "3a14bd5f3ebe45d344c1f2bade0fe074e6ea2a83" } ], "linux-x86_64": [ diff --git a/javafx.gradle.kts b/javafx.gradle.kts index aaa266e241..686c1e32fd 100644 --- a/javafx.gradle.kts +++ b/javafx.gradle.kts @@ -33,8 +33,8 @@ val jfxPlatforms = listOf( Platform("windows-x86", "win-x86", version = oldJfxVersion), Platform("windows-x86_64", "win"), Platform("windows-arm64", "win", groupId = "org.glavo.hmcl.openjfx", version = "18.0.2+1-arm64"), - Platform("osx-x86_64", "mac"), - Platform("osx-arm64", "mac-aarch64"), + Platform("osx-x86_64", "mac", version = oldJfxVersion), + Platform("osx-arm64", "mac-aarch64", version = oldJfxVersion), Platform("linux-x86_64", "linux"), Platform("linux-arm32", "linux-arm32-monocle", version = oldJfxVersion), Platform("linux-arm64", "linux-aarch64", version = oldJfxVersion), From 5591d92e25a1a785bc3d0d8099d033b4a5e4426e Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Fri, 15 Nov 2024 22:49:30 +0800 Subject: [PATCH 119/169] =?UTF-8?q?Fix=20#2991:=20=E5=AF=BC=E5=85=A5=20Pri?= =?UTF-8?q?smLauncher=20=E6=A0=BC=E5=BC=8F=E6=95=B4=E5=90=88=E5=8C=85?= =?UTF-8?q?=E6=97=B6=20$.jvmArgs=20=E5=8F=82=E6=95=B0=E6=9C=AA=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E7=A7=BB=E9=99=A4=E4=B8=A4=E4=BE=A7=E5=BC=95=E5=8F=B7?= =?UTF-8?q?=20(#3030)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../multimc/MultiMCInstanceConfiguration.java | 64 ++++++++++++------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java index 4cbc228c61..8a24499294 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java @@ -62,36 +62,54 @@ public final class MultiMCInstanceConfiguration implements ModpackManifest { private final MultiMCManifest mmcPack; MultiMCInstanceConfiguration(String defaultName, InputStream contentStream, MultiMCManifest mmcPack) throws IOException { + // instance.cfg is in .ini format. As it's like the .properties format, we use Properties to parse thie file. + // Maybe this will provide some problems (and it does, such as https://github.com/HMCL-dev/HMCL/issues/2991), but this workaround works, doesn't it? Properties p = new Properties(); p.load(new InputStreamReader(contentStream, StandardCharsets.UTF_8)); this.mmcPack = mmcPack; - instanceType = p.getProperty("InstanceType"); - autoCloseConsole = Boolean.parseBoolean(p.getProperty("AutoCloseConsole")); + instanceType = readValue(p, "InstanceType"); + autoCloseConsole = Boolean.parseBoolean(readValue(p, "AutoCloseConsole")); gameVersion = mmcPack != null ? mmcPack.getComponents().stream().filter(e -> "net.minecraft".equals(e.getUid())).findAny() - .orElseThrow(() -> new IOException("Malformed mmc-pack.json")).getVersion() : p.getProperty("IntendedVersion"); - javaPath = p.getProperty("JavaPath"); - jvmArgs = p.getProperty("JvmArgs"); - fullscreen = Boolean.parseBoolean(p.getProperty("LaunchMaximized")); - maxMemory = Lang.toIntOrNull(p.getProperty("MaxMemAlloc")); - minMemory = Lang.toIntOrNull(p.getProperty("MinMemAlloc")); - height = Lang.toIntOrNull(p.getProperty("MinecraftWinHeight")); - width = Lang.toIntOrNull(p.getProperty("MinecraftWinWidth")); - overrideCommands = Boolean.parseBoolean(p.getProperty("OverrideCommands")); - overrideConsole = Boolean.parseBoolean(p.getProperty("OverrideConsole")); - overrideJavaArgs = Boolean.parseBoolean(p.getProperty("OverrideJavaArgs")); - overrideJavaLocation = Boolean.parseBoolean(p.getProperty("OverrideJavaLocation")); - overrideMemory = Boolean.parseBoolean(p.getProperty("OverrideMemory")); - overrideWindow = Boolean.parseBoolean(p.getProperty("OverrideWindow")); - permGen = Lang.toIntOrNull(p.getProperty("PermGen")); - postExitCommand = p.getProperty("PostExitCommand"); - preLaunchCommand = p.getProperty("PreLaunchCommand"); - showConsole = Boolean.parseBoolean(p.getProperty("ShowConsole")); - showConsoleOnError = Boolean.parseBoolean(p.getProperty("ShowConsoleOnError")); - wrapperCommand = p.getProperty("WrapperCommand"); + .orElseThrow(() -> new IOException("Malformed mmc-pack.json")).getVersion() : readValue(p, "IntendedVersion"); + javaPath = readValue(p, "JavaPath"); + jvmArgs = readValue(p, "JvmArgs"); + fullscreen = Boolean.parseBoolean(readValue(p, "LaunchMaximized")); + maxMemory = Lang.toIntOrNull(readValue(p, "MaxMemAlloc")); + minMemory = Lang.toIntOrNull(readValue(p, "MinMemAlloc")); + height = Lang.toIntOrNull(readValue(p, "MinecraftWinHeight")); + width = Lang.toIntOrNull(readValue(p, "MinecraftWinWidth")); + overrideCommands = Boolean.parseBoolean(readValue(p, "OverrideCommands")); + overrideConsole = Boolean.parseBoolean(readValue(p, "OverrideConsole")); + overrideJavaArgs = Boolean.parseBoolean(readValue(p, "OverrideJavaArgs")); + overrideJavaLocation = Boolean.parseBoolean(readValue(p, "OverrideJavaLocation")); + overrideMemory = Boolean.parseBoolean(readValue(p, "OverrideMemory")); + overrideWindow = Boolean.parseBoolean(readValue(p, "OverrideWindow")); + permGen = Lang.toIntOrNull(readValue(p, "PermGen")); + postExitCommand = readValue(p, "PostExitCommand"); + preLaunchCommand = readValue(p, "PreLaunchCommand"); + showConsole = Boolean.parseBoolean(readValue(p, "ShowConsole")); + showConsoleOnError = Boolean.parseBoolean(readValue(p, "ShowConsoleOnError")); + wrapperCommand = readValue(p, "WrapperCommand"); name = defaultName; - notes = Optional.ofNullable(p.getProperty("notes")).orElse(""); + notes = Optional.ofNullable(readValue(p, "notes")).orElse(""); + } + + /** + * A workaround for ... + */ + private String readValue(Properties p, String key) { + String value = p.getProperty(key); + if (value == null) { + return null; + } + + int l = value.length(); + if (l >= 2 && value.charAt(0) == '"' && value.charAt(l - 1) == ':') { + return value.substring(0, l - 1); + } + return value; } public MultiMCInstanceConfiguration(String instanceType, String name, String gameVersion, Integer permGen, String wrapperCommand, String preLaunchCommand, String postExitCommand, String notes, String javaPath, String jvmArgs, boolean fullscreen, Integer width, Integer height, Integer maxMemory, Integer minMemory, boolean showConsole, boolean showConsoleOnError, boolean autoCloseConsole, boolean overrideMemory, boolean overrideJavaLocation, boolean overrideJavaArgs, boolean overrideConsole, boolean overrideCommands, boolean overrideWindow) { From 9edfe296590f38e409d07805b536d29df029532c Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Sat, 16 Nov 2024 23:29:53 +0800 Subject: [PATCH 120/169] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20#2969:=20=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=89=8D=E6=97=A5=E5=BF=97=E5=88=97=E5=87=BAmods?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E7=9A=84jar=E6=96=87=E4=BB=B6=20(#3125)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Support #2969: 启动前日志列出mods目录的jar文件 * Support #2969: 启动前日志列出mods目录jar文件 * Support #2969: 启动前日志中使用字符画列出mods目录模组文件 * Support #2969: 启动前日志中使用字符画列出mods目录模组文件 * Support #2969: 启动前日志中使用字符画列出mods目录模组文件 * Support #2969: 日志列出mods目录时不再过滤文件后缀 * Support #2969: 启动时日志列出mods目录(代码优化) * Support #2969: 启动时日志列出mods目录(不再列出Zip内容) * Support #2969 * Fix: checkstyle --------- Co-authored-by: YELANDAOKONG --- .../jackhuang/hmcl/game/LauncherHelper.java | 14 ++- .../util/io/DirectoryStructurePrinter.java | 99 +++++++++++++++++++ .../org/jackhuang/hmcl/util/io/FileUtils.java | 14 +-- 3 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/DirectoryStructurePrinter.java 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 79205c479d..e837fa1e25 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -36,10 +36,14 @@ import org.jackhuang.hmcl.setting.*; import org.jackhuang.hmcl.task.*; import org.jackhuang.hmcl.ui.*; -import org.jackhuang.hmcl.ui.construct.*; +import org.jackhuang.hmcl.ui.construct.DialogCloseEvent; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; +import org.jackhuang.hmcl.ui.construct.PromptDialogPane; +import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.i18n.I18n; +import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.ResponseCodeException; import org.jackhuang.hmcl.util.platform.*; import org.jackhuang.hmcl.util.versioning.GameVersionNumber; @@ -60,9 +64,10 @@ import static javafx.application.Platform.setImplicitExit; import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.Lang.resolveException; -import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -import static org.jackhuang.hmcl.util.platform.Platform.*; +import static org.jackhuang.hmcl.util.logging.Logger.LOG; +import static org.jackhuang.hmcl.util.platform.Platform.SYSTEM_PLATFORM; +import static org.jackhuang.hmcl.util.platform.Platform.isCompatibleWithX86Java; public final class LauncherHelper { @@ -178,6 +183,9 @@ private void launch0() { .thenComposeAsync(() -> logIn(account).withStage("launch.state.logging_in")) .thenComposeAsync(authInfo -> Task.supplyAsync(() -> { LaunchOptions launchOptions = repository.getLaunchOptions(selectedVersion, javaVersionRef.get(), profile.getGameDir(), javaAgents, scriptFile != null); + + LOG.info("Here's the structure of game mod directory:\n" + FileUtils.printFileStructure(repository.getModManager(selectedVersion).getModsDirectory(), 10)); + return new HMCLGameLauncher( repository, version.get(), diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/DirectoryStructurePrinter.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/DirectoryStructurePrinter.java new file mode 100644 index 0000000000..a07ba372b2 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/DirectoryStructurePrinter.java @@ -0,0 +1,99 @@ +package org.jackhuang.hmcl.util.io; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; + +final class DirectoryStructurePrinter { + private DirectoryStructurePrinter() { + } + + public static String list(Path path, int maxDepth) throws IOException { + StringBuilder output = new StringBuilder(128); + list(path, maxDepth, output); + output.setLength(output.length() - 1); + return output.toString(); + } + + private static void list(Path path, int maxDepth, StringBuilder output) throws IOException { + output.append("Filesystem structure of: ").append(path).append('\n'); + + if (!Files.exists(path)) { + pushMessage(output, "nonexistent path", 1); + return; + } + if (Files.isRegularFile(path)) { + pushMessage(output, "regular file path", 1); + return; + } + if (Files.isDirectory(path)) { + Files.walkFileTree(path, new FileVisitor() { + private boolean isFolderEmpty; + + private int depth = 1; + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + isFolderEmpty = true; + + pushFile(output, dir, depth); + if (depth == maxDepth) { + pushMessage(output, "too deep", depth); + return FileVisitResult.SKIP_SUBTREE; + } + + depth++; + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + isFolderEmpty = false; + + pushFile(output, file, depth); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + visitFile(file, null); + + pushMessage(output, exc.toString(), depth); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { + if (isFolderEmpty) { + pushMessage(output, "empty directory", depth); + } + + depth--; + return FileVisitResult.CONTINUE; + } + }); + return; + } + + pushMessage(output, "unknown file type", 1); + } + + private static void pushFile(StringBuilder output, Path file, int depth) { + output.append("|"); + for (int i = 1; i < depth; i++) { + output.append(" |"); + } + output.append("-> ").append(FileUtils.getName(file)).append('\n'); + } + + private static void pushMessage(StringBuilder output, String message, int depth) { + output.append("| "); + for (int i = 1; i < depth; i++) { + output.append(" | "); + } + output.append('<').append(message).append(">\n"); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java index baa444003f..ba257a94cb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java @@ -30,11 +30,7 @@ import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import java.util.function.Predicate; import static java.nio.charset.StandardCharsets.UTF_8; @@ -199,7 +195,7 @@ public static void writeText(Path file, String text, Charset charset) throws IOE * It will create the file if it does not exist, or truncate the existing file to empty for rewriting. * All bytes in byte array will be written into the file in binary format. Existing data will be erased. * - * @param file the path to the file + * @param file the path to the file * @param data the data being written to file * @throws IOException if an I/O error occurs */ @@ -212,7 +208,7 @@ public static void writeBytes(File file, byte[] data) throws IOException { * It will create the file if it does not exist, or truncate the existing file to empty for rewriting. * All bytes in byte array will be written into the file in binary format. Existing data will be erased. * - * @param file the path to the file + * @param file the path to the file * @param data the data being written to file * @throws IOException if an I/O error occurs */ @@ -591,4 +587,8 @@ public static void saveSafely(Path file, ExceptionalConsumer Date: Sun, 17 Nov 2024 22:09:29 +0800 Subject: [PATCH 121/169] Bump action-gh-release to v2 (#3469) --- .github/workflows/check-update.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-update.yml b/.github/workflows/check-update.yml index db7cc514fc..c33f23232f 100644 --- a/.github/workflows/check-update.yml +++ b/.github/workflows/check-update.yml @@ -59,7 +59,7 @@ jobs: echo "| HMCL-$HMCL_VERSION.sh | $(cat HMCL-$HMCL_VERSION.sh.sha256) |" >> RELEASE_NOTE - name: Create release if: ${{ env.continue == 'true' }} - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: body_path: RELEASE_NOTE files: | @@ -124,7 +124,7 @@ jobs: echo "| HMCL-$HMCL_VERSION.sh | $(cat HMCL-$HMCL_VERSION.sh.sha256) |" >> RELEASE_NOTE - name: Create release if: ${{ env.continue == 'true' }} - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: body_path: RELEASE_NOTE files: | From c12ae9fdf8bc223f3dc6b4a23c87537bcd4c4b5b Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:22:20 +0800 Subject: [PATCH 122/169] =?UTF-8?q?Fix=20#3460=20=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E5=A5=87=E5=BC=82=E7=9A=84=20Forge=20(Like)?= =?UTF-8?q?=20=E6=A8=A1=E7=BB=84=20Metadata=20(#3470)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/mod/modinfo/ForgeNewModMetadata.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeNewModMetadata.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeNewModMetadata.java index 4a94eff56f..ec4efb22ed 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeNewModMetadata.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeNewModMetadata.java @@ -160,12 +160,17 @@ private static LocalModFile fromFile0(String tomlPath, int loaderACC, ModLoaderT private static ModLoaderType analyzeLoader(Toml toml, String modID, int loaderACC, ModLoaderType defaultLoader) throws IOException { List> dependencies = toml.getList("dependencies." + modID); - if (dependencies != null) { - for (HashMap dependency : dependencies) { - switch ((String) dependency.get("modId")) { - case "forge": return checkLoaderACC(loaderACC, ACC_FORGE, ModLoaderType.FORGE); - case "neoforge": return checkLoaderACC(loaderACC, ACC_NEO_FORGED, ModLoaderType.NEO_FORGED); - } + if (dependencies == null) { + dependencies = toml.getList("dependencies"); // ??? I have no idea why some of the Forge mods use [[dependencies]] + if (dependencies == null) { + return defaultLoader; + } + } + + for (HashMap dependency : dependencies) { + switch ((String) dependency.get("modId")) { + case "forge": return checkLoaderACC(loaderACC, ACC_FORGE, ModLoaderType.FORGE); + case "neoforge": return checkLoaderACC(loaderACC, ACC_NEO_FORGED, ModLoaderType.NEO_FORGED); } } From 0a230ef6b5d41ee97cfde369f2a2701e132a95a0 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 23 Nov 2024 19:48:46 +0800 Subject: [PATCH 123/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20Release=20Note=20(?= =?UTF-8?q?#3472)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/check-update.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check-update.yml b/.github/workflows/check-update.yml index c33f23232f..cff9d2f278 100644 --- a/.github/workflows/check-update.yml +++ b/.github/workflows/check-update.yml @@ -54,9 +54,11 @@ jobs: echo "" >> RELEASE_NOTE echo "| File Name | SHA-256 Checksum |" >> RELEASE_NOTE echo "| --- | --- |" >> RELEASE_NOTE - echo "| HMCL-$HMCL_VERSION.exe | $(cat HMCL-$HMCL_VERSION.exe.sha256) |" >> RELEASE_NOTE - echo "| HMCL-$HMCL_VERSION.jar | $(cat HMCL-$HMCL_VERSION.jar.sha256) |" >> RELEASE_NOTE - echo "| HMCL-$HMCL_VERSION.sh | $(cat HMCL-$HMCL_VERSION.sh.sha256) |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.exe]($GH_DOWNLOAD_BASE_URL/v$HMCL_VERSION/HMCL-$HMCL_VERSION.exe) | $(cat HMCL-$HMCL_VERSION.exe.sha256) |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.jar]($GH_DOWNLOAD_BASE_URL/v$HMCL_VERSION/HMCL-$HMCL_VERSION.jar) | $(cat HMCL-$HMCL_VERSION.jar.sha256) |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.sh]($GH_DOWNLOAD_BASE_URL/v$HMCL_VERSION/HMCL-$HMCL_VERSION.sh) | $(cat HMCL-$HMCL_VERSION.sh.sha256) |" >> RELEASE_NOTE + env: + GH_DOWNLOAD_BASE_URL: https://github.com/HMCL-dev/HMCL/releases/download - name: Create release if: ${{ env.continue == 'true' }} uses: softprops/action-gh-release@v2 @@ -119,9 +121,11 @@ jobs: echo "" >> RELEASE_NOTE echo "| File Name | SHA-256 Checksum |" >> RELEASE_NOTE echo "| --- | --- |" >> RELEASE_NOTE - echo "| HMCL-$HMCL_VERSION.exe | $(cat HMCL-$HMCL_VERSION.exe.sha256) |" >> RELEASE_NOTE - echo "| HMCL-$HMCL_VERSION.jar | $(cat HMCL-$HMCL_VERSION.jar.sha256) |" >> RELEASE_NOTE - echo "| HMCL-$HMCL_VERSION.sh | $(cat HMCL-$HMCL_VERSION.sh.sha256) |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.exe]($GH_DOWNLOAD_BASE_URL/release-$HMCL_VERSION/HMCL-$HMCL_VERSION.exe) | $(cat HMCL-$HMCL_VERSION.exe.sha256) |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.jar]($GH_DOWNLOAD_BASE_URL/release-$HMCL_VERSION/HMCL-$HMCL_VERSION.jar) | $(cat HMCL-$HMCL_VERSION.jar.sha256) |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.sh]($GH_DOWNLOAD_BASE_URL/release-$HMCL_VERSION/HMCL-$HMCL_VERSION.sh) | $(cat HMCL-$HMCL_VERSION.sh.sha256) |" >> RELEASE_NOTE + env: + GH_DOWNLOAD_BASE_URL: https://github.com/HMCL-dev/HMCL/releases/download - name: Create release if: ${{ env.continue == 'true' }} uses: softprops/action-gh-release@v2 From 4c242d0c805996bc741056f1f6a1d18ad8c4edd6 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 24 Nov 2024 14:10:58 +0800 Subject: [PATCH 124/169] =?UTF-8?q?=E4=B8=8D=E5=86=8D=E7=94=9F=E6=88=90=20?= =?UTF-8?q?MD5=20checksum=20(#3473)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/HMCL/build.gradle.kts b/HMCL/build.gradle.kts index 645a055d09..ee46d63e88 100644 --- a/HMCL/build.gradle.kts +++ b/HMCL/build.gradle.kts @@ -43,7 +43,6 @@ fun digest(algorithm: String, bytes: ByteArray): ByteArray = MessageDigest.getIn fun createChecksum(file: File) { val algorithms = linkedMapOf( - "MD5" to "md5", "SHA-1" to "sha1", "SHA-256" to "sha256", "SHA-512" to "sha512" From 36da64f796d55938656745d1f4df873606979826 Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 28 Nov 2024 00:35:08 +0800 Subject: [PATCH 125/169] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8A=A0=E8=BD=BD=20?= =?UTF-8?q?WebP=20=E6=A0=BC=E5=BC=8F=E7=9A=84=E8=83=8C=E6=99=AF=E5=9B=BE?= =?UTF-8?q?=E7=89=87=20(#3457)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 支持加载 WebP 格式的背景图片 * update * update * update * update --- HMCL/build.gradle.kts | 4 + .../hmcl/game/HMCLGameRepository.java | 42 ++---- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 67 +++++++++- .../hmcl/ui/construct/MultiFileItem.java | 14 +- .../ui/decorator/DecoratorController.java | 83 ++++-------- .../hmcl/ui/export/ExportWizardProvider.java | 17 +-- .../hmcl/ui/main/PersonalizationPage.java | 4 +- .../hmcl/ui/versions/VersionIconDialog.java | 2 +- .../hmcl/ui/versions/VersionSettingsPage.java | 2 +- .../org/jackhuang/hmcl/util/SwingFXUtils.java | 124 ++++++++++++++++++ .../resources/assets/lang/I18N.properties | 3 +- .../resources/assets/lang/I18N_es.properties | 3 +- .../resources/assets/lang/I18N_ja.properties | 3 +- .../resources/assets/lang/I18N_ru.properties | 3 +- .../resources/assets/lang/I18N_zh.properties | 3 +- .../assets/lang/I18N_zh_CN.properties | 3 +- 16 files changed, 264 insertions(+), 113 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/util/SwingFXUtils.java diff --git a/HMCL/build.gradle.kts b/HMCL/build.gradle.kts index ee46d63e88..86bda3f8f1 100644 --- a/HMCL/build.gradle.kts +++ b/HMCL/build.gradle.kts @@ -37,6 +37,7 @@ version = "$versionRoot.$buildNumber" dependencies { implementation(project(":HMCLCore")) implementation("libs:JFoenix") + implementation("com.twelvemonkeys.imageio:imageio-webp:3.12.0") } fun digest(algorithm: String, bytes: ByteArray): ByteArray = MessageDigest.getInstance(algorithm).digest(bytes) @@ -110,6 +111,9 @@ tasks.getByName("sha exclude("**/package-info.class") exclude("META-INF/maven/**") + exclude("META-INF/services/javax.imageio.spi.ImageReaderSpi") + exclude("META-INF/services/javax.imageio.spi.ImageInputStreamSpi") + minimize { exclude(dependency("com.google.code.gson:.*:.*")) exclude(dependency("libs:JFoenix:.*")) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index db71cb536d..1d34d9fd36 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -33,6 +33,7 @@ import org.jackhuang.hmcl.setting.ProxyManager; import org.jackhuang.hmcl.setting.VersionIconType; import org.jackhuang.hmcl.setting.VersionSetting; +import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -43,9 +44,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.time.Instant; @@ -261,24 +260,11 @@ public VersionSetting getVersionSetting(String id) { public Optional getVersionIconFile(String id) { File root = getVersionRoot(id); - File iconFile = new File(root, "icon.png"); - if (iconFile.exists()) { - return Optional.of(iconFile); - } - - iconFile = new File(root, "icon.jpg"); - if (iconFile.exists()) { - return Optional.of(iconFile); - } - - iconFile = new File(root, "icon.bmp"); - if (iconFile.exists()) { - return Optional.of(iconFile); - } - - iconFile = new File(root, "icon.gif"); - if (iconFile.exists()) { - return Optional.of(iconFile); + for (String extension : FXUtils.IMAGE_EXTENSIONS) { + File file = new File(root, "icon." + extension); + if (file.exists()) { + return Optional.of(file); + } } return Optional.empty(); @@ -286,7 +272,7 @@ public Optional getVersionIconFile(String id) { public void setVersionIconFile(String id, File iconFile) throws IOException { String ext = FileUtils.getExtension(iconFile).toLowerCase(Locale.ROOT); - if (!ext.equals("png") && !ext.equals("jpg") && !ext.equals("bmp") && !ext.equals("gif")) { + if (!FXUtils.IMAGE_EXTENSIONS.contains(ext)) { throw new IllegalArgumentException("Unsupported icon file: " + ext); } @@ -297,11 +283,9 @@ public void setVersionIconFile(String id, File iconFile) throws IOException { public void deleteIconFile(String id) { File root = getVersionRoot(id); - - new File(root, "icon.png").delete(); - new File(root, "icon.jpg").delete(); - new File(root, "icon.bmp").delete(); - new File(root, "icon.gif").delete(); + for (String extension : FXUtils.IMAGE_EXTENSIONS) { + new File(root, "icon." + extension).delete(); + } } public Image getVersionIconImage(String id) { @@ -315,9 +299,9 @@ public Image getVersionIconImage(String id) { Version version = getVersion(id).resolve(this); Optional iconFile = getVersionIconFile(id); if (iconFile.isPresent()) { - try (InputStream inputStream = new FileInputStream(iconFile.get())) { - return new Image(inputStream); - } catch (IOException e) { + try { + return FXUtils.loadImage(iconFile.get().toPath()); + } catch (Exception e) { LOG.warning("Failed to load version icon of " + id, e); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index 5d0d684731..d42a5913b5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.controls.*; +import com.twelvemonkeys.imageio.plugins.webp.WebPImageReaderSpi; import javafx.animation.*; import javafx.application.Platform; import javafx.beans.InvalidationListener; @@ -44,6 +45,7 @@ import javafx.scene.shape.Rectangle; import javafx.scene.text.Text; import javafx.scene.text.TextFlow; +import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.util.Callback; import javafx.util.Duration; @@ -53,11 +55,9 @@ import org.glavo.png.javafx.PNGJavaFXUtils; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.animation.AnimationUtils; -import org.jackhuang.hmcl.util.Holder; -import org.jackhuang.hmcl.util.Lang; -import org.jackhuang.hmcl.util.ResourceNotFoundError; -import org.jackhuang.hmcl.util.StringUtils; +import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.io.FileUtils; +import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.javafx.ExtendedProperties; import org.jackhuang.hmcl.util.javafx.SafeStringConverter; import org.jackhuang.hmcl.util.platform.OperatingSystem; @@ -68,13 +68,15 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.*; import java.lang.ref.WeakReference; -import java.net.URI; -import java.net.URISyntaxException; +import java.net.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -113,6 +115,10 @@ private FXUtils() { public static final String DEFAULT_MONOSPACE_FONT = OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS ? "Consolas" : "Monospace"; + public static final List IMAGE_EXTENSIONS = Lang.immutableListOf( + "png", "jpg", "jpeg", "bmp", "gif", "webp" + ); + private static final Map builtinImageCache = new ConcurrentHashMap<>(); private static final Map remoteImageCache = new ConcurrentHashMap<>(); @@ -713,6 +719,50 @@ public static void setIcon(Stage stage) { stage.getIcons().add(newBuiltinImage(icon)); } + private static Image loadWebPImage(InputStream input) throws IOException { + WebPImageReaderSpi spi = new WebPImageReaderSpi(); + ImageReader reader = spi.createReaderInstance(null); + + try (ImageInputStream imageInput = ImageIO.createImageInputStream(input)) { + reader.setInput(imageInput, true, true); + return SwingFXUtils.toFXImage(reader.read(0, reader.getDefaultReadParam()), null); + } finally { + reader.dispose(); + } + } + + public static Image loadImage(Path path) throws Exception { + try (InputStream input = Files.newInputStream(path)) { + if ("webp".equalsIgnoreCase(FileUtils.getExtension(path))) + return loadWebPImage(input); + else { + Image image = new Image(input); + if (image.isError()) + throw image.getException(); + return image; + } + } + } + + public static Image loadImage(URL url) throws Exception { + URLConnection connection = NetworkUtils.createConnection(url); + if (connection instanceof HttpURLConnection) { + connection = NetworkUtils.resolveConnection((HttpURLConnection) connection); + } + + try (InputStream input = connection.getInputStream()) { + String path = url.getPath(); + if (path != null && "webp".equalsIgnoreCase(StringUtils.substringAfterLast(path, '.'))) + return loadWebPImage(input); + else { + Image image = new Image(input); + if (image.isError()) + throw image.getException(); + return image; + } + } + } + /** * Suppress IllegalArgumentException since the url is supposed to be correct definitely. * @@ -1034,4 +1084,9 @@ public static String toWeb(Color color) { return String.format("#%02x%02x%02x", r, g, b); } + + public static FileChooser.ExtensionFilter getImageExtensionFilter() { + return new FileChooser.ExtensionFilter(i18n("extension.png"), + IMAGE_EXTENSIONS.stream().map(ext -> "*." + ext).toArray(String[]::new)); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java index d7e224baa0..70b8c2247f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java @@ -21,7 +21,6 @@ import com.jfoenix.controls.JFXTextField; import com.jfoenix.validation.base.ValidatorBase; import javafx.beans.property.*; -import javafx.collections.ObservableList; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; @@ -114,6 +113,7 @@ public void setFallbackData(T fallbackData) { public static class Option { protected final String title; protected String subtitle; + protected String tooltip; protected final T data; protected final BooleanProperty selected = new SimpleBooleanProperty(); protected final JFXRadioButton left = new JFXRadioButton(); @@ -140,6 +140,11 @@ public Option setSubtitle(String subtitle) { return this; } + public Option setTooltip(String tooltip) { + this.tooltip = tooltip; + return this; + } + public boolean isSelected() { return left.isSelected(); } @@ -161,6 +166,8 @@ protected Node createItem(ToggleGroup group) { BorderPane.setAlignment(left, Pos.CENTER_LEFT); left.setToggleGroup(group); left.setUserData(data); + if (StringUtils.isNotBlank(tooltip)) + FXUtils.installFastTooltip(left, tooltip); pane.setLeft(left); if (StringUtils.isNotBlank(subtitle)) { @@ -268,8 +275,9 @@ public FileOption setChooserTitle(String chooserTitle) { return this; } - public ObservableList getExtensionFilters() { - return selector.getExtensionFilters(); + public FileOption addExtensionFilter(FileChooser.ExtensionFilter filter) { + selector.getExtensionFilters().add(filter); + return this; } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java index 7b7b552292..2d0d555a0d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java @@ -49,13 +49,10 @@ import org.jackhuang.hmcl.ui.construct.StackContainerPane; import org.jackhuang.hmcl.ui.wizard.Refreshable; import org.jackhuang.hmcl.ui.wizard.WizardProvider; -import org.jackhuang.hmcl.util.io.NetworkUtils; +import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; import java.net.URL; -import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -180,23 +177,13 @@ private Background getBackground() { case CUSTOM: String backgroundImage = config().getBackgroundImage(); if (backgroundImage != null) - image = tryLoadImage(Paths.get(backgroundImage)).orElse(null); + image = tryLoadImage(Paths.get(backgroundImage)); break; case NETWORK: String backgroundImageUrl = config().getBackgroundImageUrl(); if (backgroundImageUrl != null) { try { - URLConnection connection = NetworkUtils.createConnection(new URL(backgroundImageUrl)); - if (connection instanceof HttpURLConnection) { - connection = NetworkUtils.resolveConnection((HttpURLConnection) connection); - } - - try (InputStream input = connection.getInputStream()) { - image = new Image(input); - if (image.isError()) { - throw image.getException(); - } - } + image = FXUtils.loadImage(new URL(backgroundImageUrl)); } catch (Exception e) { LOG.warning("Couldn't load background image", e); } @@ -218,73 +205,57 @@ private Background getBackground() { * Load background image from bg/, background.png, background.jpg, background.gif */ private Image loadDefaultBackgroundImage() { - Optional image = randomImageIn(Paths.get("bg")); - if (!image.isPresent()) { - image = tryLoadImage(Paths.get("background.png")); - } - if (!image.isPresent()) { - image = tryLoadImage(Paths.get("background.jpg")); + Image image = randomImageIn(Paths.get("bg")); + if (image != null) + return image; + + for (String extension : FXUtils.IMAGE_EXTENSIONS) { + image = tryLoadImage(Paths.get("background." + extension)); + if (image != null) + return image; } - if (!image.isPresent()) { - image = tryLoadImage(Paths.get("background.gif")); - } - return image.orElseGet(() -> newBuiltinImage("/assets/img/background.jpg")); + + return newBuiltinImage("/assets/img/background.jpg"); } - private Optional randomImageIn(Path imageDir) { + private @Nullable Image randomImageIn(Path imageDir) { if (!Files.isDirectory(imageDir)) { - return Optional.empty(); + return null; } List candidates; try (Stream stream = Files.list(imageDir)) { candidates = stream + .filter(it -> FXUtils.IMAGE_EXTENSIONS.contains(getExtension(it).toLowerCase(Locale.ROOT))) .filter(Files::isReadable) - .filter(it -> { - String ext = getExtension(it).toLowerCase(Locale.ROOT); - return ext.equals("png") || ext.equals("jpg") || ext.equals("gif"); - }) .collect(toList()); } catch (IOException e) { LOG.warning("Failed to list files in ./bg", e); - return Optional.empty(); + return null; } Random rnd = new Random(); - while (candidates.size() > 0) { + while (!candidates.isEmpty()) { int selected = rnd.nextInt(candidates.size()); - Optional loaded = tryLoadImage(candidates.get(selected)); - if (loaded.isPresent()) { + Image loaded = tryLoadImage(candidates.get(selected)); + if (loaded != null) return loaded; - } else { + else candidates.remove(selected); - } } - return Optional.empty(); + return null; } - private Optional tryLoadImage(Path path) { + private @Nullable Image tryLoadImage(Path path) { if (!Files.isReadable(path)) - return Optional.empty(); - - return tryLoadImage(path.toAbsolutePath().toUri().toString()); - } + return null; - private Optional tryLoadImage(String url) { - Image img; try { - img = new Image(url); - } catch (IllegalArgumentException e) { + return FXUtils.loadImage(path); + } catch (Exception e) { LOG.warning("Couldn't load background image", e); - return Optional.empty(); + return null; } - - if (img.getException() != null) { - LOG.warning("Couldn't load background image", img.getException()); - return Optional.empty(); - } - - return Optional.of(img); } // ==== Navigation ==== diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java index c4087f0387..12ee29fc52 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java @@ -29,6 +29,7 @@ import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.VersionSetting; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardProvider; import org.jackhuang.hmcl.util.Lang; @@ -129,17 +130,13 @@ public void execute() throws Exception { if (bg.isDirectory()) zip.putDirectory(bg.toPath(), "bg"); - File background_png = new File("background.png").getAbsoluteFile(); - if (background_png.isFile()) - zip.putFile(background_png, "background.png"); + for (String extension : FXUtils.IMAGE_EXTENSIONS) { + String fileName = "background." + extension; - File background_jpg = new File("background.jpg").getAbsoluteFile(); - if (background_jpg.isFile()) - zip.putFile(background_jpg, "background.jpg"); - - File background_gif = new File("background.gif").getAbsoluteFile(); - if (background_gif.isFile()) - zip.putFile(background_gif, "background.gif"); + File background = new File(fileName).getAbsoluteFile(); + if (background.isFile()) + zip.putFile(background, "background.png"); + } zip.putFile(launcherJar, launcherJar.getFileName().toString()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java index f1938c8efc..0f3aac4a44 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java @@ -106,11 +106,13 @@ public PersonalizationPage() { backgroundSublist.setHasSubtitle(true); backgroundItem.loadChildren(Arrays.asList( - new MultiFileItem.Option<>(i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT), + new MultiFileItem.Option<>(i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT) + .setTooltip(i18n("launcher.background.default.tooltip")), new MultiFileItem.Option<>(i18n("launcher.background.classic"), EnumBackgroundImage.CLASSIC), new MultiFileItem.Option<>(i18n("launcher.background.translucent"), EnumBackgroundImage.TRANSLUCENT), new MultiFileItem.FileOption<>(i18n("settings.custom"), EnumBackgroundImage.CUSTOM) .setChooserTitle(i18n("launcher.background.choose")) + .addExtensionFilter(FXUtils.getImageExtensionFilter()) .bindBidirectional(config().backgroundImageProperty()), new MultiFileItem.StringOption<>(i18n("launcher.background.network"), EnumBackgroundImage.NETWORK) .setValidators(new URLValidator(true)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java index a19ab6ac50..44b2ada093 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java @@ -72,7 +72,7 @@ public VersionIconDialog(Profile profile, String versionId, Runnable onFinish) { private void exploreIcon() { FileChooser chooser = new FileChooser(); - chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("extension.png"), "*.png", "*.jpg", "*.bmp", "*.gif")); + chooser.getExtensionFilters().add(FXUtils.getImageExtensionFilter()); File selectedFile = chooser.showOpenDialog(Controllers.getStage()); if (selectedFile != null) { try { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index cd025c5c62..b756ec6851 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -185,7 +185,7 @@ public VersionSettingsPage(boolean globalSetting) { javaCustomOption = new MultiFileItem.FileOption>(i18n("settings.custom"), pair(JavaVersionType.CUSTOM, null)) .setChooserTitle(i18n("settings.game.java_directory.choose")); if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) - javaCustomOption.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe")); + javaCustomOption.addExtensionFilter(new FileChooser.ExtensionFilter("Java", "java.exe")); javaListChangeListener = FXUtils.onWeakChangeAndOperate(JavaManager.getAllJavaProperty(), allJava -> { List>> options = new ArrayList<>(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/SwingFXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/SwingFXUtils.java new file mode 100644 index 0000000000..1163c0e8ce --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/SwingFXUtils.java @@ -0,0 +1,124 @@ +// Copy from javafx.swing +/* + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.jackhuang.hmcl.util; + +import javafx.scene.image.*; +import javafx.scene.image.Image; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.nio.IntBuffer; + +/** + * This class provides utility methods for converting data types between + * Swing/AWT and JavaFX formats. + * + * @since JavaFX 2.2 + */ +public final class SwingFXUtils { + private SwingFXUtils() { + } + + /** + * Snapshots the specified {@link BufferedImage} and stores a copy of + * its pixels into a JavaFX {@link Image} object, creating a new + * object if needed. + * The returned {@code Image} will be a static snapshot of the state + * of the pixels in the {@code BufferedImage} at the time the method + * completes. Further changes to the {@code BufferedImage} will not + * be reflected in the {@code Image}. + *

    + * The optional JavaFX {@link WritableImage} parameter may be reused + * to store the copy of the pixels. + * A new {@code Image} will be created if the supplied object is null, + * is too small or of a type which the image pixels cannot be easily + * converted into. + * + * @param bimg the {@code BufferedImage} object to be converted + * @param wimg an optional {@code WritableImage} object that can be + * used to store the returned pixel data + * @return an {@code Image} object representing a snapshot of the + * current pixels in the {@code BufferedImage}. + * @since JavaFX 2.2 + */ + public static WritableImage toFXImage(BufferedImage bimg, WritableImage wimg) { + int bw = bimg.getWidth(); + int bh = bimg.getHeight(); + switch (bimg.getType()) { + case BufferedImage.TYPE_INT_ARGB: + case BufferedImage.TYPE_INT_ARGB_PRE: + break; + default: + BufferedImage converted = + new BufferedImage(bw, bh, BufferedImage.TYPE_INT_ARGB_PRE); + Graphics2D g2d = converted.createGraphics(); + g2d.drawImage(bimg, 0, 0, null); + g2d.dispose(); + bimg = converted; + break; + } + // assert(bimg.getType == TYPE_INT_ARGB[_PRE]); + if (wimg != null) { + int iw = (int) wimg.getWidth(); + int ih = (int) wimg.getHeight(); + if (iw < bw || ih < bh) { + wimg = null; + } else if (bw < iw || bh < ih) { + int[] empty = new int[iw]; + PixelWriter pw = wimg.getPixelWriter(); + PixelFormat pf = PixelFormat.getIntArgbPreInstance(); + if (bw < iw) { + pw.setPixels(bw, 0, iw - bw, bh, pf, empty, 0, 0); + } + if (bh < ih) { + pw.setPixels(0, bh, iw, ih - bh, pf, empty, 0, 0); + } + } + } + if (wimg == null) { + wimg = new WritableImage(bw, bh); + } + PixelWriter pw = wimg.getPixelWriter(); + DataBufferInt db = (DataBufferInt) bimg.getRaster().getDataBuffer(); + int[] data = db.getData(); + int offset = bimg.getRaster().getDataBuffer().getOffset(); + int scan = 0; + SampleModel sm = bimg.getRaster().getSampleModel(); + if (sm instanceof SinglePixelPackedSampleModel) { + scan = ((SinglePixelPackedSampleModel) sm).getScanlineStride(); + } + + PixelFormat pf = (bimg.isAlphaPremultiplied() ? + PixelFormat.getIntArgbPreInstance() : + PixelFormat.getIntArgbInstance()); + pw.setPixels(0, 0, bw, bh, pf, data, offset, scan); + return wimg; + } +} + diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 62a8348e37..cdcd6a1be4 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -787,7 +787,8 @@ launcher.agreement.hint=You must agree to the EULA to use this software. launcher.background=Background Image launcher.background.choose=Choose background image launcher.background.classic=Classic -launcher.background.default=Default (Or "background.png/.jpg/.gif" and the images in the "bg" directory) +launcher.background.default=Default +launcher.background.default.tooltip=Or "background.png/.jpg/.gif/.webp" and the images in the "bg" directory launcher.background.network=From URL launcher.background.translucent=Translucent launcher.cache_directory=Cache Directory diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 551a0c4dd6..20122a125d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -682,7 +682,8 @@ launcher.agreement.hint=Debe aceptar el EULA para utilizar este software. launcher.background=Imagen de fondo launcher.background.choose=Elige una imagen de fondo launcher.background.classic=Clásico -launcher.background.default=Por defecto (o background.png/jpg/gif, o imágenes en la carpeta bg) +launcher.background.default=Por defecto +launcher.background.default.tooltip=o background.png/.jpg/.gif/.webp, o imágenes en la carpeta bg launcher.background.network=Desde la URL launcher.background.translucent=Translúcido launcher.cache_directory=Directorio de la caché diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index a630f26e82..170d0c691f 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -535,7 +535,8 @@ launcher.agreement.hint=このソフトウェアを使用するには、EULAに launcher.background=背景画像 launcher.background.classic=クラシック launcher.background.choose=背景画像ファイルを選択してください -launcher.background.default=標準(ランチャーと同じディレクトリにある background.png/jpg/gif と bg フォルダから自動的に画像を取得します。) +launcher.background.default=標準 +launcher.background.default.tooltip=ランチャーと同じディレクトリにある background.png/.jpg/.gif/.webp と bg フォルダから自動的に画像を取得します。 launcher.background.network=ネットワーク launcher.background.translucent=半透明 launcher.cache_directory=キャッシュ用のディレクトリ diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index e0d58deb40..15f88033d9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -557,7 +557,8 @@ launcher.agreement.hint=Нужно принять пользовательско launcher.background=Фоновое изображение launcher.background.choose=Выберите фоновое изображение launcher.background.classic=Классическое -launcher.background.default=По умолчанию (или background.png/jpg/gif, или папку с изображениями) +launcher.background.default=По умолчанию +launcher.background.default.tooltip=или background.png/.jpg/.gif/.webp, или папку с изображениями launcher.background.network=По ссылке launcher.background.translucent=Полупрозрачный launcher.cache_directory=Папка с кэшем diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index ce564a8e60..0eef2f5f3f 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -602,7 +602,8 @@ launcher.agreement.hint=同意本軟體的使用者協議與免責宣告以使 launcher.background=背景圖片 launcher.background.choose=選取背景圖片 launcher.background.classic=經典 -launcher.background.default=預設 (自動尋找啟動器同目錄下的「background.png/.jpg/.gif」及「bg」目錄內的圖片) +launcher.background.default=預設 +launcher.background.default.tooltip=自動尋找啟動器同目錄下的「background.png/.jpg/.gif/.webp」及「bg」目錄內的圖片 launcher.background.network=網路 launcher.background.translucent=半透明 launcher.cache_directory=檔案下載快取目錄 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 652debe8a2..b39e8a2ef8 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -613,7 +613,8 @@ launcher.agreement.hint=同意本软件的用户协议与免责声明以使用 launcher.background=背景图片 launcher.background.choose=选择背景图片 launcher.background.classic=经典 -launcher.background.default=默认 (自动检索启动器同文件夹下的“background.png/.jpg/.gif”及“bg”文件夹内的图片) +launcher.background.default=默认 +launcher.background.default.tooltip=自动检索启动器同文件夹下的“background.png/.jpg/.gif/.webp”及“bg”文件夹内的图片 launcher.background.network=网络 launcher.background.translucent=半透明 launcher.cache_directory=文件下载缓存文件夹 From 6f0e133bb034bf0312d3a6c181cdd53e2b862f74 Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 28 Nov 2024 20:34:12 +0800 Subject: [PATCH 126/169] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20banshanjdk-8=20?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=9C=B0=E5=9D=80=20(#3476)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加 banshanjdk-8 下载地址 * update * fix i18n * fix typo --- .../org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java | 7 +++++++ HMCL/src/main/resources/assets/lang/I18N.properties | 1 + HMCL/src/main/resources/assets/lang/I18N_zh.properties | 1 + HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 1 + 4 files changed, 10 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java index 231be4b2b5..f5d27ea2e5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java @@ -48,6 +48,8 @@ import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.TaskCancellationAction; import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.platform.Architecture; +import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.Platform; import java.io.File; @@ -289,6 +291,11 @@ else if (list.status == DiscoJavaVersionList.Status.LOADING) setHeading(new Label(i18n("java.download"))); setBody(body); setActions(warningLabel, downloadButtonPane, cancelButton); + if (platform.getOperatingSystem() == OperatingSystem.LINUX && platform.getArchitecture() == Architecture.RISCV64) { + JFXHyperlink hyperlink = new JFXHyperlink(i18n("java.download.banshanjdk-8")); + hyperlink.setExternalLink("https://www.zthread.cn/#product"); + getActions().add(0, hyperlink); + } } private void onDownload() { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index cdcd6a1be4..79f5b8394b 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -711,6 +711,7 @@ java.disabled.management=Disabled Java java.disabled.management.remove=Remove this Java from the list java.disabled.management.restore=Re-enable this Java java.download=Download Java +java.download.banshanjdk-8=Download Banshan JDK 8 java.download.load_list.failed=Failed to load version list java.download.more=More Java distributions java.download.prompt=Please choose the Java version you want to download: diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 0eef2f5f3f..4058fadbfb 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -525,6 +525,7 @@ java.disabled.management=管理已禁用的 Java java.disabled.management.remove=從清單中移除此 Java java.disabled.management.restore=重新啟用此 Java java.download=下載 Java +java.download.banshanjdk-8=下載 Banshan JDK 8 java.download.load_list.failed=載入版本清單失敗 java.download.more=更多發行版 java.download.prompt=請選擇你要下載的 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 b39e8a2ef8..a521d602fd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -536,6 +536,7 @@ java.disabled.management=管理已禁用的 Java java.disabled.management.remove=从列表中移除此 Java java.disabled.management.restore=重新启用此 Java java.download=下载 Java +java.download.banshanjdk-8=下载 Banshan JDK 8 java.download.load_list.failed=加载版本列表失败 java.download.more=更多发行版 java.download.prompt=请选择你要下载的 Java 版本: From 3df52b0e8f68503991e92abf95830d53f800e40b Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 29 Nov 2024 20:06:08 +0800 Subject: [PATCH 127/169] Fix typo in check-update.yml (#3479) --- .github/workflows/check-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-update.yml b/.github/workflows/check-update.yml index cff9d2f278..8fd415ff30 100644 --- a/.github/workflows/check-update.yml +++ b/.github/workflows/check-update.yml @@ -71,7 +71,7 @@ jobs: target_commitish: ${{ env.HMCL_COMMIT_SHA }} name: ${{ env.HMCL_TAG_NAME }} tag_name: ${{ env.HMCL_TAG_NAME }} - prerelease: ture + prerelease: true stable-check-update: if: ${{ github.repository_owner == 'HMCL-dev' }} needs: dev-check-update From 8e0f0e2a38f1846ca307902c3ad8d26aaad43e86 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 2 Dec 2024 21:24:58 +0800 Subject: [PATCH 128/169] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20ONE=5FPASS=5FBOX?= =?UTF-8?q?=20=E9=98=B4=E5=BD=B1=E4=BB=A3=E6=9B=BF=E9=AB=98=E6=96=AF?= =?UTF-8?q?=E6=A8=A1=E7=B3=8A=20(#3458)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 使用 ONE_PASS_BOX 代替高斯模糊 * update * update * update --- .../org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java | 8 ++++---- HMCL/src/main/resources/assets/css/root.css | 5 ----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index 5bc5e1b50d..bbcf7585c1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -27,11 +27,10 @@ import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.SkinBase; +import javafx.scene.effect.BlurType; +import javafx.scene.effect.DropShadow; import javafx.scene.input.MouseEvent; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.StackPane; +import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; @@ -68,6 +67,7 @@ public DecoratorSkin(Decorator control) { StackPane shadowContainer = new StackPane(); shadowContainer.getStyleClass().add("body"); + shadowContainer.setEffect(new DropShadow(BlurType.ONE_PASS_BOX, Color.rgb(0, 0, 0, 0.4), 10, 0.3, 0.0, 0.0)); parent = new StackPane(); Rectangle clip = new Rectangle(); diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 6ee1010484..e836437e54 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -1307,11 +1307,6 @@ -fx-padding: 8; } -.body { - -fx-border-radius: 5; - -fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.4), 10, 0.3, 0.0, 0.0); -} - .debug-border { -fx-border-color: red; -fx-border-width: 1; From 727e6746d2c8ce34a53bdd3c1c3607e981c074dc Mon Sep 17 00:00:00 2001 From: Glavo Date: Wed, 4 Dec 2024 12:29:17 +0800 Subject: [PATCH 129/169] Update versions.txt (#3484) * Update versions.txt * update --- HMCLCore/src/main/resources/assets/game/versions.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/HMCLCore/src/main/resources/assets/game/versions.txt b/HMCLCore/src/main/resources/assets/game/versions.txt index 2d8fdada50..363dc0b470 100644 --- a/HMCLCore/src/main/resources/assets/game/versions.txt +++ b/HMCLCore/src/main/resources/assets/game/versions.txt @@ -786,4 +786,14 @@ 1.21.2-rc1 1.21.2-rc2 1.21.2 -1.21.3 \ No newline at end of file +1.21.3 +24w44a +24w45a +24w46a +1.21.4-pre1 +1.21.4-pre2 +1.21.4-pre3 +1.21.4-rc1 +1.21.4-rc2 +1.21.4-rc3 +1.21.4 From 8460df7d5d4738f59edddfc8c39029cebada8534 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 9 Dec 2024 17:47:42 +0800 Subject: [PATCH 130/169] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20OAuth=20=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=97=B6=E8=BD=AE=E8=AF=A2=E8=BF=87=E4=BA=8E=E9=A2=91?= =?UTF-8?q?=E7=B9=81=E7=9A=84=E9=97=AE=E9=A2=98=20(#3490)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修复 OAuth 登录时轮询过于频繁的问题 * update --- HMCLCore/src/main/java/org/jackhuang/hmcl/auth/OAuth.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/OAuth.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/OAuth.java index 7ae6d51a04..c71b022168 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/OAuth.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/OAuth.java @@ -109,7 +109,7 @@ private Result authenticateDevice(Options options) throws IOException, Interrupt options.callback.openBrowser(deviceTokenResponse.verificationURI); long startTime = System.nanoTime(); - int interval = deviceTokenResponse.interval; + long interval = TimeUnit.MILLISECONDS.convert(deviceTokenResponse.interval, TimeUnit.SECONDS); while (true) { Thread.sleep(Math.max(interval, 1)); @@ -138,7 +138,7 @@ private Result authenticateDevice(Options options) throws IOException, Interrupt } if ("slow_down".equals(tokenResponse.error)) { - interval += 5; + interval += 5000; continue; } From 981b55a10ede72df9b07bbbacafafe73a285aeb2 Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:20:02 +0800 Subject: [PATCH 131/169] =?UTF-8?q?Fix=20#3456=20=E5=9C=A8=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E9=A2=84=E8=A7=88=E7=95=8C=E9=9D=A2=E6=B2=A1=E6=B3=95?= =?UTF-8?q?=E6=8B=96=E5=8A=A8=E5=90=AF=E5=8A=A8=E5=99=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=20(#3464)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java index e6b1e99255..abc62af4c2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/UpgradeDialog.java @@ -41,6 +41,9 @@ public final class UpgradeDialog extends JFXDialogLayout { public UpgradeDialog(RemoteVersion remoteVersion, Runnable updateRunnable) { + maxWidthProperty().bind(Controllers.getScene().widthProperty().multiply(0.7)); + maxHeightProperty().bind(Controllers.getScene().heightProperty().multiply(0.7)); + setHeading(new Label(i18n("update.changelog"))); setBody(new ProgressIndicator()); From 4c6fdf49de8ed0e70a07f633a7dfe26253117603 Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 13 Dec 2024 00:29:34 +0800 Subject: [PATCH 132/169] Bump JetBrains Annotations to 26.0.1 (#3493) --- HMCLCore/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/build.gradle.kts b/HMCLCore/build.gradle.kts index c25db1c3ee..ba4e103da1 100644 --- a/HMCLCore/build.gradle.kts +++ b/HMCLCore/build.gradle.kts @@ -13,7 +13,7 @@ dependencies { api("org.nanohttpd:nanohttpd:2.3.1") api("org.apache.commons:commons-compress:1.25.0") api("org.jsoup:jsoup:1.18.1") - compileOnlyApi("org.jetbrains:annotations:24.1.0") + compileOnlyApi("org.jetbrains:annotations:26.0.1") if (JavaVersion.current().isJava8) { org.gradle.internal.jvm.Jvm.current().toolsJar?.let { From cb2b3525b83c628661e822251706e93561837f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E9=93=AD=E9=AA=A2=20=28Mingcong=20Bai=29?= Date: Wed, 25 Dec 2024 03:55:42 -0800 Subject: [PATCH 133/169] fix(DefaultLauncher): also set LIBGL_KOPPER_DRI2=1 for Zink mode (#3503) The amdgpu DDX is missing support for modifiers, causing Zink to fail. Disable DRI3 to workaround this issue. Link: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10093 Signed-off-by: Mingcong Bai --- .../java/org/jackhuang/hmcl/launch/DefaultLauncher.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index 6bb0494739..1f4c13043a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -496,6 +496,13 @@ private Map getEnvVars() { break; case ZINK: env.put("MESA_LOADER_DRIVER_OVERRIDE", "zink"); + /** + * The amdgpu DDX is missing support for modifiers, causing Zink to fail. + * Disable DRI3 to workaround this issue. + * + * Link: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10093 + */ + env.put("LIBGL_KOPPER_DRI2", "1"); break; } } From 5fd52bb808630d5f213fe6c2350d561e3ae20481 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Sun, 29 Dec 2024 18:28:23 +0800 Subject: [PATCH 134/169] Move skin cache directory to hmcl dir, close #2970 --- HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java index d314869eef..0321615a3c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java @@ -87,7 +87,7 @@ public Map getMetadata() { } private static final ThreadPoolExecutor POOL = threadPool("TexturesDownload", true, 2, 10, TimeUnit.SECONDS); - private static final Path TEXTURES_DIR = Metadata.MINECRAFT_DIRECTORY.resolve("assets").resolve("skins"); + private static final Path TEXTURES_DIR = Metadata.HMCL_DIRECTORY.resolve("skins"); private static Path getTexturePath(Texture texture) { String url = texture.getUrl(); From d5408c38b3d18e23eb3a6df2dcc8c66dacaea8f2 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Sun, 29 Dec 2024 20:18:58 +0800 Subject: [PATCH 135/169] Copy global settings when specialize version setting --- .../main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 1d34d9fd36..f02e5f393f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -38,6 +38,7 @@ import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; +import org.jackhuang.hmcl.util.javafx.PropertyUtils; import org.jackhuang.hmcl.java.JavaRuntime; import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.versioning.VersionNumber; @@ -357,7 +358,10 @@ public VersionSetting specializeVersionSetting(String id) { vs = createLocalVersionSetting(id); if (vs == null) return null; + VersionIconType versionIcon = vs.getVersionIcon(); + PropertyUtils.copyProperties(profile.getGlobal(), vs); vs.setUsesGlobal(false); + vs.setVersionIcon(versionIcon); // versionIcon is preserved return vs; } From e63ee49eaaafc8eac6dea3cc65b3abdc4fe57ada Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Sun, 29 Dec 2024 20:59:47 +0800 Subject: [PATCH 136/169] Remove VersionSetting.global property as it's unused --- .../org/jackhuang/hmcl/game/HMCLGameRepository.java | 1 - .../org/jackhuang/hmcl/setting/VersionSetting.java | 10 ---------- 2 files changed, 11 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index f02e5f393f..26a148835a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -251,7 +251,6 @@ public VersionSetting getLocalVersionSettingOrCreate(String id) { public VersionSetting getVersionSetting(String id) { VersionSetting vs = getLocalVersionSetting(id); if (vs == null || vs.isUsesGlobal()) { - profile.getGlobal().setGlobal(true); // always keep global.isGlobal = true profile.getGlobal().setUsesGlobal(true); return profile.getGlobal(); } else diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java index aa084d119b..cf337e3ddd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -44,16 +44,6 @@ @JsonAdapter(VersionSetting.Serializer.class) public final class VersionSetting implements Cloneable { - private boolean global = false; - - public boolean isGlobal() { - return global; - } - - public void setGlobal(boolean global) { - this.global = global; - } - private final BooleanProperty usesGlobalProperty = new SimpleBooleanProperty(this, "usesGlobal", true); public BooleanProperty usesGlobalProperty() { From 8a4f6af193ab5f7cf94685552d9f4cc61bdd3b17 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Sun, 29 Dec 2024 21:40:09 +0800 Subject: [PATCH 137/169] Fix NPE due to the order of attaching specificSettingsListener --- .../org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index b756ec6851..aab4a3c1a3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -552,9 +552,9 @@ public void loadVersion(Profile profile, String versionId) { FXUtils.bindEnum(cboLauncherVisibility, versionSetting.launcherVisibilityProperty()); FXUtils.bindEnum(cboProcessPriority, versionSetting.processPriorityProperty()); - versionSetting.usesGlobalProperty().addListener(specificSettingsListener); if (versionId != null) enableSpecificSettings.set(!versionSetting.isUsesGlobal()); + versionSetting.usesGlobalProperty().addListener(specificSettingsListener); javaItem.setToggleSelectedListener(newValue -> { if (javaItem.getSelectedData() == null || updatingSelectedJava) From f0a064afdd2433ef2fec116bd4f3cf2221c89495 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Sun, 29 Dec 2024 22:18:15 +0800 Subject: [PATCH 138/169] Fix sometimes version specific setting is lost --- .../hmcl/game/HMCLGameRepository.java | 6 ++- .../hmcl/ui/versions/VersionSettingsPage.java | 39 +++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 26a148835a..638546c1c0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -358,8 +358,10 @@ public VersionSetting specializeVersionSetting(String id) { if (vs == null) return null; VersionIconType versionIcon = vs.getVersionIcon(); - PropertyUtils.copyProperties(profile.getGlobal(), vs); - vs.setUsesGlobal(false); + if (vs.isUsesGlobal()) { + PropertyUtils.copyProperties(profile.getGlobal(), vs); + vs.setUsesGlobal(false); + } vs.setVersionIcon(versionIcon); // versionIcon is preserved return vs; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index aab4a3c1a3..f22390d620 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -92,7 +92,8 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag private final ImagePickerItem iconPickerItem; private final ChangeListener> javaListChangeListener; - private final InvalidationListener specificSettingsListener; + private final InvalidationListener usesGlobalListener; + private final ChangeListener specificSettingsListener; private final InvalidationListener javaListener = any -> initJavaSubtitle(); private boolean updatingJavaSetting = false; private boolean updatingSelectedJava = false; @@ -443,22 +444,8 @@ public VersionSettingsPage(boolean globalSetting) { rootPane.getChildren().add(componentList); - initialize(); - - specificSettingsListener = any -> enableSpecificSettings.set(!lastVersionSetting.isUsesGlobal()); - - addEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onDecoratorPageNavigating); - - cboLauncherVisibility.getItems().setAll(LauncherVisibility.values()); - cboLauncherVisibility.setConverter(stringConverter(e -> i18n("settings.advanced.launcher_visibility." + e.name().toLowerCase(Locale.ROOT)))); - - cboProcessPriority.getItems().setAll(ProcessPriority.values()); - cboProcessPriority.setConverter(stringConverter(e -> i18n("settings.advanced.process_priority." + e.name().toLowerCase(Locale.ROOT)))); - } - - private void initialize() { - memoryStatus.set(OperatingSystem.getPhysicalMemoryStatus()); - enableSpecificSettings.addListener((a, b, newValue) -> { + usesGlobalListener = any -> enableSpecificSettings.set(!lastVersionSetting.isUsesGlobal()); + specificSettingsListener = (a, b, newValue) -> { if (versionId == null) return; // do not call versionSettings.setUsesGlobal(true/false) @@ -470,8 +457,17 @@ private void initialize() { profile.getRepository().globalizeVersionSetting(versionId); Platform.runLater(() -> loadVersion(profile, versionId)); - }); + }; + + addEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onDecoratorPageNavigating); + + cboLauncherVisibility.getItems().setAll(LauncherVisibility.values()); + cboLauncherVisibility.setConverter(stringConverter(e -> i18n("settings.advanced.launcher_visibility." + e.name().toLowerCase(Locale.ROOT)))); + cboProcessPriority.getItems().setAll(ProcessPriority.values()); + cboProcessPriority.setConverter(stringConverter(e -> i18n("settings.advanced.process_priority." + e.name().toLowerCase(Locale.ROOT)))); + + memoryStatus.set(OperatingSystem.getPhysicalMemoryStatus()); componentList.disableProperty().bind(enableSpecificSettings.not()); } @@ -519,7 +515,7 @@ public void loadVersion(Profile profile, String versionId) { FXUtils.unbindEnum(cboLauncherVisibility); FXUtils.unbindEnum(cboProcessPriority); - lastVersionSetting.usesGlobalProperty().removeListener(specificSettingsListener); + lastVersionSetting.usesGlobalProperty().removeListener(usesGlobalListener); lastVersionSetting.javaVersionTypeProperty().removeListener(javaListener); lastVersionSetting.javaDirProperty().removeListener(javaListener); lastVersionSetting.defaultJavaPathPropertyProperty().removeListener(javaListener); @@ -528,6 +524,8 @@ public void loadVersion(Profile profile, String versionId) { gameDirItem.selectedDataProperty().unbindBidirectional(lastVersionSetting.gameDirTypeProperty()); gameDirSublist.subtitleProperty().unbind(); + enableSpecificSettings.removeListener(specificSettingsListener); + if (advancedVersionSettingPage != null) { advancedVersionSettingPage.unbindProperties(); advancedVersionSettingPage = null; @@ -554,7 +552,8 @@ public void loadVersion(Profile profile, String versionId) { if (versionId != null) enableSpecificSettings.set(!versionSetting.isUsesGlobal()); - versionSetting.usesGlobalProperty().addListener(specificSettingsListener); + versionSetting.usesGlobalProperty().addListener(usesGlobalListener); + enableSpecificSettings.addListener(specificSettingsListener); javaItem.setToggleSelectedListener(newValue -> { if (javaItem.getSelectedData() == null || updatingSelectedJava) From c5b8aabc57189de8808dec7b78c270a4bc8aee92 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Sun, 29 Dec 2024 22:36:40 +0800 Subject: [PATCH 139/169] Refactor VersionSetting.clone() & .addListener(), fix javaVersionType is not saved --- .../hmcl/game/HMCLGameRepository.java | 2 +- .../org/jackhuang/hmcl/setting/Config.java | 7 +- .../jackhuang/hmcl/setting/ConfigHolder.java | 8 +- .../jackhuang/hmcl/setting/GlobalConfig.java | 7 +- .../org/jackhuang/hmcl/setting/Profile.java | 2 +- .../hmcl/setting/VersionSetting.java | 91 +++++-------------- 6 files changed, 27 insertions(+), 90 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 638546c1c0..503f2870e5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -218,7 +218,7 @@ public VersionSetting createLocalVersionSetting(String id) { private VersionSetting initLocalVersionSetting(String id, VersionSetting vs) { localVersionSettings.put(id, vs); - vs.addPropertyChangedListener(a -> saveVersionSetting(id)); + vs.addListener(a -> saveVersionSetting(id)); return vs; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index b124c509a5..44e7d3a6be 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -47,7 +47,7 @@ import java.util.Map; import java.util.TreeMap; -public final class Config implements Cloneable, Observable { +public final class Config implements Observable { public static final int CURRENT_UI_VERSION = 0; @@ -223,11 +223,6 @@ public String toJson() { return CONFIG_GSON.toJson(this); } - @Override - public Config clone() { - return fromJson(this.toJson()); - } - // Getters & Setters & Properties public String getSelectedProfile() { return selectedProfile.get(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java index cbd034e958..8d5e4809b5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java @@ -197,7 +197,7 @@ private static void writeToConfig(String content) throws IOException { } } - static void markConfigDirty() { + private static void markConfigDirty() { configWriter.accept(configInstance.toJson()); } @@ -241,11 +241,7 @@ private static void writeToGlobalConfig(String content) throws IOException { } } - static void markGlobalConfigDirty() { + private static void markGlobalConfigDirty() { globalConfigWriter.accept(globalConfigInstance.toJson()); } - - private static void saveGlobalConfigSync() throws IOException { - writeToConfig(globalConfigInstance.toJson()); - } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/GlobalConfig.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/GlobalConfig.java index 7979f17fde..b78acc0cc2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/GlobalConfig.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/GlobalConfig.java @@ -33,7 +33,7 @@ import java.util.*; @JsonAdapter(GlobalConfig.Serializer.class) -public final class GlobalConfig implements Cloneable, Observable { +public final class GlobalConfig implements Observable { @Nullable public static GlobalConfig fromJson(String json) throws JsonParseException { @@ -79,11 +79,6 @@ public String toJson() { return Config.CONFIG_GSON.toJson(this); } - @Override - public GlobalConfig clone() { - return fromJson(this.toJson()); - } - public int getAgreementVersion() { return agreementVersion.get(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java index 5b8da0995b..239eef2eca 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java @@ -188,7 +188,7 @@ private void addPropertyChangedListener(InvalidationListener listener) { global.addListener(listener); gameDir.addListener(listener); useRelativePath.addListener(listener); - global.get().addPropertyChangedListener(listener); + global.get().addListener(listener); selectedVersion.addListener(listener); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java index cf337e3ddd..39fb1afd48 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -20,11 +20,14 @@ import com.google.gson.*; import com.google.gson.annotations.JsonAdapter; import javafx.beans.InvalidationListener; +import javafx.beans.Observable; import javafx.beans.property.*; import org.jackhuang.hmcl.game.*; import org.jackhuang.hmcl.java.JavaManager; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.StringUtils; +import org.jackhuang.hmcl.util.javafx.ObservableHelper; +import org.jackhuang.hmcl.util.javafx.PropertyUtils; import org.jackhuang.hmcl.java.JavaRuntime; import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.versioning.GameVersionNumber; @@ -42,7 +45,13 @@ * @author huangyuhui */ @JsonAdapter(VersionSetting.Serializer.class) -public final class VersionSetting implements Cloneable { +public final class VersionSetting implements Cloneable, Observable { + + private transient ObservableHelper helper = new ObservableHelper(this); + + public VersionSetting() { + PropertyUtils.attachListener(this, helper); + } private final BooleanProperty usesGlobalProperty = new SimpleBooleanProperty(this, "usesGlobal", true); @@ -698,79 +707,21 @@ public JavaRuntime getJava(GameVersionNumber gameVersion, Version version) throw } } - public void addPropertyChangedListener(InvalidationListener listener) { - usesGlobalProperty.addListener(listener); - javaVersionProperty.addListener(listener); - javaDirProperty.addListener(listener); - wrapperProperty.addListener(listener); - permSizeProperty.addListener(listener); - maxMemoryProperty.addListener(listener); - minMemoryProperty.addListener(listener); - autoMemory.addListener(listener); - preLaunchCommandProperty.addListener(listener); - postExitCommand.addListener(listener); - javaArgsProperty.addListener(listener); - minecraftArgsProperty.addListener(listener); - environmentVariablesProperty.addListener(listener); - noJVMArgsProperty.addListener(listener); - notCheckGameProperty.addListener(listener); - notCheckJVMProperty.addListener(listener); - notPatchNativesProperty.addListener(listener); - showLogsProperty.addListener(listener); - serverIpProperty.addListener(listener); - fullscreenProperty.addListener(listener); - widthProperty.addListener(listener); - heightProperty.addListener(listener); - gameDirTypeProperty.addListener(listener); - gameDirProperty.addListener(listener); - processPriorityProperty.addListener(listener); - rendererProperty.addListener(listener); - useNativeGLFW.addListener(listener); - useNativeOpenAL.addListener(listener); - launcherVisibilityProperty.addListener(listener); - defaultJavaPathProperty.addListener(listener); - nativesDirProperty.addListener(listener); - nativesDirTypeProperty.addListener(listener); - versionIcon.addListener(listener); + @Override + public void addListener(InvalidationListener listener) { + helper.addListener(listener); + } + + @Override + public void removeListener(InvalidationListener listener) { + helper.removeListener(listener); } @Override public VersionSetting clone() { - VersionSetting versionSetting = new VersionSetting(); - versionSetting.setUsesGlobal(isUsesGlobal()); - versionSetting.setJavaVersionType(getJavaVersionType()); - versionSetting.setJavaVersion(getJavaVersion()); - versionSetting.setDefaultJavaPath(getDefaultJavaPath()); - versionSetting.setJavaDir(getJavaDir()); - versionSetting.setWrapper(getWrapper()); - versionSetting.setPermSize(getPermSize()); - versionSetting.setMaxMemory(getMaxMemory()); - versionSetting.setMinMemory(getMinMemory()); - versionSetting.setAutoMemory(isAutoMemory()); - versionSetting.setPreLaunchCommand(getPreLaunchCommand()); - versionSetting.setPostExitCommand(getPostExitCommand()); - versionSetting.setJavaArgs(getJavaArgs()); - versionSetting.setMinecraftArgs(getMinecraftArgs()); - versionSetting.setEnvironmentVariables(getEnvironmentVariables()); - versionSetting.setNoJVMArgs(isNoJVMArgs()); - versionSetting.setNotCheckGame(isNotCheckGame()); - versionSetting.setNotCheckJVM(isNotCheckJVM()); - versionSetting.setNotPatchNatives(isNotPatchNatives()); - versionSetting.setShowLogs(isShowLogs()); - versionSetting.setServerIp(getServerIp()); - versionSetting.setFullscreen(isFullscreen()); - versionSetting.setWidth(getWidth()); - versionSetting.setHeight(getHeight()); - versionSetting.setGameDirType(getGameDirType()); - versionSetting.setGameDir(getGameDir()); - versionSetting.setProcessPriority(getProcessPriority()); - versionSetting.setRenderer(getRenderer()); - versionSetting.setUseNativeGLFW(isUseNativeGLFW()); - versionSetting.setUseNativeOpenAL(isUseNativeOpenAL()); - versionSetting.setLauncherVisibility(getLauncherVisibility()); - versionSetting.setNativesDir(getNativesDir()); - versionSetting.setVersionIcon(getVersionIcon()); - return versionSetting; + VersionSetting cloned = new VersionSetting(); + PropertyUtils.copyProperties(this, cloned); + return cloned; } public static class Serializer implements JsonSerializer, JsonDeserializer { From 81b3911dc901eb1bcd34f6a29a18057459341270 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Mon, 30 Dec 2024 00:02:32 +0800 Subject: [PATCH 140/169] Fix value in text field might not be saved when pressing ESC https://github.com/HMCL-dev/HMCL/pull/1869#issuecomment-2335027530 --- .../hmcl/game/HMCLGameRepository.java | 2 + .../java/org/jackhuang/hmcl/ui/FXUtils.java | 107 +++++++++--------- 2 files changed, 56 insertions(+), 53 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 503f2870e5..189313ca9e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -337,6 +337,8 @@ public boolean saveVersionSetting(String id) { if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile())) return false; + LOG.info("Saving version setting: " + id); + try { FileUtils.writeText(file, GSON.toJson(localVersionSettings.get(id))); return true; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index d42a5913b5..4b7087eb79 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -31,6 +31,7 @@ import javafx.geometry.Pos; import javafx.scene.Cursor; import javafx.scene.Node; +import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.control.*; @@ -521,10 +522,12 @@ public static void openLink(String link) { } public static void bind(JFXTextField textField, Property property, StringConverter converter) { - textField.setText(converter == null ? (String) property.getValue() : converter.toString(property.getValue())); - TextFieldBindingListener listener = new TextFieldBindingListener<>(textField, property, converter); - textField.focusedProperty().addListener((ChangeListener) listener); - property.addListener(listener); + TextFieldBinding binding = new TextFieldBinding<>(textField, property, converter); + binding.updateTextField(); + textField.getProperties().put("FXUtils.bind.binding", binding); + textField.focusedProperty().addListener(binding.focusedListener); + textField.sceneProperty().addListener(binding.sceneListener); + property.addListener(binding.propertyListener); } public static void bindInt(JFXTextField textField, Property property) { @@ -536,68 +539,66 @@ public static void bindString(JFXTextField textField, Property property) } public static void unbind(JFXTextField textField, Property property) { - TextFieldBindingListener listener = new TextFieldBindingListener<>(textField, property, null); - textField.focusedProperty().removeListener((ChangeListener) listener); - property.removeListener(listener); + TextFieldBinding binding = (TextFieldBinding) textField.getProperties().remove("FXUtils.bind.binding"); + if (binding != null) { + textField.focusedProperty().removeListener(binding.focusedListener); + textField.sceneProperty().removeListener(binding.sceneListener); + property.removeListener(binding.propertyListener); + } } - private static final class TextFieldBindingListener implements ChangeListener, InvalidationListener { - private final int hashCode; - private final WeakReference textFieldRef; - private final WeakReference> propertyRef; + private static final class TextFieldBinding { + private final JFXTextField textField; + private final Property property; private final StringConverter converter; - TextFieldBindingListener(JFXTextField textField, Property property, StringConverter converter) { - this.textFieldRef = new WeakReference<>(textField); - this.propertyRef = new WeakReference<>(property); + public final ChangeListener focusedListener; + public final ChangeListener sceneListener; + public final InvalidationListener propertyListener; + + public TextFieldBinding(JFXTextField textField, Property property, StringConverter converter) { + this.textField = textField; + this.property = property; this.converter = converter; - this.hashCode = System.identityHashCode(textField) ^ System.identityHashCode(property); - } - @Override - public void changed(ObservableValue observable, Boolean oldValue, Boolean focused) { // On TextField changed - JFXTextField textField = textFieldRef.get(); - Property property = this.propertyRef.get(); - - if (textField != null && property != null && oldValue == Boolean.TRUE && focused == Boolean.FALSE) { - if (textField.validate()) { - String newText = textField.getText(); - @SuppressWarnings("unchecked") - T newValue = converter == null ? (T) newText : converter.fromString(newText); - - if (!Objects.equals(newValue, property.getValue())) - property.setValue(newValue); - } else { - // Rollback to old value - invalidated(null); + focusedListener = (observable, oldFocused, newFocused) -> { + if (oldFocused && !newFocused) { + if (textField.validate()) { + uppdateProperty(); + } else { + // Rollback to old value + updateTextField(); + } } - } - } + }; - @Override - public void invalidated(Observable observable) { // On property change - JFXTextField textField = textFieldRef.get(); - Property property = this.propertyRef.get(); + sceneListener = (observable, oldScene, newScene) -> { + if (oldScene != null && newScene == null) { + // Component is being removed from scene + if (textField.validate()) { + uppdateProperty(); + } + } + }; - if (textField != null && property != null) { - T value = property.getValue(); - textField.setText(converter == null ? (String) value : converter.toString(value)); - } + propertyListener = observable -> { + updateTextField(); + }; } - @Override - public int hashCode() { - return hashCode; + public void uppdateProperty() { + String newText = textField.getText(); + @SuppressWarnings("unchecked") + T newValue = converter == null ? (T) newText : converter.fromString(newText); + + if (!Objects.equals(newValue, property.getValue())) { + property.setValue(newValue); + } } - @Override - public boolean equals(Object obj) { - if (!(obj instanceof TextFieldBindingListener)) - return false; - TextFieldBindingListener other = (TextFieldBindingListener) obj; - return this.hashCode == other.hashCode - && this.textFieldRef.get() == other.textFieldRef.get() - && this.propertyRef.get() == other.propertyRef.get(); + public void updateTextField() { + T value = property.getValue(); + textField.setText(converter == null ? (String) value : converter.toString(value)); } } From 104534d12fc86b473d1b181574dfd4cb0d3b4b7b Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Mon, 30 Dec 2024 00:07:43 +0800 Subject: [PATCH 141/169] Fix style --- HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java | 1 - 1 file changed, 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index 4b7087eb79..7759337bbd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -76,7 +76,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.*; -import java.lang.ref.WeakReference; import java.net.*; import java.nio.file.Files; import java.nio.file.Path; From 260f4b6c5d579b7789d1713a88aa976e7c3b8665 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Mon, 30 Dec 2024 00:17:00 +0800 Subject: [PATCH 142/169] Fix ESC not working in input dialog --- .../java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java index 770c4af9ca..d2c06b5d90 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java @@ -27,6 +27,7 @@ import java.util.concurrent.CompletableFuture; +import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class InputDialogPane extends JFXDialogLayout { @@ -68,6 +69,8 @@ public InputDialogPane(String text, String initialValue, FutureCallback lblCreationWarning.setText(msg); }); }); + + onEscPressed(this, cancelButton::fire); } public CompletableFuture getCompletableFuture() { From 7d12ef6b09017ff9a0c1c7ae5ce3912bf7519cac Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Mon, 30 Dec 2024 19:39:42 +0800 Subject: [PATCH 143/169] Fix memory slider indicator is covered by progress bar --- .../java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java | 1 + 1 file changed, 1 insertion(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index f22390d620..c0b6bbd8c4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -236,6 +236,7 @@ public VersionSettingsPage(boolean globalSetting) { VBox.setMargin(chkAutoAllocate, new Insets(0, 0, 8, 5)); HBox lowerBoundPane = new HBox(8); + lowerBoundPane.setStyle("-fx-view-order: -1;"); // prevent the indicator from being covered by the progress bar lowerBoundPane.setAlignment(Pos.CENTER); VBox.setMargin(lowerBoundPane, new Insets(0, 0, 0, 16)); { From 78e15d130bcf49b6e9a63def44fcbc85aa959ced Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Mon, 30 Dec 2024 20:14:04 +0800 Subject: [PATCH 144/169] Update memory status every 1s, fix #3440 This commit also fixes Lang.getTimer() returns a non-daemon Timer, preventing Java from exiting after closing the launcher. --- .../hmcl/ui/versions/VersionSettingsPage.java | 20 ++++++++++++++++++- .../java/org/jackhuang/hmcl/util/Lang.java | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index c0b6bbd8c4..17b6a35124 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -57,10 +57,27 @@ import java.util.concurrent.atomic.AtomicBoolean; import static org.jackhuang.hmcl.ui.FXUtils.stringConverter; +import static org.jackhuang.hmcl.util.Lang.getTimer; import static org.jackhuang.hmcl.util.Pair.pair; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class VersionSettingsPage extends StackPane implements DecoratorPage, VersionPage.VersionLoadable, PageAware { + + private static final ObjectProperty memoryStatus = new SimpleObjectProperty<>(OperatingSystem.PhysicalMemoryStatus.INVALID); + private static TimerTask memoryStatusUpdateTask; + private static void initMemoryStatusUpdateTask() { + FXUtils.checkFxUserThread(); + if (memoryStatusUpdateTask != null) + return; + memoryStatusUpdateTask = new TimerTask() { + @Override + public void run() { + Platform.runLater(() -> memoryStatus.set(OperatingSystem.getPhysicalMemoryStatus())); + } + }; + getTimer().scheduleAtFixedRate(memoryStatusUpdateTask, 0, 1000); + } + private final ReadOnlyObjectWrapper state = new ReadOnlyObjectWrapper<>(new State("", null, false, false, false)); private AdvancedVersionSettingPage advancedVersionSettingPage; @@ -102,7 +119,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag private final BooleanProperty navigateToSpecificSettings = new SimpleBooleanProperty(false); private final BooleanProperty enableSpecificSettings = new SimpleBooleanProperty(false); private final IntegerProperty maxMemory = new SimpleIntegerProperty(); - private final ObjectProperty memoryStatus = new SimpleObjectProperty<>(OperatingSystem.PhysicalMemoryStatus.INVALID); private final BooleanProperty modpack = new SimpleBooleanProperty(); public VersionSettingsPage(boolean globalSetting) { @@ -470,6 +486,8 @@ public VersionSettingsPage(boolean globalSetting) { memoryStatus.set(OperatingSystem.getPhysicalMemoryStatus()); componentList.disableProperty().bind(enableSpecificSettings.not()); + + initMemoryStatusUpdateTask(); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java index b0be0988c0..85001ba8c0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java @@ -389,7 +389,7 @@ public static void forEachZipped(Iterable i1, Iterable i2, BiConsum public static synchronized Timer getTimer() { if (timer == null) { - timer = new Timer(); + timer = new Timer(true); } return timer; } From 6f53da159a9ee3c94d8921b849748cc640d30c77 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Tue, 31 Dec 2024 19:56:38 +0800 Subject: [PATCH 145/169] Refine DownloadPage * Fix cursor is not hand when hovering on ModItem * Fix clicking on the ModItem in ModVersion dialog would open a new dialog again * Fix ESC doesn't work in ModVersion dialog --- .../java/org/jackhuang/hmcl/ui/versions/DownloadPage.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java index d566567eca..b00adb7754 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java @@ -62,6 +62,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class DownloadPage extends Control implements DecoratorPage { @@ -380,6 +381,7 @@ private static final class ModItem extends StackPane { HBox descPane = new HBox(8); descPane.setPadding(new Insets(0, 8, 0, 8)); descPane.setAlignment(Pos.CENTER_LEFT); + descPane.setMouseTransparent(true); { StackPane graphicPane = new StackPane(); @@ -445,7 +447,7 @@ public ModVersion(RemoteMod.Version version, DownloadPage selfPage) { VBox box = new VBox(8); box.setPadding(new Insets(8)); ModItem modItem = new ModItem(version, selfPage); - FXUtils.onClicked(modItem, () -> fireEvent(new DialogCloseEvent())); + modItem.setMouseTransparent(true); // Item is displayed for info, clicking shouldn't open the dialog again box.getChildren().setAll(modItem); SpinnerPane spinnerPane = new SpinnerPane(); ScrollPane scrollPane = new ScrollPane(); @@ -488,6 +490,8 @@ public ModVersion(RemoteMod.Version version, DownloadPage selfPage) { this.prefWidthProperty().bind(BindingMapping.of(Controllers.getStage().widthProperty()).map(w -> w.doubleValue() * 0.7)); this.prefHeightProperty().bind(BindingMapping.of(Controllers.getStage().heightProperty()).map(w -> w.doubleValue() * 0.7)); + + onEscPressed(this, cancelButton::fire); } private void loadDependencies(RemoteMod.Version version, DownloadPage selfPage, SpinnerPane spinnerPane, ComponentList dependenciesList) { From 85886da770de557209ccb9726bd7d90ba6d0e560 Mon Sep 17 00:00:00 2001 From: Glavo Date: Wed, 1 Jan 2025 05:14:14 +0800 Subject: [PATCH 146/169] Bump Mesa to 24.3.2 (#3515) * Bump Mesa to 24.3.2 * update --- .../jackhuang/hmcl/util/NativePatcher.java | 2 +- HMCL/src/main/resources/assets/natives.json | 44 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java index 82ccd9fc3b..8052493ee9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java @@ -153,6 +153,6 @@ public static Version patchNative(Version version, String gameVersion, JavaRunti } public static Library getMesaLoader(JavaRuntime javaVersion, Renderer renderer) { - return getNatives(javaVersion.getPlatform()).get(renderer == Renderer.LLVMPIPE ? "software-renderer-loader" : "mesa-loader"); + return getNatives(javaVersion.getPlatform()).get("mesa-loader"); } } diff --git a/HMCL/src/main/resources/assets/natives.json b/HMCL/src/main/resources/assets/natives.json index 7f4f6eaaff..2c3c4d50b1 100644 --- a/HMCL/src/main/resources/assets/natives.json +++ b/HMCL/src/main/resources/assets/natives.json @@ -3986,38 +3986,27 @@ "com.mojang:text2speech:1.13.9:natives-linux": null }, "windows-x86_64": { - "software-renderer-loader": { - "name": "org.glavo:llvmpipe-loader:1.0", - "downloads": { - "artifact": { - "path": "org/glavo/llvmpipe-loader/1.0/llvmpipe-loader-1.0.jar", - "url": "https://repo1.maven.org/maven2/org/glavo/llvmpipe-loader/1.0/llvmpipe-loader-1.0.jar", - "sha1": "ff255415e5c4b2a18970da0a8e552b557ca013ae", - "size": 12964773 - } - } - }, "mesa-loader": { - "name": "org.glavo:mesa-loader-windows:0.2.0:x64", + "name": "org.glavo:mesa-loader-windows:0.3.0:x64", "downloads": { "artifact": { - "path": "org/glavo/mesa-loader-windows/0.2.0/mesa-loader-windows-0.2.0-x64.jar", - "url": "https://repo1.maven.org/maven2/org/glavo/mesa-loader-windows/0.2.0/mesa-loader-windows-0.2.0-x64.jar", - "sha1": "adb4a16ecb95c8944a016829b05d70f934ea1a29", - "size": 22823052 + "path": "org/glavo/mesa-loader-windows/0.3.0/mesa-loader-windows-0.3.0-x64.jar", + "url": "https://repo1.maven.org/maven2/org/glavo/mesa-loader-windows/0.3.0/mesa-loader-windows-0.3.0-x64.jar", + "sha1": "629fca32417d6ec489cef8b2cbd0827131ec6801", + "size": 27174940 } } } }, "windows-x86": { "mesa-loader": { - "name": "org.glavo:mesa-loader-windows:0.2.0:x86", + "name": "org.glavo:mesa-loader-windows:0.3.0:x86", "downloads": { "artifact": { - "path": "org/glavo/mesa-loader-windows/0.2.0/mesa-loader-windows-0.2.0-x86.jar", - "url": "https://repo1.maven.org/maven2/org/glavo/mesa-loader-windows/0.2.0/mesa-loader-windows-0.2.0-x86.jar", - "sha1": "93c0b9b7382d984e713d3aa299ceb337fde2897b", - "size": 18273286 + "path": "org/glavo/mesa-loader-windows/0.3.0/mesa-loader-windows-0.3.0-x86.jar", + "url": "https://repo1.maven.org/maven2/org/glavo/mesa-loader-windows/0.3.0/mesa-loader-windows-0.3.0-x86.jar", + "sha1": "d25e0cdf5c5eb182acc9b93f700e0e6d8de36283", + "size": 22528549 } } } @@ -4398,7 +4387,18 @@ "com.mojang:text2speech:1.10.3:natives": null, "com.mojang:text2speech:1.11.3:natives": null, "com.mojang:text2speech:1.12.4:natives": null, - "com.mojang:text2speech:1.13.9:natives-windows": null + "com.mojang:text2speech:1.13.9:natives-windows": null, + "mesa-loader": { + "name": "org.glavo:mesa-loader-windows:0.3.0:arm64", + "downloads": { + "artifact": { + "path": "org/glavo/mesa-loader-windows/0.3.0/mesa-loader-windows-0.3.0-arm64.jar", + "url": "https://repo1.maven.org/maven2/org/glavo/mesa-loader-windows/0.3.0/mesa-loader-windows-0.3.0-arm64.jar", + "sha1": "1986490c6fbe950e64018c2fb62c8ecf77a247ed", + "size": 24082103 + } + } + } }, "osx-arm64": { "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20130708-debug3:natives": { From d61826ba4c4b409f17e4f0cc0e6de90cd7269f39 Mon Sep 17 00:00:00 2001 From: Glavo Date: Wed, 1 Jan 2025 05:37:30 +0800 Subject: [PATCH 147/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20Release=20Note=20(?= =?UTF-8?q?#3516)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/check-update.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check-update.yml b/.github/workflows/check-update.yml index 8fd415ff30..f112915e7d 100644 --- a/.github/workflows/check-update.yml +++ b/.github/workflows/check-update.yml @@ -54,9 +54,9 @@ jobs: echo "" >> RELEASE_NOTE echo "| File Name | SHA-256 Checksum |" >> RELEASE_NOTE echo "| --- | --- |" >> RELEASE_NOTE - echo "| [HMCL-$HMCL_VERSION.exe]($GH_DOWNLOAD_BASE_URL/v$HMCL_VERSION/HMCL-$HMCL_VERSION.exe) | $(cat HMCL-$HMCL_VERSION.exe.sha256) |" >> RELEASE_NOTE - echo "| [HMCL-$HMCL_VERSION.jar]($GH_DOWNLOAD_BASE_URL/v$HMCL_VERSION/HMCL-$HMCL_VERSION.jar) | $(cat HMCL-$HMCL_VERSION.jar.sha256) |" >> RELEASE_NOTE - echo "| [HMCL-$HMCL_VERSION.sh]($GH_DOWNLOAD_BASE_URL/v$HMCL_VERSION/HMCL-$HMCL_VERSION.sh) | $(cat HMCL-$HMCL_VERSION.sh.sha256) |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.exe]($GH_DOWNLOAD_BASE_URL/v$HMCL_VERSION/HMCL-$HMCL_VERSION.exe) | \`$(cat HMCL-$HMCL_VERSION.exe.sha256)\` |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.jar]($GH_DOWNLOAD_BASE_URL/v$HMCL_VERSION/HMCL-$HMCL_VERSION.jar) | \`$(cat HMCL-$HMCL_VERSION.jar.sha256)\` |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.sh]($GH_DOWNLOAD_BASE_URL/v$HMCL_VERSION/HMCL-$HMCL_VERSION.sh) | \`$(cat HMCL-$HMCL_VERSION.sh.sha256)\` |" >> RELEASE_NOTE env: GH_DOWNLOAD_BASE_URL: https://github.com/HMCL-dev/HMCL/releases/download - name: Create release @@ -121,9 +121,9 @@ jobs: echo "" >> RELEASE_NOTE echo "| File Name | SHA-256 Checksum |" >> RELEASE_NOTE echo "| --- | --- |" >> RELEASE_NOTE - echo "| [HMCL-$HMCL_VERSION.exe]($GH_DOWNLOAD_BASE_URL/release-$HMCL_VERSION/HMCL-$HMCL_VERSION.exe) | $(cat HMCL-$HMCL_VERSION.exe.sha256) |" >> RELEASE_NOTE - echo "| [HMCL-$HMCL_VERSION.jar]($GH_DOWNLOAD_BASE_URL/release-$HMCL_VERSION/HMCL-$HMCL_VERSION.jar) | $(cat HMCL-$HMCL_VERSION.jar.sha256) |" >> RELEASE_NOTE - echo "| [HMCL-$HMCL_VERSION.sh]($GH_DOWNLOAD_BASE_URL/release-$HMCL_VERSION/HMCL-$HMCL_VERSION.sh) | $(cat HMCL-$HMCL_VERSION.sh.sha256) |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.exe]($GH_DOWNLOAD_BASE_URL/release-$HMCL_VERSION/HMCL-$HMCL_VERSION.exe) | \`$(cat HMCL-$HMCL_VERSION.exe.sha256)\` |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.jar]($GH_DOWNLOAD_BASE_URL/release-$HMCL_VERSION/HMCL-$HMCL_VERSION.jar) | \`$(cat HMCL-$HMCL_VERSION.jar.sha256)\` |" >> RELEASE_NOTE + echo "| [HMCL-$HMCL_VERSION.sh]($GH_DOWNLOAD_BASE_URL/release-$HMCL_VERSION/HMCL-$HMCL_VERSION.sh) | \`$(cat HMCL-$HMCL_VERSION.sh.sha256)\` |" >> RELEASE_NOTE env: GH_DOWNLOAD_BASE_URL: https://github.com/HMCL-dev/HMCL/releases/download - name: Create release From 5197157a97598975b70ef952200dbc02f1c08998 Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Wed, 1 Jan 2025 05:21:31 +0000 Subject: [PATCH 148/169] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=90=9C=E7=B4=A2?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/ui/download/VersionsPage.java | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index a64bf1aeae..e96e44d4e1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -21,12 +21,16 @@ import com.jfoenix.controls.JFXCheckBox; import com.jfoenix.controls.JFXListView; import com.jfoenix.controls.JFXSpinner; +import com.jfoenix.controls.JFXTextField; +import javafx.animation.PauseTransition; import javafx.application.Platform; import javafx.beans.InvalidationListener; import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.layout.*; +import javafx.util.Duration; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.VersionList; @@ -55,14 +59,18 @@ import org.jackhuang.hmcl.util.Holder; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.function.Predicate; +import java.util.regex.Pattern; import java.util.stream.Collectors; import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.wrap; import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.formatDateTime; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; +import static org.jackhuang.hmcl.util.StringUtils.isBlank; public final class VersionsPage extends BorderPane implements WizardPage, Refreshable { private final String gameVersion; @@ -86,6 +94,11 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres private final VersionList versionList; private CompletableFuture executor; + private final TransitionPane toolbarPane; + private final HBox searchBar; + private final JFXTextField searchField; + private boolean isSearching = false; + public VersionsPage(Navigation navigation, String title, String gameVersion, DownloadProvider downloadProvider, String libraryId, Runnable callback) { this.title = title; this.gameVersion = gameVersion; @@ -187,6 +200,49 @@ public VersionsPage(Navigation navigation, String title, String gameVersion, Dow callback.run(); }); + { + toolbarPane = new TransitionPane(); + searchBar = new HBox(); + searchBar.setAlignment(Pos.CENTER); + searchBar.setPadding(new Insets(0, 5, 0, 5)); + searchField = new JFXTextField(); + searchField.setPromptText(i18n("search")); + HBox.setHgrow(searchField, Priority.ALWAYS); + + JFXButton closeSearchBar = new JFXButton(); + closeSearchBar.getStyleClass().add("jfx-tool-bar-button"); + closeSearchBar.setGraphic(wrap(SVG.CLOSE.createIcon(Theme.blackFill(), -1, -1))); + closeSearchBar.setOnAction(e -> { + toolbarPane.setContent(checkPane, ContainerAnimations.FADE); + isSearching = false; + searchField.clear(); + list.getItems().setAll(loadVersions()); + }); + + searchBar.getChildren().setAll(searchField, closeSearchBar); + + JFXButton searchButton = new JFXButton(i18n("search")); + searchButton.getStyleClass().add("jfx-tool-bar-button"); + searchButton.setGraphic(wrap(SVG.MAGNIFY.createIcon(Theme.blackFill(), -1, -1))); + searchButton.setOnAction(e -> { + toolbarPane.setContent(searchBar, ContainerAnimations.FADE); + searchField.requestFocus(); + }); + + checkPane.getChildren().add(checkPane.getChildren().size() - 1, searchButton); + + centrePane.getContent().remove(checkPane); + toolbarPane.setContent(checkPane, ContainerAnimations.FADE); + centrePane.getContent().add(0, toolbarPane); + + PauseTransition pause = new PauseTransition(Duration.millis(100)); + pause.setOnFinished(e -> search()); + searchField.textProperty().addListener((observable, oldValue, newValue) -> { + pause.setRate(1); + pause.playFromStart(); + }); + } + refresh(); } @@ -265,6 +321,37 @@ private void onSponsor() { FXUtils.openLink("https://bmclapidoc.bangbang93.com"); } + private void search() { + isSearching = true; + String queryString = searchField.getText(); + + if (isBlank(queryString)) { + list.getItems().setAll(loadVersions()); + } else { + list.getItems().clear(); + + Predicate predicate; + if (queryString.startsWith("regex:")) { + try { + Pattern pattern = Pattern.compile(queryString.substring("regex:".length())); + predicate = s -> pattern.matcher(s).find(); + } catch (Throwable e) { + LOG.warning("Illegal regular expression", e); + return; + } + } else { + String lowerQueryString = queryString.toLowerCase(Locale.ROOT); + predicate = s -> s.toLowerCase(Locale.ROOT).contains(lowerQueryString); + } + + for (RemoteVersion version : loadVersions()) { + if (predicate.test(version.getSelfVersion())) { + list.getItems().add(version); + } + } + } + } + private static class RemoteVersionListCell extends ListCell { final IconedTwoLineListItem content = new IconedTwoLineListItem(); final RipplerContainer ripplerContainer = new RipplerContainer(content); From 39b8de4824ac561403aef416d8bfa0772e002f89 Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Wed, 1 Jan 2025 07:40:13 +0000 Subject: [PATCH 149/169] fix --- .../org/jackhuang/hmcl/ui/download/VersionsPage.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index e96e44d4e1..35974e30e5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -176,7 +176,15 @@ public VersionsPage(Navigation navigation, String title, String gameVersion, Dow this.setCenter(root); versionList = downloadProvider.getVersionListById(libraryId); - if (versionList.hasType()) { + boolean hasType = versionList.hasType(); + chkRelease.setManaged(hasType); + chkRelease.setVisible(hasType); + chkSnapshot.setManaged(hasType); + chkSnapshot.setVisible(hasType); + chkOld.setManaged(hasType); + chkOld.setVisible(hasType); + + if (hasType) { centrePane.getContent().setAll(checkPane, list); } else { centrePane.getContent().setAll(list); From 397edaec5de950b6d6236d80d660493ed751facd Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Wed, 1 Jan 2025 21:15:09 +0800 Subject: [PATCH 150/169] Press ESC in search box to exit search --- .../main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index 35974e30e5..8a94ab9703 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -66,6 +66,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.wrap; import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.formatDateTime; @@ -226,6 +227,7 @@ public VersionsPage(Navigation navigation, String title, String gameVersion, Dow searchField.clear(); list.getItems().setAll(loadVersions()); }); + onEscPressed(searchField, closeSearchBar::fire); searchBar.getChildren().setAll(searchField, closeSearchBar); From b5cea83a8a0e748b2c25c9fa5c3317f1302c448f Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Tue, 31 Dec 2024 22:08:54 +0800 Subject: [PATCH 151/169] Workaround for JDK-8344372 https://bugs.openjdk.org/browse/JDK-8344372 --- .../jackhuang/hmcl/ui/decorator/DecoratorSkin.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index bbcf7585c1..b65c0b3c06 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -324,12 +324,17 @@ private boolean isLeftEdge(double x, double y, Bounds boundsInParent) { private boolean setStageWidth(double width) { if (width >= primaryStage.getMinWidth() && width >= titleContainer.getMinWidth()) { + // Workaround for JDK-8344372 (https://github.com/openjdk/jfx/pull/1654) + // Width and height must be set simultaneously to avoid the bug primaryStage.setWidth(width); + primaryStage.setHeight(primaryStage.getHeight()); initX = newX; return true; } else { - if (width >= primaryStage.getMinWidth() && width <= titleContainer.getMinWidth()) + if (width >= primaryStage.getMinWidth() && width <= titleContainer.getMinWidth()) { primaryStage.setWidth(titleContainer.getMinWidth()); + primaryStage.setHeight(primaryStage.getHeight()); + } return false; } @@ -338,11 +343,14 @@ private boolean setStageWidth(double width) { private boolean setStageHeight(double height) { if (height >= primaryStage.getMinHeight() && height >= titleContainer.getHeight()) { primaryStage.setHeight(height); + primaryStage.setWidth(primaryStage.getWidth()); initY = newY; return true; } else { - if (height >= primaryStage.getMinHeight() && height <= titleContainer.getHeight()) + if (height >= primaryStage.getMinHeight() && height <= titleContainer.getHeight()) { primaryStage.setHeight(titleContainer.getHeight()); + primaryStage.setWidth(primaryStage.getWidth()); + } return false; } From 56d20a5d0845adb1f18d2634312c9102aea71d01 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Sat, 4 Jan 2025 00:34:48 +0800 Subject: [PATCH 152/169] Fix problems with window resizing in Linux --- .../hmcl/ui/decorator/DecoratorSkin.java | 257 ++++++++---------- 1 file changed, 117 insertions(+), 140 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index b65c0b3c06..d179cedb45 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -48,8 +48,7 @@ public class DecoratorSkin extends SkinBase { private final Stage primaryStage; private final TransitionPane navBarPane; - private double xOffset, yOffset, newX, newY, initX, initY; - private boolean titleBarTransparent = true; + private double mouseInitX, mouseInitY, stageInitX, stageInitY, stageInitWidth, stageInitHeight; /** * Constructor for all SkinBase instances. @@ -299,13 +298,6 @@ private Node createNavBar(Decorator skinnable, double leftPaneWidth, boolean can return navBar; } - private void updateInitMouseValues(MouseEvent mouseEvent) { - initX = mouseEvent.getScreenX(); - initY = mouseEvent.getScreenY(); - xOffset = mouseEvent.getSceneX(); - yOffset = mouseEvent.getSceneY(); - } - private boolean isRightEdge(double x, double y, Bounds boundsInParent) { return x < root.getWidth() && x >= root.getWidth() - root.snappedLeftInset(); } @@ -322,154 +314,139 @@ private boolean isLeftEdge(double x, double y, Bounds boundsInParent) { return x >= 0 && x <= root.snappedLeftInset(); } - private boolean setStageWidth(double width) { - if (width >= primaryStage.getMinWidth() && width >= titleContainer.getMinWidth()) { - // Workaround for JDK-8344372 (https://github.com/openjdk/jfx/pull/1654) - // Width and height must be set simultaneously to avoid the bug - primaryStage.setWidth(width); - primaryStage.setHeight(primaryStage.getHeight()); - initX = newX; - return true; - } else { - if (width >= primaryStage.getMinWidth() && width <= titleContainer.getMinWidth()) { - primaryStage.setWidth(titleContainer.getMinWidth()); - primaryStage.setHeight(primaryStage.getHeight()); - } - - return false; - } - } - - private boolean setStageHeight(double height) { - if (height >= primaryStage.getMinHeight() && height >= titleContainer.getHeight()) { - primaryStage.setHeight(height); - primaryStage.setWidth(primaryStage.getWidth()); - initY = newY; - return true; - } else { - if (height >= primaryStage.getMinHeight() && height <= titleContainer.getHeight()) { - primaryStage.setHeight(titleContainer.getHeight()); - primaryStage.setWidth(primaryStage.getWidth()); - } - - return false; - } + private void resizeStage(double newWidth, double newHeight) { + if (newWidth < 0) + newWidth = primaryStage.getWidth(); + if (newWidth < primaryStage.getMinWidth()) + newWidth = primaryStage.getMinWidth(); + if (newWidth < titleContainer.getMinWidth()) + newWidth = titleContainer.getMinWidth(); + + if (newHeight < 0) + newHeight = primaryStage.getHeight(); + if (newHeight < primaryStage.getMinHeight()) + newHeight = primaryStage.getMinHeight(); + if (newHeight < titleContainer.getMinHeight()) + newHeight = titleContainer.getMinHeight(); + + // Width and height must be set simultaneously to avoid JDK-8344372 (https://github.com/openjdk/jfx/pull/1654) + primaryStage.setWidth(newWidth); + primaryStage.setHeight(newHeight); } - // ==== - - protected void onMouseMoved(MouseEvent mouseEvent) { - if (!primaryStage.isFullScreen()) { - updateInitMouseValues(mouseEvent); - if (primaryStage.isResizable()) { - double x = mouseEvent.getX(), y = mouseEvent.getY(); - Bounds boundsInParent = root.getBoundsInParent(); - double diagonalSize = root.snappedLeftInset() + 10; - if (this.isRightEdge(x, y, boundsInParent)) { - if (y < diagonalSize) { - root.setCursor(Cursor.NE_RESIZE); - } else if (y > root.getHeight() - diagonalSize) { - root.setCursor(Cursor.SE_RESIZE); - } else { - root.setCursor(Cursor.E_RESIZE); - } - } else if (this.isLeftEdge(x, y, boundsInParent)) { - if (y < diagonalSize) { - root.setCursor(Cursor.NW_RESIZE); - } else if (y > root.getHeight() - diagonalSize) { - root.setCursor(Cursor.SW_RESIZE); - } else { - root.setCursor(Cursor.W_RESIZE); - } - } else if (this.isTopEdge(x, y, boundsInParent)) { - if (x < diagonalSize) { - root.setCursor(Cursor.NW_RESIZE); - } else if (x > root.getWidth() - diagonalSize) { - root.setCursor(Cursor.NE_RESIZE); - } else { - root.setCursor(Cursor.N_RESIZE); - } - } else if (this.isBottomEdge(x, y, boundsInParent)) { - if (x < diagonalSize) { - root.setCursor(Cursor.SW_RESIZE); - } else if (x > root.getWidth() - diagonalSize) { - root.setCursor(Cursor.SE_RESIZE); - } else { - root.setCursor(Cursor.S_RESIZE); - } + private void onMouseMoved(MouseEvent mouseEvent) { + if (!primaryStage.isFullScreen() && primaryStage.isResizable()) { + double x = mouseEvent.getX(), y = mouseEvent.getY(); + Bounds boundsInParent = root.getBoundsInParent(); + double diagonalSize = root.snappedLeftInset() + 10; + if (this.isRightEdge(x, y, boundsInParent)) { + if (y < diagonalSize) { + root.setCursor(Cursor.NE_RESIZE); + } else if (y > root.getHeight() - diagonalSize) { + root.setCursor(Cursor.SE_RESIZE); } else { - root.setCursor(Cursor.DEFAULT); + root.setCursor(Cursor.E_RESIZE); } + } else if (this.isLeftEdge(x, y, boundsInParent)) { + if (y < diagonalSize) { + root.setCursor(Cursor.NW_RESIZE); + } else if (y > root.getHeight() - diagonalSize) { + root.setCursor(Cursor.SW_RESIZE); + } else { + root.setCursor(Cursor.W_RESIZE); + } + } else if (this.isTopEdge(x, y, boundsInParent)) { + if (x < diagonalSize) { + root.setCursor(Cursor.NW_RESIZE); + } else if (x > root.getWidth() - diagonalSize) { + root.setCursor(Cursor.NE_RESIZE); + } else { + root.setCursor(Cursor.N_RESIZE); + } + } else if (this.isBottomEdge(x, y, boundsInParent)) { + if (x < diagonalSize) { + root.setCursor(Cursor.SW_RESIZE); + } else if (x > root.getWidth() - diagonalSize) { + root.setCursor(Cursor.SE_RESIZE); + } else { + root.setCursor(Cursor.S_RESIZE); + } + } else { + root.setCursor(Cursor.DEFAULT); } } else { root.setCursor(Cursor.DEFAULT); } } - protected void onMouseReleased(MouseEvent mouseEvent) { + private void onMouseReleased(MouseEvent mouseEvent) { getSkinnable().setDragging(false); } - protected void onMouseDragged(MouseEvent mouseEvent) { - getSkinnable().setDragging(true); - if (mouseEvent.isPrimaryButtonDown() && (this.xOffset != -1.0 || this.yOffset != -1.0)) { - if (!this.primaryStage.isFullScreen() && !mouseEvent.isStillSincePress()) { - this.newX = mouseEvent.getScreenX(); - this.newY = mouseEvent.getScreenY(); - double deltaX = this.newX - this.initX; - double deltaY = this.newY - this.initY; - Cursor cursor = root.getCursor(); - if (Cursor.E_RESIZE == cursor) { - this.setStageWidth(this.primaryStage.getWidth() + deltaX); - mouseEvent.consume(); - } else if (Cursor.NE_RESIZE == cursor) { - if (this.setStageHeight(this.primaryStage.getHeight() - deltaY)) { - this.primaryStage.setY(this.primaryStage.getY() + deltaY); - } - - this.setStageWidth(this.primaryStage.getWidth() + deltaX); - mouseEvent.consume(); - } else if (Cursor.SE_RESIZE == cursor) { - this.setStageWidth(this.primaryStage.getWidth() + deltaX); - this.setStageHeight(this.primaryStage.getHeight() + deltaY); - mouseEvent.consume(); - } else if (Cursor.S_RESIZE == cursor) { - this.setStageHeight(this.primaryStage.getHeight() + deltaY); - mouseEvent.consume(); - } else if (Cursor.W_RESIZE == cursor) { - if (this.setStageWidth(this.primaryStage.getWidth() - deltaX)) { - this.primaryStage.setX(this.primaryStage.getX() + deltaX); - } + private void onMouseDragged(MouseEvent mouseEvent) { + if (!getSkinnable().isDragging()) { + getSkinnable().setDragging(true); + mouseInitX = mouseEvent.getScreenX(); + mouseInitY = mouseEvent.getScreenY(); + stageInitX = primaryStage.getX(); + stageInitY = primaryStage.getY(); + stageInitWidth = primaryStage.getWidth(); + stageInitHeight = primaryStage.getHeight(); + } - mouseEvent.consume(); - } else if (Cursor.SW_RESIZE == cursor) { - if (this.setStageWidth(this.primaryStage.getWidth() - deltaX)) { - this.primaryStage.setX(this.primaryStage.getX() + deltaX); - } + if (primaryStage.isFullScreen() || !mouseEvent.isPrimaryButtonDown() || mouseEvent.isStillSincePress()) + return; - this.setStageHeight(this.primaryStage.getHeight() + deltaY); - mouseEvent.consume(); - } else if (Cursor.NW_RESIZE == cursor) { - if (this.setStageWidth(this.primaryStage.getWidth() - deltaX)) { - this.primaryStage.setX(this.primaryStage.getX() + deltaX); - } - - if (this.setStageHeight(this.primaryStage.getHeight() - deltaY)) { - this.primaryStage.setY(this.primaryStage.getY() + deltaY); - } + double dx = mouseEvent.getScreenX() - mouseInitX; + double dy = mouseEvent.getScreenY() - mouseInitY; - mouseEvent.consume(); - } else if (Cursor.N_RESIZE == cursor) { - if (this.setStageHeight(this.primaryStage.getHeight() - deltaY)) { - this.primaryStage.setY(this.primaryStage.getY() + deltaY); - } + Cursor cursor = root.getCursor(); + if (getSkinnable().isAllowMove()) { + if (cursor == Cursor.DEFAULT) { + primaryStage.setX(stageInitX + dx); + primaryStage.setY(stageInitY + dy); + mouseEvent.consume(); + } + } - mouseEvent.consume(); - } else if (getSkinnable().isAllowMove()) { - this.primaryStage.setX(mouseEvent.getScreenX() - this.xOffset); - this.primaryStage.setY(mouseEvent.getScreenY() - this.yOffset); - mouseEvent.consume(); - } + if (getSkinnable().isResizable()) { + if (cursor == Cursor.E_RESIZE) { + resizeStage(stageInitWidth + dx, -1); + mouseEvent.consume(); + + } else if (cursor == Cursor.S_RESIZE) { + resizeStage(-1, stageInitHeight + dy); + mouseEvent.consume(); + + } else if (cursor == Cursor.W_RESIZE) { + resizeStage(stageInitWidth - dx, -1); + primaryStage.setX(stageInitX + stageInitWidth - primaryStage.getWidth()); + mouseEvent.consume(); + + } else if (cursor == Cursor.N_RESIZE) { + resizeStage(-1, stageInitHeight - dy); + primaryStage.setY(stageInitY + stageInitHeight - primaryStage.getHeight()); + mouseEvent.consume(); + + } else if (cursor == Cursor.SE_RESIZE) { + resizeStage(stageInitWidth + dx, stageInitHeight + dy); + mouseEvent.consume(); + + } else if (cursor == Cursor.SW_RESIZE) { + resizeStage(stageInitWidth - dx, stageInitHeight + dy); + primaryStage.setX(stageInitX + stageInitWidth - primaryStage.getWidth()); + mouseEvent.consume(); + + } else if (cursor == Cursor.NW_RESIZE) { + resizeStage(stageInitWidth - dx, stageInitHeight - dy); + primaryStage.setX(stageInitX + stageInitWidth - primaryStage.getWidth()); + primaryStage.setY(stageInitY + stageInitHeight - primaryStage.getHeight()); + mouseEvent.consume(); + + } else if (cursor == Cursor.NE_RESIZE) { + resizeStage(stageInitWidth + dx, stageInitHeight - dy); + primaryStage.setY(stageInitY + stageInitHeight - primaryStage.getHeight()); + mouseEvent.consume(); } } } From 1f7b15642373a4e208ea600985107769060aae73 Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Sat, 4 Jan 2025 01:38:11 +0800 Subject: [PATCH 153/169] Press ESC in search box to exit search (#3519) --- .../java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index 028e74883b..61674d3ed9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -131,6 +131,8 @@ class ModListPageSkin extends SkinBase { Bindings.bindContent(listView.getItems(), getSkinnable().getItems()); }); + onEscPressed(searchField, closeSearchBar::fire); + searchBar.getChildren().setAll(searchField, closeSearchBar); // Toolbar Normal From d80f61e2e76cda846f5bbcef8828117bd11fc49e Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Sat, 4 Jan 2025 21:33:48 +0800 Subject: [PATCH 154/169] update getAssetIndex() (#3252) * update getAssetIndex() * update --------- Co-authored-by: Glavo --- .../java/org/jackhuang/hmcl/game/Version.java | 53 +++++++++++++------ .../org/jackhuang/hmcl/util/Constants.java | 2 +- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java index 16bda75f0f..e7e808be8a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/Version.java @@ -18,25 +18,13 @@ package org.jackhuang.hmcl.game; import com.google.gson.JsonParseException; -import org.jackhuang.hmcl.util.Constants; -import org.jackhuang.hmcl.util.Immutable; -import org.jackhuang.hmcl.util.Lang; -import org.jackhuang.hmcl.util.StringUtils; -import org.jackhuang.hmcl.util.ToStringBuilder; +import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.gson.JsonMap; import org.jackhuang.hmcl.util.gson.Validation; import org.jetbrains.annotations.Nullable; import java.time.Instant; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -229,7 +217,42 @@ public DownloadInfo getDownloadInfo() { public AssetIndexInfo getAssetIndex() { String assetsId = assets == null ? "legacy" : assets; - return assetIndex == null ? new AssetIndexInfo(assetsId, Constants.DEFAULT_INDEX_URL + assetsId + ".json") : assetIndex; + + if (assetIndex == null) { + String hash; + switch (assetsId) { + case "1.8": + hash = "f6ad102bcaa53b1a58358f16e376d548d44933ec"; + break; + case "14w31a": + hash = "10a2a0e75b03cfb5a7196abbdf43b54f7fa61deb"; + break; + case "14w25a": + hash = "32ff354a3be1c4dd83027111e6d79ee4d701d2c0"; + break; + case "1.7.4": + hash = "545510a60f526b9aa8a38f9c0bc7a74235d21675"; + break; + case "1.7.10": + hash = "1863782e33ce7b584fc45b037325a1964e095d3e"; + break; + case "1.7.3": + hash = "f6cf726f4747128d13887010c2cbc44ba83504d9"; + break; + case "pre-1.6": + hash = "3d8e55480977e32acd9844e545177e69a52f594b"; + break; + case "legacy": + default: + assetsId = "legacy"; + hash = "770572e819335b6c0a053f8378ad88eda189fc14"; + } + + String url = Constants.DEFAULT_INDEX_URL + hash + "/" + assetsId + ".json"; + return new AssetIndexInfo(assetsId, url); + } else { + return assetIndex; + } } public boolean appliesToCurrentEnvironment() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.java index 55717ea90a..34da8d031d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.java @@ -29,5 +29,5 @@ private Constants() { public static final String DEFAULT_LIBRARY_URL = "https://libraries.minecraft.net/"; public static final String DEFAULT_VERSION_DOWNLOAD_URL = "https://bmclapi2.bangbang93.com/versions/"; - public static final String DEFAULT_INDEX_URL = "https://launchermeta.mojang.com/mc-staging/assets/legacy/c0fd82e8ce9fbc93119e40d96d5a4e62cfa3f729/"; + public static final String DEFAULT_INDEX_URL = "https://launchermeta.mojang.com/v1/packages/"; } From bfda2978386c2c4edbdba23c6436003d0390ed11 Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Sun, 5 Jan 2025 01:31:44 +0800 Subject: [PATCH 155/169] =?UTF-8?q?=E6=A3=80=E6=9F=A5=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E9=9D=9EASCII=E5=AD=97=E7=AC=A6=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=20(#3244)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 检查安装时的非ASCII字符名称 * i18n * 添加导出模组列表信息功能 * Revert "添加导出模组列表信息功能" This reverts commit 6505d1c28465b88b8af8e7347a254bc7804c8593. * Update HMCL/src/main/resources/assets/lang/I18N.properties Co-authored-by: 3gf8jv4dv <158490944+3gf8jv4dv@users.noreply.github.com> * Update HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties Co-authored-by: 3gf8jv4dv <158490944+3gf8jv4dv@users.noreply.github.com> * Update HMCL/src/main/resources/assets/lang/I18N_zh.properties Co-authored-by: 3gf8jv4dv <158490944+3gf8jv4dv@users.noreply.github.com> --------- Co-authored-by: 3gf8jv4dv <158490944+3gf8jv4dv@users.noreply.github.com> --- .../hmcl/ui/download/InstallersPage.java | 22 ++++++++++++++-- .../hmcl/ui/download/LocalModpackPage.java | 26 ++++++++++++++++--- .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index e5e935eb1a..8a80a0ba1b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -40,6 +40,7 @@ import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; +import java.nio.charset.StandardCharsets; import java.util.Map; import static javafx.beans.binding.Bindings.createBooleanBinding; @@ -121,8 +122,25 @@ public void cleanup(Map settings) { } protected void onInstall() { - controller.getSettings().put("name", txtName.getText()); - controller.onFinish(); + String name = txtName.getText(); + + // Check for non-ASCII characters. + if (!StandardCharsets.US_ASCII.newEncoder().canEncode(name)) { + Controllers.dialog(new MessageDialogPane.Builder( + i18n("install.name.invalid"), + i18n("message.warning"), + MessageDialogPane.MessageType.QUESTION) + .yesOrNo(() -> { + controller.getSettings().put("name", name); + controller.onFinish(); + }, () -> { + // The user selects Cancel and does nothing. + }) + .build()); + } else { + controller.getSettings().put("name", name); + controller.onFinish(); + } } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java index eb9e3f441a..9c3b4fab2e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java @@ -42,6 +42,7 @@ import java.io.File; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Optional; @@ -149,10 +150,27 @@ public void cleanup(Map settings) { } protected void onInstall() { - if (!txtModpackName.validate()) return; - controller.getSettings().put(MODPACK_NAME, txtModpackName.getText()); - controller.getSettings().put(MODPACK_CHARSET, charset); - controller.onFinish(); + String name = txtModpackName.getText(); + + // Check for non-ASCII characters. + if (!StandardCharsets.US_ASCII.newEncoder().canEncode(name)) { + Controllers.dialog(new MessageDialogPane.Builder( + i18n("install.name.invalid"), + i18n("message.warning"), + MessageDialogPane.MessageType.QUESTION) + .yesOrNo(() -> { + controller.getSettings().put(MODPACK_NAME, name); + controller.getSettings().put(MODPACK_CHARSET, charset); + controller.onFinish(); + }, () -> { + // The user selects Cancel and does nothing. + }) + .build()); + } else { + controller.getSettings().put(MODPACK_NAME, name); + controller.getSettings().put(MODPACK_CHARSET, charset); + controller.onFinish(); + } } protected void onDescribe() { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 79f5b8394b..03edcab3cb 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -696,6 +696,7 @@ install.installer.quilt-api=QSL/QFAPI install.installer.version=%s install.installer.external_version=%s (Installed by external process, which cannot be configured) install.modpack=Install Modpack +install.name.invalid=The name contains non-ASCII characters (such as emoji or CJK characters).\nIt is recommended to modify the name to include only English letters, numbers and underscores to avoid potential issues when launching the game. \nDo you want to proceed with the installation? install.new_game=Install Instance install.new_game.already_exists=This instance name already exists. Please use another name. install.new_game.current_game_version=Current Instance Version diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 4058fadbfb..f6bcc77c28 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -510,6 +510,7 @@ install.installer.quilt-api=QSL/QFAPI install.installer.version=%s install.installer.external_version=%s [由外部安裝的版本,無法解除安裝或更換] install.modpack=安裝模組包 +install.name.invalid=名稱中包含非 ASCII 字元(如 Emoji 表情或中文字元)。\n建議修改名稱,名稱建議僅包含英文字母、數字和底線,以防啟動遊戲時出現問題。是否繼續安裝? install.new_game=安裝新實例 install.new_game.already_exists=此實例已經存在,請重新命名 install.new_game.current_game_version=目前遊戲版本 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 a521d602fd..e516c160d9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -521,6 +521,7 @@ install.installer.quilt-api=QSL/QFAPI install.installer.version=%s install.installer.external_version=%s (由外部安装的版本,无法卸载或更换) install.modpack=安装整合包 +install.name.invalid=名称中包含非 ASCII 字符(如 Emoji 表情或中文字符)。\n建议修改名称,名称建议仅包含英文字母、数字和下划线,以防启动游戏时出现问题。是否继续安装? install.new_game=安装新游戏 install.new_game.already_exists=此版本已经存在,请换一个名字 install.new_game.current_game_version=当前游戏版本 From 662bf1a9d416c481b0a76bf41e35c280face6ffd Mon Sep 17 00:00:00 2001 From: lijiaxuan <132456728+lijiaxuan1811@users.noreply.github.com> Date: Sun, 5 Jan 2025 13:15:58 -0500 Subject: [PATCH 156/169] Update I18N.properties English Translations (#3477) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update I18N.properties English Translations 更新了英文语言翻译文件,修复了一些语法错误并且让一些句子更加通顺 * Update I18N.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> * Update I18N.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> * Update I18N.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> * Update I18N.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> * Update HMCL/src/main/resources/assets/lang/I18N.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> * Update I18N.properties * Update HMCL/src/main/resources/assets/lang/I18N.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> * Update HMCL/src/main/resources/assets/lang/I18N.properties Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> --------- Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> --- .../resources/assets/lang/I18N.properties | 128 +++++++++--------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 03edcab3cb..681bd471de 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -66,17 +66,17 @@ account.failed.injector_download_failure=Failed to download the authlib-injector account.failed.invalid_credentials=Incorrect password or rate limited. Please try again later. account.failed.invalid_password=Invalid password. account.failed.invalid_token=Please try logging in again. -account.failed.migration=Your account needs to be migrated to a Microsoft account. If you already did, you should log in to your migrated Microsoft account again. +account.failed.migration=Your account needs to be migrated to a Microsoft account. If you already did, you should log in using your migrated Microsoft account again. account.failed.no_character=There are no characters linked to this account. account.failed.server_disconnected=Failed to connect to the authentication server. You can log in using offline mode or try logging in again.\n\ - If you try several times and still fail, please try logging in to the account again. -account.failed.server_response_malformed=Invalid server response. The authentication server may not be working. + If the issue persists after multiple attempts, please try logging in to the account again. +account.failed.server_response_malformed=Invalid server response. The authentication server may be down. account.failed.ssl=An SSL error occurred while connecting to the server. Please try updating your Java. account.failed.wrong_account=You have logged in to the wrong account. account.hmcl.hint=You need to click "Login" and complete the process in the opened browser window. account.injector.add=New Auth Server account.injector.empty=None (You can click "+" to add one) -account.injector.http=Warning: This server uses the unsafe HTTP protocol. Anyone between your connections will be able to see your credentials in cleartext. +account.injector.http=Warning: This server uses the unsafe HTTP protocol. Anyone intercepting your connection would be able to see your credentials in plaintext. account.injector.link.homepage=Homepage account.injector.link.register=Register account.injector.server=Authentication Server @@ -113,26 +113,26 @@ account.methods.microsoft.hint=Please click "Log in" and copy the code displayed If the token used to log in to the Microsoft account is leaked, you can click "Deauthorize" to deauthorize it. account.methods.microsoft.manual=Your device code is %1$s. Please click here to copy.\n\ \n\ - After clicking "Log in", you should complete the login process in the opened browser window. If it did not show, you can navigate to %2$s manually.\n\ + After clicking "Log in", you should complete the login process in the opened browser window. If that does not show up, you can navigate to %2$s manually.\n\ \n\ If the token used to log in to the Microsoft account is leaked, you can click "Deauthorize" to deauthorize it. account.methods.microsoft.makegameidsettings=Create Profile / Edit Profile Name account.methods.microsoft.profile=Account Profile account.methods.microsoft.purchase=Buy Minecraft -account.methods.microsoft.snapshot=You are using an unofficial build of HMCL. Please download the official build for login. +account.methods.microsoft.snapshot=You are using an unofficial build of HMCL. Please download the official build to log in. account.methods.microsoft.snapshot.website=Official Website account.methods.offline=Offline -account.methods.offline.name.special_characters=Recommended to use English letters, numbers, and underscores -account.methods.offline.name.invalid=Generally, game usernames only allow English letters, numbers, and underscores and cannot exceed 16 characters in length.\n\ +account.methods.offline.name.special_characters=Using only English letters, numbers, and underscores is recommended +account.methods.offline.name.invalid=Generally, game usernames are limited to English letters, numbers, and underscores and cannot exceed 16 characters in length.\n\ \n\ - \ · Some legitimate usernames: HuangYu, huang_Yu, Huang_Yu_123;\n\ - \ · Some illegal usernames: Huang Yu, Huang-Yu_%%%, Huang_Yu_hello_world_hello_world.\n\ + \ · Valid usernames: HuangYu, huang_Yu, Huang_Yu_123;\n\ + \ · Invalid usernames: Huang Yu, Huang-Yu_%%%, Huang_Yu_hello_world_hello_world.\n\ \n\ - If you believe that there is a corresponding mod or plugin on the server side to remove this restriction, you can ignore this warning. + If you believe there is a corresponding mod or plugin on the server side to remove this restriction, you can ignore this warning. account.methods.offline.uuid=UUID -account.methods.offline.uuid.hint=UUID is a unique identifier for Minecraft players, and each launcher may generate UUIDs differently. Editing it to the one generated by other launchers allows you to keep your items in your offline account inventory.\n\ +account.methods.offline.uuid.hint=UUID is a unique identifier for Minecraft players, and each launcher may generate UUIDs differently. Changing it to the one generated by other launchers allows you to keep your items in your offline account inventory.\n\ \n\ - This option is for advanced users only. We do not recommend editing this option unless you know what you are doing. + This option is for advanced users only. We do not recommend changing this option unless you know what you are doing. account.methods.offline.uuid.malformed=Invalid format. account.methods.forgot_password=Forgot Password account.missing=No Accounts @@ -165,7 +165,7 @@ archive.version=Version assets.download=Downloading Assets assets.download_all=Validating Assets Integrity -assets.index.malformed=Index files of downloaded assets were corrupted. You can resolve this problem by clicking "Manage → Update Game Assets" on the "Edit Instance" page. +assets.index.malformed=Index files of downloaded assets are corrupted. You can resolve this problem by clicking "Manage → Update Game Assets" on the "Edit Instance" page. button.cancel=Cancel button.change_source=Change Download Source @@ -193,7 +193,7 @@ color.recent=Recommended color.custom=Custom Color crash.NoClassDefFound=Please verify the integrity of this software, or try updating your Java. -crash.user_fault=The launcher crashed because of corrupted Java or system environment. Please make sure your Java or OS is installed properly. +crash.user_fault=The launcher crashed due to corrupted Java or system environment. Please make sure your Java or OS is installed properly. curse.category.0=All @@ -321,7 +321,7 @@ curse.sort.total_downloads=Total Downloads download=Download download.hint=Install games and modpacks or download mods, resource packs, and worlds. -download.code.404=File not found on the remote server: %s +download.code.404=File "%s" not found on the remote server. download.content=Addons download.curseforge.unavailable=HMCL Nightly channel build does not support access to CurseForge. Please use Release or Beta channel builds to download. download.existing=The file cannot be saved because it already exists. You can click "Save As" to save the file elsewhere. @@ -348,10 +348,10 @@ download.javafx.prepare=Preparing to download exception.access_denied=HMCL is unable to access the file "%s". It may be locked by another process.\n\ \n\ - For Windows users, you can open "Resource Monitor" to check if another process is currently using it. If so, you can try again after closing that process.\n\ - If not, please check if your account has enough permissions to access it. + For Windows users, you can open "Resource Monitor" to check if another process is currently using it. If so, you can try again after terminating that process.\n\ + If not, please check if your user account has adequate permissions to access it. exception.artifact_malformed=Cannot verify the integrity of the downloaded files. -exception.ssl_handshake=Failed to establish an SSL connection because the SSL certificate is missing from the current Java installation. You can try opening HMCL with another Java and try again. +exception.ssl_handshake=Failed to establish SSL connection because the SSL certificate is missing from the current Java installation. You can try opening HMCL with another Java installation and try again. extension.bat=Windows Batch File (.bat) extension.mod=Mod File @@ -365,7 +365,7 @@ fatal.javafx.incompatible=Missing JavaFX environment.\n\ fatal.javafx.incomplete=The JavaFX environment is incomplete.\n\ Please try replacing your Java or reinstalling OpenJFX. fatal.javafx.missing=Missing JavaFX environment. Please open Hello Minecraft! Launcher with Java, which includes OpenJFX. -fatal.config_change_owner_root=You are using the root account to open Hello Minecraft! Launcher. This may cause you to fail to open HMCL with another account in the future.\n\ +fatal.config_change_owner_root=You are using the root account to open Hello Minecraft! Launcher. This may prevent you from opening HMCL with another account in the future.\n\ Do you still want to continue? fatal.config_in_temp_dir=You are opening Hello Minecraft! Launcher in a temporary directory. Your settings and game data may be lost.\n\ It is recommended to move HMCL to another location and reopen it.\n\ @@ -375,7 +375,7 @@ fatal.config_loading_failure=Cannot load configuration files.\n\ For macOS, try putting HMCL somewhere with permissions other than "Desktop", "Downloads", and "Documents" and try again. fatal.config_loading_failure.unix=Hello Minecraft! Launcher could not load the configuration file because it was created by user "%1$s".\n\ Please open HMCL as root user (not recommended), or execute the following command in the terminal to change the ownership of the configuration file to the current user:\n%2$s -fatal.mac_app_translocation=Hello Minecraft! Launcher is isolated to a temporary directory by the OS because of macOS security mechanisms.\n\ +fatal.mac_app_translocation=Hello Minecraft! Launcher is isolated to a temporary directory by the OS due to macOS security mechanisms.\n\ Please move HMCL to a different directory before attempting to open. Otherwise, your settings and game data may be lost after restarting.\n\ Do you still want to continue? fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher has been upgraded. Please restart the launcher. @@ -388,13 +388,13 @@ fatal.apply_update_need_win7=Hello Minecraft! Launcher cannot automatically upda You can update manually by downloading a newer launcher version from %s. fatal.samba=If you opened Hello Minecraft! Launcher from a Samba network drive, some features might not be working. Please try updating your Java or moving the launcher to another directory. fatal.illegal_char=Your user path contains an illegal character "=". You will not be able to use authlib-injector or change the skin of your offline account. -fatal.unsupported_platform=Minecraft is not yet fully supported for your platform, so you may experience missing functionality or even be unable to launch the game.\n\ +fatal.unsupported_platform=Minecraft is not fully supported on your platform yet, so you may experience missing features or even be unable to launch the game.\n\ \n\ If you cannot launch Minecraft 1.17 and later, you can try switching the "Renderer" to "Software" in "Global/Instance-specific Settings → Advanced Settings" to use CPU rendering for better compatibility. fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher has provided support for the Loongson platform.\n\ If you encounter problems when playing a game, you can visit https://docs.hmcl.net/groups.html for help. -fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher has provided support for the Apple silicon platform, using native ARM Java to launch games to get a smoother game experience.\n\ - If you encounter problems when playing a game, launching the game with Java based on x86-64 architecture may have better compatibility. +fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher has provided support for the Apple silicon platform, using native ARM Java to launch games to get a smoother gaming experience.\n\ + If you encounter problems when playing a game, launching the game with Java based on x86-64 architecture may offer better compatibility. fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher has provided native support for the Windows on Arm platform. If you encounter problems when playing a game, please try launching the game with Java based on x86 architecture.\n\ \n\ If you are using the Qualcomm platform, you may need to install the OpenGL Compatibility Pack before playing games.\n\ @@ -421,7 +421,7 @@ folder.saves=Saves folder.screenshots=Screenshots game=Games -game.crash.feedback=Please do not share screenshots of this interface with others! If you ask for help from others, please click "Export Crash Logs" and send the exported file to others for analysis. +game.crash.feedback=Please do not share screenshots of this window with others! If you ask for help from others, please click "Export Crash Logs" and send the exported file to others for analysis. game.crash.info=Crash Info game.crash.reason=Crash Cause game.crash.reason.analyzing=Analyzing... @@ -476,14 +476,14 @@ game.crash.reason.need_jdk11=The game crashed because of an inappropriate Java V You need to download and install Java 11, and set it in "Global/Instance-specific Settings → Java". game.crash.reason.mod_name=The game crashed because of mod filename problems.\n\ \n\ - Mod file names should use only English letters (Aa~Zz), numbers (0~9), hyphens (-), underscores (_), and dots (.) in half-width.\n\ + Mod file names should use only English letters (A~Z, a~z), numbers (0~9), hyphens (-), underscores (_), and dots (.) in half-width.\n\ \n\ - Please navigate to the mod directory and add all non-compliant mod file names with one of the above compliant characters. + Please navigate to the mod directory and change all non-compliant mod file names using the compliant characters above. game.crash.reason.incomplete_forge_installation=The game cannot continue to run because of an incomplete Forge/NeoForge installation.\n\ \n\ Please reinstall Forge/NeoForge in "Edit Instance → Loaders". game.crash.reason.fabric_version_0_12=Fabric Loader 0.12 or later is incompatible with currently installed mods. You need to downgrade it to 0.11.7. -game.crash.reason.fabric_warnings=The Fabric warned:\n\ +game.crash.reason.fabric_warnings=The Fabric Loader warned:\n\ \n\ %1$s game.crash.reason.file_already_exists=The game crashed because the file "%1$s" already exists.\n\ @@ -499,9 +499,9 @@ game.crash.reason.graphics_driver=The game crashed because of a problem with you \n\ Please try again after updating your graphics driver to the latest version.\n\ \n\ - If your computer has a discrete graphics card, you need to check whether the game uses integrated/core graphics. If so, please open the launcher using your discrete graphics card. If the problem persists, you probably should consider using a new graphics card or a new computer.\n\ + If your computer has a dedicated graphics card, you need to check whether the game uses integrated/core graphics. If so, please open the launcher using your dedicated graphics card. If the problem persists, you probably should consider using a new graphics card or a new computer.\n\ \n\ - If you are using your integrated graphics card, please notice that Minecraft 1.16.5 or previous requires Java 1.8.0_51 or previous for Intel(R) Core(TM) 3000 processor series or previous. + If you are using your integrated graphics card, please notice that Minecraft 1.16.5 or earlier requires Java 1.8.0_51 or earlier for Intel(R) Core(TM) 3000 processor series or earlier. game.crash.reason.macos_failed_to_find_service_port_for_display=The game cannot continue because the OpenGL window on the Apple silicon platform failed to initialize.\n\ \n\ For this problem, HMCL does not have direct solutions at the moment. Please try opening any browser and going fullscreen, then return to HMCL, launch the game, and quickly return to the browser page before the game window pops up, wait for the game window to appear, and then switch back to the game window. @@ -520,8 +520,8 @@ game.crash.reason.mod_files_are_decompressed=The game crashed because the mod fi \n\ Please put the entire mod file directly into the mod directory!\n\ \n\ - If extract will cause errors in the game, please delete the extracted mod in the mod directory and then launch the game. -game.crash.reason.shaders_mod=The game crashed because of both OptiFine and Shaders mod installed at the same time.\n\ + If extraction causes errors in the game, please delete the extracted mod in the mod directory and then launch the game. +game.crash.reason.shaders_mod=The game crashed because of both OptiFine and Shaders mod are installed at the same time.\n\ \n\ Just remove the Shader mod because OptiFine has built-in support for shaders. game.crash.reason.rtss_forest_sodium=The game crashed because the RivaTuner Statistical Server (RTSS) is not compatible with Sodium.\n\ @@ -617,15 +617,15 @@ game.crash.reason.no_such_method_error=The game cannot continue to run because o You may need to reinstall the game and all mods or ask someone for help. game.crash.reason.opengl_not_supported=The game crashed because your graphics driver does not support OpenGL.\n\ \n\ - If you are streaming the game over the Internet or using a remote desktop environment, please play the game on your local one.\n\ + If you are streaming the game over the Internet or using a remote desktop environment, please play the game on your local machine.\n\ \n\ - Or, you can try updating your driver to the latest version and then try again.\n\ + Or, you can update your graphic driver to the latest version and then try again.\n\ \n\ - If your computer has a discrete graphics card, please make sure the game is actually using it for rendering. If the problem persists, please consider getting a new graphics card or a new computer. -game.crash.reason.openj9=The game is unable to run on an OpenJ9 VM. Please switch to a Java that uses the Hotspot VM in "Global/Instance-specific Settings → Java" and relaunch the game. If you do not have one, you can download one online. + If your computer has a dedicated graphics card, please make sure the game is indeed using it for rendering. If the problem persists, please consider getting a new graphics card or a new computer. +game.crash.reason.openj9=The game is unable to run on an OpenJ9 VM. Please switch to a Java that uses the Hotspot VM in "Global/Instance-specific Settings → Java" and relaunch the game. If you do not have one, you can download one. game.crash.reason.out_of_memory=The game crashed because the computer ran out of memory.\n\ \n\ - Maybe because there is not enough memory available or too many mods installed. You can try resolving it by increasing the allocated memory in "Global/Instance-specific Settings → Memory".\n\ + Maybe there is not enough memory available or too many mods installed. You can try resolving it by increasing the allocated memory in "Global/Instance-specific Settings → Memory".\n\ \n\ If you still encounter these problems, you may need a better computer. game.crash.reason.resolution_too_high=The game crashed because the resource pack resolution is too high.\n\ @@ -644,7 +644,7 @@ game.crash.reason.unsatisfied_link_error=Failed to launch Minecraft because of m \n\ If you have edited the native library path, please make sure these libraries do exist. Or, please try launching again after reverting it to default.\n\ \n\ - If you did not, please check if you have missing dependency mods.\n\ + If you have not, please check if you have missing dependency mods.\n\ \n\ Otherwise, if you believe this is caused by HMCL, please provide feedback to us. game.crash.title=Game Crashed @@ -677,7 +677,7 @@ install.installer.choose=Choose Your %s Version install.installer.depend=Requires %s install.installer.fabric=Fabric install.installer.fabric-api=Fabric API -install.installer.fabric-api.warning=Warning: Fabric API is a mod and will be installed into the mod directory of the game instance. Please do not change the working directory of the game, or the Fabric API will not work. If you do want to change these settings, you should reinstall it. +install.installer.fabric-api.warning=Warning: Fabric API is a mod and will be installed into the mod directory of the game instance. Please do not change the working directory of the game, or the Fabric API won't function. If you do want to change the directory, you should reinstall it. install.installer.forge=Forge install.installer.neoforge=NeoForge install.installer.game=Minecraft @@ -738,31 +738,31 @@ java.uninstall.confirm=Are you sure you want to uninstall this Java? This action lang=English lang.default=Use System Locales 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 cause you to be unable to launch the game or affect the game experience. \nDo 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 VM version is not compatible with the instance.\n\nClick "Yes" to automatically choose the most compatible Java VM 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 previous. -launch.advice.corrected=We have resolved the Java VM problem. If you still want to use your choice of Java version, you can disable the "Do not check Java VM 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 the "Do not check Java VM compatibility" in "Global/Instance-specific Settings → Advanced Settings". +launch.advice.java.modded_java_7=Minecraft 1.7.2 and previous versions require Java 7 or earlier. +launch.advice.corrected=We have resolved the Java VM problem. If you still want to use your choice of Java version, you can disable "Do not check Java VM 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 Java VM 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. launch.advice.forge2760_liteloader=Forge version 2760 is not compatible with LiteLoader. Please consider upgrading Forge to version 2773 or later. -launch.advice.forge28_2_2_optifine=Forge version 28.2.2 or later is not compatible with OptiFine. Please consider downgrading Forge to version 28.2.1 or previous. -launch.advice.forge37_0_60=Forge versions previous to 37.0.60 are not compatible with Java 17. Please update Forge to 37.0.60 or later, or launch the game with Java 16. +launch.advice.forge28_2_2_optifine=Forge version 28.2.2 or later is not compatible with OptiFine. Please consider downgrading Forge to version 28.2.1 or earlier. +launch.advice.forge37_0_60=Forge versions prior to 37.0.60 are not compatible with Java 17. Please update Forge to 37.0.60 or later, or launch the game with Java 16. launch.advice.java8_1_13=Minecraft 1.13 and later can only be run on Java 8 or later. Please use Java 8 or later versions. -launch.advice.java8_51_1_13=Minecraft 1.13 may crash on Java 8 versions previous to 1.8.0_51. Please install the latest Java 8 version. -launch.advice.java9=You cannot launch Minecraft 1.12 or previous with Java 9 or later. Please use Java 8 instead. +launch.advice.java8_51_1_13=Minecraft 1.13 may crash on Java 8 versions prior to 1.8.0_51. Please install the latest Java 8 version. +launch.advice.java9=You cannot launch Minecraft 1.12 or earlier with Java 9 or later. Please use Java 8 instead. launch.advice.modded_java=Some mods may not be compatible with newer Java versions. It is recommended to use Java %s to launch Minecraft %s. launch.advice.modlauncher8=The Forge version you are using is not compatible with the current Java version. Please try updating Forge. -launch.advice.newer_java=You are using the old Java to launch the game. It is recommended to update to Java 8, otherwise some mods may cause the game to crash. +launch.advice.newer_java=You are using an older Java version to launch the game. It is recommended to update to Java 8, otherwise some mods may cause the game to crash. launch.advice.not_enough_space=You have allocated a memory size larger than the actual %d MB of memory installed on your computer. You may experience degraded performance or even be unable to launch the game. launch.advice.require_newer_java_version=The current game version requires Java %s, but we could not find one. Do you want to download one now? launch.advice.too_large_memory_for_32bit=You have allocated a memory size larger than the memory limitation of the 32-bit Java installation. You may be unable to launch the game. -launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 or previous only supports Java 8 for the Linux x86-64 platform because the later versions cannot load 32-bit native libraries like liblwjgl.so\n\nPlease download it from java.com or install OpenJDK 8. -launch.advice.vanilla_x86.translation=Minecraft is not fully supported for your platform, so you may experience missing functionality or even be unable to launch the game.\nYou can download Java for the x86-64 architecture here for a full gaming experience. -launch.advice.unknown=The game cannot be launched for the following reasons: +launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 or earlier only supports Java 8 for the Linux x86-64 platform because the later versions cannot load 32-bit native libraries like liblwjgl.so\n\nPlease download it from java.com or install OpenJDK 8. +launch.advice.vanilla_x86.translation=Minecraft is not fully supported on your platform, so you may experience missing features or even be unable to launch the game.\nYou can download Java for the x86-64 architecture here for a full gaming experience. +launch.advice.unknown=The game cannot be launched due to the following reasons: launch.failed=Failed to launch launch.failed.cannot_create_jvm=We are unable to create a Java VM. It may be caused by incorrect Java VM arguments. You can try resolving it by removing all arguments you added in "Global/Instance-specific Settings → Advanced Settings → Java VM Options". launch.failed.creating_process=We are unable to create a new process. Please check your Java path.\n -launch.failed.command_too_long=The command length exceeds the maximum length of a bat script. Please try exporting it as a PowerShell script. +launch.failed.command_too_long=The command length exceeds the maximum length of a batch script. Please try exporting it as a PowerShell script. launch.failed.decompressing_natives=Failed to extract native libraries.\n launch.failed.download_library=Failed to download libraries "%s". launch.failed.executable_permission=Failed to make the launch script executable. @@ -866,7 +866,7 @@ modpack.install=Install Modpack %s modpack.installing=Installing Modpack modpack.introduction=Curse, Modrinth, MultiMC, and MCBBS modpacks are currently supported. modpack.invalid=Invalid modpack, you can try downloading it again. -modpack.mismatched_type=Modpack type mismatched, the current instance is a(an) %s type, but the provided one is %s type. +modpack.mismatched_type=Modpack type mismatched, the current instance is a(n) %s type, but the provided one is %s type. modpack.name=Modpack Name modpack.not_a_valid_name=Invalid modpack name. modpack.origin=Source @@ -903,8 +903,8 @@ modpack.wizard.step.initialization.include_launcher=Include the launcher modpack.wizard.step.initialization.save=Export to... modpack.wizard.step.initialization.warning=Before making a modpack, please make sure the game launches normally and Minecraft is a release version instead of a snapshot. The launcher will save your download settings.\n\ \n\ - Keep in mind that you are not allowed to add mods and resource packs that are explicitly said not to be distributed or put in a modpack. -modpack.wizard.step.initialization.server=Click here for more tutorials for making a server modpack that can be automatically updated. + Keep in mind that you are not allowed to add mods and resource packs that explicitly state they could not to be distributed or put in a modpack. +modpack.wizard.step.initialization.server=Click here for more information on how to make a server modpack that can be automatically updated. modrinth.category.adventure=Adventure modrinth.category.audio=Audio @@ -980,7 +980,7 @@ mods.add=Add Mod mods.add.failed=Failed to add mod %s. mods.add.success=%s was successfully added. mods.broken_dependency.title=Broken dependency -mods.broken_dependency.desc=This dependency existed before, but it does not exist now. Try using another download source. +mods.broken_dependency.desc=This dependency existed before, but it does not exist anymore. Try using another download source. mods.category=Category mods.channel.alpha=Alpha mods.channel.beta=Beta @@ -998,11 +998,11 @@ mods.choose_mod=Choose mod mods.curseforge=CurseForge mods.dependency.embedded=Built-in Pre-mod (Already packaged in the mod file by the author. No need to download separately) mods.dependency.optional=Optional Pre-mod (If missing, the game will run normally, but the mod features may be missing) -mods.dependency.required=Required Pre-mod (Must be downloaded separately. Missing may cause the game to fail to launch) -mods.dependency.tool=Required Library (Must be downloaded separately. Missing may cause the game to fail to launch) +mods.dependency.required=Required Pre-mod (Must be downloaded separately. Missing may prevent the game from launching) +mods.dependency.tool=Required Library (Must be downloaded separately. Missing may prevent the game from launching) mods.dependency.include=Built-in Pre-mod (Already packaged in the mod file by the author, no need to download separately) -mods.dependency.incompatible=Incompatible Mod (Installing these mods at the same time will cause the game to fail to launch) -mods.dependency.broken=Broken Pre-mod (This mod existed before, but it does not exist now. Try using another download source.) +mods.dependency.incompatible=Incompatible Mod (Installing these mods at the same time will prevent the game from launching) +mods.dependency.broken=Broken Pre-mod (This mod existed before, but it does not exist anymore. Try using another download source.) mods.disable=Disable mods.download=Mod Download mods.download.title=Mod Download - %1s @@ -1171,7 +1171,7 @@ settings.advanced.natives_directory=Native Library Path settings.advanced.natives_directory.choose=Choose the location of the desired native library settings.advanced.natives_directory.custom=Custom settings.advanced.natives_directory.default=Default -settings.advanced.natives_directory.hint=This option is intended only for users of Apple M1 or other not officially supported platforms. Please do not edit this option unless you know what you are doing.\n\ +settings.advanced.natives_directory.hint=This option is intended only for users of Apple silicon or other not officially supported platforms. Please do not edit this option unless you know what you are doing.\n\ \n\ Before proceeding, please make sure all libraries (e.g. lwjgl.dll, libopenal.so) are provided in your desired directory.\n\ Note: It is recommended to use a fully English-letters path for the specified local library file. Otherwise it may lead to game launch failure. @@ -1293,12 +1293,12 @@ update=Update update.accept=Update update.changelog=Changelog update.channel.dev=Beta -update.channel.dev.hint=You are currently using a Beta channel build of the launcher, which may include some extra features but is also sometimes more unstable than the Release channel.\n\ +update.channel.dev.hint=You are currently using a Beta channel build of the launcher. While it may include some extra features, it is also sometimes less stable than the Release channel builds.\n\ \n\ If you encounter any bugs or problems, please navigate to Settings → Feedback page to submit your feedback. update.channel.dev.title=Beta Channel Notice update.channel.nightly=Nightly -update.channel.nightly.hint=You are currently using a Nightly channel build of the launcher, which may include some extra features but is also always more unstable than the other channels.\n\ +update.channel.nightly.hint=You are currently using a Nightly channel build of the launcher. While it may include some extra features, it is also always less stable than the other channel builds.\n\ \n\ If you encounter any bugs or problems, please navigate to Settings → Feedback page to submit your feedback. update.channel.nightly.title=Nightly Channel Notice @@ -1351,7 +1351,7 @@ version.manage.remove_assets=Delete All Assets version.manage.remove_libraries=Delete All Libraries version.manage.rename=Rename Instance version.manage.rename.message=Enter New Instance Name -version.manage.rename.fail=Failed to rename the instance, some files might be in use, or the name contains an invalid character. +version.manage.rename.fail=Failed to rename the instance. Some files might be in use, or the name contains an invalid character. version.settings=Settings version.update=Update Modpack From 95e39fe87afe3f884fac3126f653b0699e548bf0 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Mon, 6 Jan 2025 03:12:13 +0800 Subject: [PATCH 157/169] gha: revise release description [skip ci] (#3474) unify text style --- .github/workflows/check-update.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-update.yml b/.github/workflows/check-update.yml index f112915e7d..9bf77cf74f 100644 --- a/.github/workflows/check-update.yml +++ b/.github/workflows/check-update.yml @@ -50,7 +50,8 @@ jobs: if: ${{ env.continue == 'true' }} run: | echo "The full changelogs can be found on the website: https://docs.hmcl.net/changelog/dev.html" >> RELEASE_NOTE - echo "Notice: changelogs are written in Chinese." >> RELEASE_NOTE + echo "" >> RELEASE_NOTE + echo "*Notice: changelogs are written in Chinese.*" >> RELEASE_NOTE echo "" >> RELEASE_NOTE echo "| File Name | SHA-256 Checksum |" >> RELEASE_NOTE echo "| --- | --- |" >> RELEASE_NOTE @@ -117,7 +118,7 @@ jobs: echo "" >> RELEASE_NOTE echo "The full changelogs can be found on the website: https://docs.hmcl.net/changelog/stable.html" >> RELEASE_NOTE echo "" >> RELEASE_NOTE - echo "Notice: changelogs are written in Chinese." >> RELEASE_NOTE + echo "*Notice: changelogs are written in Chinese.*" >> RELEASE_NOTE echo "" >> RELEASE_NOTE echo "| File Name | SHA-256 Checksum |" >> RELEASE_NOTE echo "| --- | --- |" >> RELEASE_NOTE From d2df515325ac19fb234ae50140aed764c9b7e1f5 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Mon, 6 Jan 2025 03:32:42 +0800 Subject: [PATCH 158/169] Revise README [skip ci] (#3447) * Revise README [skip ci] * Apply suggestions from yushijinhun Co-authored-by: yushijinhun --------- Co-authored-by: yushijinhun --- README.md | 4 ++-- README_cn.md | 4 ++-- README_tw.md | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 18365ec2eb..b8eff4bad5 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ HMCL is an open-source, cross-platform Minecraft launcher that supports Mod Mana HMCL has amazing cross-platform capabilities. Not only does it run on different operating systems like Windows, Linux, and macOS, but it also supports various CPU architectures such as x86, ARM, MIPS, and LoongArch. You can easily enjoy Minecraft across different platforms through HMCL. -For systems and CPU architectures supported by HMCL, see [this table](PLATFORM.md). +For systems and CPU architectures supported by HMCL, please refer to [this table](PLATFORM.md). ## Download -Download the latest version from [the official website](https://hmcl.huangyuhui.net/download). +Download the latest version from the [official website](https://hmcl.huangyuhui.net/download). You can also find the latest version of HMCL in [GitHub Releases](https://github.com/HMCL-dev/HMCL/releases). diff --git a/README_cn.md b/README_cn.md index 2d8d7d0d40..2bd1a02711 100644 --- a/README_cn.md +++ b/README_cn.md @@ -12,7 +12,7 @@ HMCL 是一款开源、跨平台的 Minecraft 启动器,支持模组管理、游戏自定义、游戏自动安装 (Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine)、整合包创建、界面自定义等功能。 -HMCL 有着强大的跨平台能力。它不仅支持 Windows、Linux、macOS 等常见的操作系统,同时也支持 x86、ARM、MIPS 和 LoongArch 等不同的 CPU 架构。你可以使用 HMCL 在不同平台上轻松地游玩 Minecraft。 +HMCL 有着强大的跨平台能力。它不仅支持 Windows、Linux、macOS 等常见的操作系统,同时也支持 x86、ARM、MIPS、LoongArch 等不同的 CPU 架构。你可以使用 HMCL 在不同平台上轻松地游玩 Minecraft。 如果你想要了解 HMCL 对不同平台的支持程度,请参见 [此表格](PLATFORM_cn.md)。 @@ -59,7 +59,7 @@ HMCL 有着强大的跨平台能力。它不仅支持 Windows、Linux、macOS | 参数 | 简介 | | -------------------------------------------- | -------------------------------------------------------------------- | | `-Dhmcl.home=` | 覆盖 HMCL 数据文件夹 | -| `-Dhmcl.self_integrity_check.disable=true` | 检查更新时绕过本体完整性检查 | +| `-Dhmcl.self_integrity_check.disable=true` | 检查更新时不检查本体完整性 | | `-Dhmcl.bmclapi.override=` | 覆盖 BMCLAPI 的 API Root,默认值为 `https://bmclapi2.bangbang93.com` | | `-Dhmcl.font.override=` | 覆盖字族 | | `-Dhmcl.version.override=` | 覆盖版本号 | diff --git a/README_tw.md b/README_tw.md index 4fcebadbfb..79c31a3f35 100644 --- a/README_tw.md +++ b/README_tw.md @@ -10,9 +10,9 @@ ## 簡介 -HMCL 是一款開源、跨平臺的 Minecraft 啟動器,支援模組管理、遊戲自訂、遊戲自動安裝 (Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine)、模組包建立、介面自訂等功能。 +HMCL 是一款開源、跨平臺的 Minecraft 啟動器,支援模組管理、遊戲客製化、遊戲自動安裝 (Forge、NeoForge、Fabric、Quilt、LiteLoader 和 OptiFine)、模組包建立、介面客製化等功能。 -HMCL 有著強大的跨平臺能力。它不僅支援 Windows、Linux、macOS 等常見的作業系統,同時也支援 x86、ARM、MIPS 和 LoongArch 等不同的 CPU 架構。你可以使用 HMCL 在不同平臺上輕鬆地遊玩 Minecraft。 +HMCL 有著強大的跨平臺能力。它不僅支援 Windows、Linux、macOS 等常見的作業系統,同時也支援 x86、ARM、MIPS、LoongArch 等不同的 CPU 架構。你可以使用 HMCL 在不同平臺上輕鬆地遊玩 Minecraft。 如果你想要了解 HMCL 對不同平臺的支援程度,請參見 [此表格](PLATFORM_tw.md)。 @@ -59,7 +59,7 @@ HMCL 有著強大的跨平臺能力。它不僅支援 Windows、Linux、macOS | 參數 | 簡介 | | -------------------------------------------- | -------------------------------------------------------------------- | | `-Dhmcl.home=` | 覆蓋 HMCL 使用者目錄 | -| `-Dhmcl.self_integrity_check.disable=true` | 檢查更新時繞過本體完整性檢查 | +| `-Dhmcl.self_integrity_check.disable=true` | 檢查更新時不檢查本體完整性 | | `-Dhmcl.bmclapi.override=` | 覆蓋 BMCLAPI 的 API Root,預設值為 `https://bmclapi2.bangbang93.com` | | `-Dhmcl.font.override=` | 覆蓋字族 | | `-Dhmcl.version.override=` | 覆蓋版本號 | From f2edc8001c96bda2657b2dbb04580c4c25389b74 Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Mon, 6 Jan 2025 03:37:19 +0800 Subject: [PATCH 159/169] Revise Spanish & English (#3465) * Revise Spanish & English Overhaul for Spanish. I cannot guarantee it is 100% correct, but I promise to proofread it. During the overhaul some more mistakes in the English language were discovered, so let's fix it. All translations have been revised except for the `game.crash.reason` series. * Apply suggestions from yushijinhun Co-authored-by: yushijinhun --------- Co-authored-by: yushijinhun --- .../resources/assets/lang/I18N.properties | 35 +- .../resources/assets/lang/I18N_es.properties | 686 +++++++++++------- 2 files changed, 450 insertions(+), 271 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 681bd471de..37cbc4e40a 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -73,7 +73,7 @@ account.failed.server_disconnected=Failed to connect to the authentication serve account.failed.server_response_malformed=Invalid server response. The authentication server may be down. account.failed.ssl=An SSL error occurred while connecting to the server. Please try updating your Java. account.failed.wrong_account=You have logged in to the wrong account. -account.hmcl.hint=You need to click "Login" and complete the process in the opened browser window. +account.hmcl.hint=You need to click "Log in" and complete the process in the opened browser window. account.injector.add=New Auth Server account.injector.empty=None (You can click "+" to add one) account.injector.http=Warning: This server uses the unsafe HTTP protocol. Anyone intercepting your connection would be able to see your credentials in plaintext. @@ -95,16 +95,16 @@ account.copy_uuid=Copy UUID of the Account account.methods=Login Type account.methods.authlib_injector=authlib-injector account.methods.microsoft=Microsoft -account.methods.microsoft.birth=How to Change Your Account Birthday +account.methods.microsoft.birth=How to Change Your Account Birth Date account.methods.microsoft.close_page=Microsoft account authorization is now completed.\n\ \n\ There are some extra works for us, but you can safely close this tab for now. account.methods.microsoft.deauthorize=Deauthorize account.methods.microsoft.error.add_family=An adult must add you to a family in order for you to play Minecraft because you are not yet 18 years old. -account.methods.microsoft.error.add_family_probably=Please check if the age indicated in your account settings is at least 18 years old. If not and you believe this is an error, you can click "How to Change Your Account Birthday" to learn how to change it. +account.methods.microsoft.error.add_family_probably=Please check if the age indicated in your account settings is at least 18 years old. If not and you believe this is an error, you can click "How to Change Your Account Birth Date" to learn how to change it. account.methods.microsoft.error.country_unavailable=Xbox Live is not available in your current country/region. account.methods.microsoft.error.missing_xbox_account=Your Microsoft account does not have a linked Xbox account yet. Please click "Create Profile / Edit Profile Name" to create one before continuing. -account.methods.microsoft.error.no_character=Your account does not own the Minecraft Java Edition.\nThe game profile may not have been created\nplease click "Create Profile / Edit Profile Name" to create it. +account.methods.microsoft.error.no_character=Please ensure you have purchased Minecraft: Java Edition.\nIf you have already purchased the game, a profile may not have been created yet.\nClick "Create Profile / Edit Profile Name" to create it. account.methods.microsoft.error.unknown=Failed to log in, error code: %d. account.methods.microsoft.error.wrong_verify_method=Please log in using your password on the Microsoft account login page, and do not use a verification code to log in. account.methods.microsoft.logging_in=Logging in... @@ -696,7 +696,7 @@ install.installer.quilt-api=QSL/QFAPI install.installer.version=%s install.installer.external_version=%s (Installed by external process, which cannot be configured) install.modpack=Install Modpack -install.name.invalid=The name contains non-ASCII characters (such as emoji or CJK characters).\nIt is recommended to modify the name to include only English letters, numbers and underscores to avoid potential issues when launching the game. \nDo you want to proceed with the installation? +install.name.invalid=The name contains non-ASCII characters (such as emoji or CJK characters).\nIt is recommended to change the name to include only English letters, numbers, and underscores to avoid potential issues when launching the game.\nDo you want to proceed with the installation? install.new_game=Install Instance install.new_game.already_exists=This instance name already exists. Please use another name. install.new_game.current_game_version=Current Instance Version @@ -737,8 +737,9 @@ java.uninstall.confirm=Are you sure you want to uninstall this Java? This action lang=English lang.default=Use System Locales + 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.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 VM version is not compatible with the instance.\n\nClick "Yes" to automatically choose the most compatible Java VM 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.corrected=We have resolved the Java VM problem. If you still want to use your choice of Java version, you can disable "Do not check Java VM compatibility" in "Global/Instance-specific Settings → Advanced Settings". @@ -886,7 +887,7 @@ modpack.type.modrinth=Modrinth modpack.type.multimc=MultiMC modpack.type.multimc.export=Can be imported by Hello Minecraft! Launcher and MultiMC modpack.type.server=Auto-Update Modpack from Server -modpack.type.server.export=Allows server owner to update the game instance remotely +modpack.type.server.export=Allows server owner to remotely update the game instance modpack.type.server.malformed=Invalid modpack manifest. Please contact the modpack maker to resolve this problem. modpack.unsupported=Unsupported modpack format modpack.update=Updating modpack @@ -901,7 +902,7 @@ modpack.wizard.step.initialization.exported_version=Game version to export modpack.wizard.step.initialization.force_update=Force updating the modpack to the latest version (you will need a file-hosting server) modpack.wizard.step.initialization.include_launcher=Include the launcher modpack.wizard.step.initialization.save=Export to... -modpack.wizard.step.initialization.warning=Before making a modpack, please make sure the game launches normally and Minecraft is a release version instead of a snapshot. The launcher will save your download settings.\n\ +modpack.wizard.step.initialization.warning=Before making a modpack, please make sure the game can be launched normally and Minecraft is a release version instead of a snapshot. The launcher will save your download settings.\n\ \n\ Keep in mind that you are not allowed to add mods and resource packs that explicitly state they could not to be distributed or put in a modpack. modpack.wizard.step.initialization.server=Click here for more information on how to make a server modpack that can be automatically updated. @@ -996,16 +997,16 @@ mods.check_updates.target_version=Target Version mods.check_updates.update=Update mods.choose_mod=Choose mod mods.curseforge=CurseForge -mods.dependency.embedded=Built-in Pre-mod (Already packaged in the mod file by the author. No need to download separately) -mods.dependency.optional=Optional Pre-mod (If missing, the game will run normally, but the mod features may be missing) -mods.dependency.required=Required Pre-mod (Must be downloaded separately. Missing may prevent the game from launching) -mods.dependency.tool=Required Library (Must be downloaded separately. Missing may prevent the game from launching) -mods.dependency.include=Built-in Pre-mod (Already packaged in the mod file by the author, no need to download separately) -mods.dependency.incompatible=Incompatible Mod (Installing these mods at the same time will prevent the game from launching) -mods.dependency.broken=Broken Pre-mod (This mod existed before, but it does not exist anymore. Try using another download source.) +mods.dependency.embedded=Built-in Dependencies (Already packaged in the mod file by the author. No need to download separately) +mods.dependency.optional=Optional Dependencies (If missing, the game will run normally, but the mod features may be missing) +mods.dependency.required=Required Dependencies (Must be downloaded separately. Missing may prevent the game from launching) +mods.dependency.tool=Required Dependencies (Must be downloaded separately. Missing may prevent the game from launching) +mods.dependency.include=Built-in Dependencies (Already packaged in the mod file by the author. No need to download separately) +mods.dependency.incompatible=Incompatible Mods (Installing these mods at the same time will prevent the game from launching) +mods.dependency.broken=Broken Dependencies (This mod existed before, but it does not exist anymore. Try using another download source.) mods.disable=Disable -mods.download=Mod Download -mods.download.title=Mod Download - %1s +mods.download=Download Mod +mods.download.title=Download Mod - %1s mods.download.recommend=Recommended Mod Version - Minecraft %1s mods.enable=Enable mods.manage=Mods diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 20122a125d..6dd5db0cf0 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -29,7 +29,7 @@ about.claim.statement=Haga clic en este enlace para ver el texto completo. about.dependency=Bibliotecas de terceros about.legal=Reconocimiento legal about.thanks_to=Gracias a -about.thanks_to.bangbang93.statement=Por proporcionar el espejo de descarga de BMCLAPI, por favor considere hacer una donación! +about.thanks_to.bangbang93.statement=Por proporcionar el espejo de descarga de BMCLAPI, ¡por favor, considere hacer una donación! about.thanks_to.burningtnt.statement=Aportar mucho apoyo técnico a HMCL. about.thanks_to.contributors=Todos los colaboradores en GitHub about.thanks_to.contributors.statement=Sin la impresionante comunidad de código abierto, HMCL no habría llegado tan lejos. @@ -51,93 +51,111 @@ about.open_source.statement=GPL v3 (https://github.com/HMCL-dev/HMCL) account=Cuentas account.cape=Capa -account.character=personaje -account.choose=Elige un personaje -account.create=Añadir una cuenta +account.character=Jugador +account.choose=Elige un jugador +account.create=Añadir cuenta account.create.microsoft=Añadir una cuenta Microsoft -account.create.offline=Añadir una cuenta offline -account.create.authlibInjector=Crear una cuenta authlib-injector +account.create.offline=Añadir una cuenta sin conexión +account.create.authlibInjector=Añadir una cuenta authlib-injector account.email=Correo electrónico -account.failed=error de inicio de sesion -account.failed.character_deleted=El personaje ya ha sido eliminado. -account.failed.connect_authentication_server=No se ha podido conectar con los servidores de autenticación, es posible que la conexión a Internet esté caída. -account.failed.connect_injector_server=No se ha podido conectar con el servidor de autenticación. Por favor, compruebe su red y asegúrese de que ha introducido la URL correcta. +account.failed=Error al actualizar la cuenta. +account.failed.character_deleted=El jugador ya ha sido eliminado. +account.failed.connect_authentication_server=No se ha podido conectar con el servidor de autenticación. Es posible que su conexión de red no funcione. +account.failed.connect_injector_server=No se ha podido conectar con el servidor de autenticación. Por favor, comprueba su red y asegúrate de que has introducido la URL correcta. account.failed.injector_download_failure=No se ha podido descargar authlib-injector. Por favor, compruebe su red, o intente cambiar a un espejo de descarga diferente. -account.failed.invalid_credentials=Contraseña incorrecta o tasa limitada, por favor inténtelo más tarde. -account.failed.invalid_password=Contraseña no válida +account.failed.invalid_credentials=Contraseña incorrecta o tasa limitada, por favor, inténtelo más tarde. +account.failed.invalid_password=Contraseña no válida. account.failed.invalid_token=Por favor, intente iniciar sesión de nuevo. account.failed.migration=Su cuenta necesita ser migrada a una cuenta Microsoft. Si ya lo has hecho, debes volver a iniciar sesión con tu cuenta de Microsoft migrada. account.failed.no_character=No hay personajes vinculados a esta cuenta. +account.failed.server_disconnected=No se ha podido conectar con el servidor de autenticación. Puedes conectarte utilizando el modo sin conexión o intentar conectarte de nuevo.\n\ + Si lo intentas varias veces y sigue fallando, vuelve a intentar iniciar sesión en la cuenta. account.failed.server_response_malformed=Respuesta del servidor no válida, el servidor de autenticación puede no estar funcionando. +account.failed.ssl=Se ha producido un error SSL al conectar con el servidor. Por favor, intente actualizar su Java. account.failed.wrong_account=Ha iniciado sesión en la cuenta equivocada. -account.hmcl.hint=Debe hacer clic en "Acceder" y completar el proceso en la pestaña abierta en su navegador. -account.injector.add=Añadir un servidor de autenticación +account.hmcl.hint=Debe hacer clic en "Iniciar sesión" y completar el proceso en la ventana abierta del navegador. +account.injector.add=Nuevo servidor Auth account.injector.empty=Ninguno (Puedes hacer clic en el botón más de la derecha para añadir uno) -account.injector.http=Atención: Este servidor utiliza el protocolo HTTP inseguro, cualquiera entre su conexión podrá ver sus credenciales en texto claro. -account.injector.link.register=Registro +account.injector.http=Atención: Este servidor utiliza el protocolo HTTP inseguro. Cualquiera entre su conexión podrá ver sus credenciales en texto claro. +account.injector.link.homepage=Página de inicio +account.injector.link.register=Registrarse account.injector.server=Servidor de autenticación account.injector.server_url=URL del servidor account.injector.server_name=Nombre del servidor -account.login=Acceder +account.login=Iniciar sesión account.login.hint=No almacenaremos su contraseña. -account.login.refresh=Reiniciar sesión -account.login.refresh.microsoft.hint=Because the account authorization is invalid, you need to re-add your Microsoft account +account.login.skip=Iniciar sesión sin conexión +account.login.retry=Reintentar +account.login.refresh=Iniciar sesión de nuevo +account.login.refresh.microsoft.hint=Debe volver a iniciar sesión en su cuenta Microsoft porque la autorización de la cuenta no es válida. account.logout=Salir account.register=Registrarse account.manage=Lista de cuentas +account.copy_uuid=Copiar UUID de la cuenta account.methods=Tipo de inicio de sesión account.methods.authlib_injector=authlib-injector -account.methods.microsoft=Cuenta Microsoft -account.methods.microsoft.birth=Cómo actualizar la fecha de nacimiento de tu cuenta +account.methods.microsoft=Microsoft +account.methods.microsoft.birth=Cómo cambiar la fecha de nacimiento de su cuenta account.methods.microsoft.close_page=La autorización de la cuenta de Microsoft ha finalizado.\n\ -\n\ -Hay algunos trabajos extra para nosotros, pero puedes cerrar esta pestaña con seguridad por ahora. -account.methods.microsoft.makegameidsettings=Create Profile / Editar el nombre de perfil + \n\ + Hay algunos trabajos extra para nosotros, pero puedes cerrar esta pestaña con seguridad por ahora. +account.methods.microsoft.makegameidsettings=Crear perfil / Editar nombre del perfil account.methods.microsoft.deauthorize=Desautorizar -account.methods.microsoft.error.add_family=Como todavía no tienes 18 años, un adulto debe añadirte a una familia para que puedas jugar a Minecraft. -account.methods.microsoft.error.add_family_probably=Por favor, comprueba si la edad indicada en la configuración de tu cuenta es de al menos 18 años. Si no es así y crees que se trata de un error, puedes hacer clic en el enlace anterior para cambiarlo. +account.methods.microsoft.error.add_family=Un adulto debe añadirte a una familia para que puedas jugar a Minecraft porque aún no tienes 18 años. +account.methods.microsoft.error.add_family_probably=Por favor, compruebe si la edad indicada en la configuración de su cuenta es de al menos 18 años. Si no es así y cree que se trata de un error, puede hacer clic en "Cómo cambiar la fecha de nacimiento de su cuenta" para saber cómo cambiarla. account.methods.microsoft.error.country_unavailable=Xbox Live no está disponible en tu país/región actual. -account.methods.microsoft.error.missing_xbox_account=Tu cuenta Microsoft aún no tiene una cuenta Xbox vinculada. Crea una antes de continuar. -account.methods.microsoft.error.no_character=Tu cuenta no posee la edición Java de Minecraft.\nThe game profile may not have been created,\nplease click the link above to create it. +account.methods.microsoft.error.missing_xbox_account=Tu cuenta Microsoft aún no tiene una cuenta Xbox vinculada. Haga clic en "Crear perfil / Editar nombre de perfil" para crear una antes de continuar. +account.methods.microsoft.error.no_character=Por favor, asegúrese de que ha comprado Minecraft: Java Edition. \nSi ya lo has comprado, es posible que no hayas creado un perfil de juego.\nPor favor, haga clic en "Crear perfil / Editar nombre de perfil" para crearlo. account.methods.microsoft.error.unknown=No se ha podido iniciar sesión, error: %d. -account.methods.microsoft.logging_in=Inicio de sesión... -account.methods.microsoft.hint=Por favor, haz clic en el botón "Acceder", y copia el código que se muestra aquí para terminar el proceso de acceso en la ventana abierta del navegador.\n\ -\n\ -Si el token utilizado para acceder a la cuenta de Microsoft se ha filtrado, puedes hacer clic en "Desautorizar la cuenta" para desautorizarla.\n\ -Si encuentra algún problema, puede hacer clic en el botón de ayuda en la esquina superior derecha para obtener ayuda. -account.methods.microsoft.manual=El código de su dispositivo es %1$s, por favor, haga clic aquí para copiar. Después de hacer clic en el botón "Iniciar sesión", debería terminar el proceso de inicio de sesión en la ventana abierta del navegador. Si no aparece, puede ir a %2$s manualmente.n\ -\n\ -Si el token utilizado para acceder a la cuenta de Microsoft se ha filtrado, puedes hacer clic en "Desautorizar la cuenta" para desautorizarla.\n\ -Si encuentra algún problema, puede hacer clic en el botón de ayuda en la esquina superior derecha para obtener ayuda. +account.methods.microsoft.error.wrong_verify_method=Inicie sesión con su contraseña en la página de inicio de sesión de la cuenta Microsoft y no utilice un código de verificación para iniciar sesión. +account.methods.microsoft.logging_in=Iniciando sesión... +account.methods.microsoft.hint=Por favor, haga clic en "Iniciar sesión" y copie el código que aparece aquí para completar el proceso de inicio de sesión en la ventana del navegador que se abre.\n\ + \n\ + Si el token utilizado para iniciar sesión en la cuenta de Microsoft se ha filtrado, puedes hacer clic en "Desautorizar" para desautorizarlo. +account.methods.microsoft.manual=El código de su dispositivo es %1$s. Por favor, haga clic aquí para copiarlo.\n\ + \n\ + Después de hacer clic en "Iniciar sesión", debe completar el proceso de inicio de sesión en la ventana abierta del navegador. Si no se muestra, puede navegar a %2$s manualmente.\n\ + \n\ + Si el token utilizado para iniciar sesión en la cuenta de Microsoft se ha filtrado, puedes hacer clic en "Desautorizar" para desautorizarlo. account.methods.microsoft.profile=Perfil de la cuenta account.methods.microsoft.purchase=Comprar Minecraft -account.methods.microsoft.snapshot=Estás usando una construcción no oficial de hmcls, por favor descargue la construcción oficial para iniciar sesión en microsoft. +account.methods.microsoft.snapshot=Está utilizando una versión no oficial de HMCL. Por favor, descargue la versión oficial para iniciar sesión. +account.methods.microsoft.snapshot.website=Sitio web oficial account.methods.offline=Sin conexión +account.methods.offline.name.special_characters=Se recomienda utilizar letras en inglés, números y guiones bajos +account.methods.offline.name.invalid=Por lo general, los nombres de usuario de los juegos sólo admiten letras en inglés, números y guiones bajos, y no pueden superar los 16 caracteres de longitud.\n\ + \n\ + \ · Algunos nombres de usuario legítimos: HuangYu, huang_Yu, Huang_Yu_123;\n\ + \ · Algunos nombres de usuario ilegales: Huang Yu, Huang-Yu_%%%, Huang_Yu_hello_world_hello_world.\n\ + \n\ + Si crees que existe un mod o plugin correspondiente en el lado del servidor para eliminar esta restricción, puedes ignorar esta advertencia. account.methods.offline.uuid=UUID -account.methods.offline.uuid.hint=UUID es el identificador único del personaje del juego en Minecraft. La forma en que se genera puede variar entre diferentes launcheres. Cambiarlo por el generado por otros launchers te permite mantener tus objetos en el inventario de tu cuenta offline.\n\ -\n\ -Esta opción es sólo para usuarios avanzados. No recomendamos modificar esta opción a menos que sepas lo que estás haciendo.\n\ -Esta opción no es necesaria para unirse a servidores. -account.methods.offline.uuid.malformed=Formato no válido -account.methods.forgot_password=OLVIDÉ MI CONTRASEÑA +account.methods.offline.uuid.hint=UUID es un identificador único para los jugadores de Minecraft, y cada launcher puede generar UUID de manera diferente. Editarlo al generado por otros launchers te permite mantener tus objetos en el inventario de tu cuenta sin conexión.\n\ + \n\ + Esta opción es sólo para usuarios avanzados. No recomendamos editar esta opción a menos que sepas lo que estás haciendo. +account.methods.offline.uuid.malformed=Formato no válido. +account.methods.forgot_password=Olvidé mi contraseña account.missing=No hay cuentas -account.missing.add=Haz clic aquí para añadir una. +account.missing.add=Haga clic aquí para añadir una. +account.move_to_global=Convertir en cuenta global\nLa información de la cuenta se guardará en un archivo de configuración del directorio de usuario actual del sistema. +account.move_to_portable=Convertir en cuenta portátil\nLa información de la cuenta se guardará en un archivo de configuración en el mismo directorio que HMCL. account.not_logged_in=No ha iniciado sesión account.password=Contraseña -account.skin=Skin -account.skin.file=Archivo de skin +account.portable=Cuenta portátil +account.skin=Aspecto +account.skin.file=Archivo de aspecto account.skin.model=Modelo account.skin.model.default=Clásico -account.skin.model.slim=Delgado +account.skin.model.slim=Slim account.skin.type.csl_api=Blessing skin account.skin.type.csl_api.location=URL account.skin.type.csl_api.location.hint=CustomSkinAPI URL account.skin.type.little_skin=LittleSkin -account.skin.type.little_skin.hint=Tienes que crear un personaje con el mismo nombre que tu cuenta offline en la web de tu proveedor de skins. Tu skin será entonces subido a ese sitio. -account.skin.type.local_file=Archivo de skin local -account.skin.upload=Subir skin -account.skin.upload.failed=No se pudo subir la skin -account.skin.invalid_skin=Archivo de skin inválido +account.skin.type.little_skin.hint=Tienes que crear un jugador con el mismo nombre de jugador que tu cuenta sin conexión en el sitio web del proveedor de aspectos. Tu aspecto se ajustará ahora al aspecto asignado a tu jugador en el sitio web del proveedor de aspectos. +account.skin.type.local_file=Archivo local de aspecto +account.skin.upload=Subir/editar aspecto +account.skin.upload.failed=No se pudo subir el aspecto. +account.skin.invalid_skin=Archivo de aspecto inválido. account.username=Nombre de usuario archive.author=Autor(es) @@ -175,7 +193,7 @@ color.recent=Recomendado color.custom=Color personalizado crash.NoClassDefFound=Por favor, verifique la integridad de este software, o intente actualizar su Java. -crash.user_fault=El lanzador se ha bloqueado debido a que Java o el entorno del sistema están dañados. Por favor, asegúrese de que su Java o sistema operativo está instalado correctamente. +crash.user_fault=El launcher se ha bloqueado debido a que Java o el entorno del sistema están dañados. Por favor, asegúrese de que su Java o sistema operativo está instalado correctamente. curse.category.0=Todos @@ -228,6 +246,7 @@ curse.category.4486=Lucky Blocks curse.category.432=Buildcraft curse.category.418=Genética curse.category.4671=Integración Twitch +curse.category.5314=KubeJS curse.category.408=Recursos y minerales curse.category.4773=CraftTweaker curse.category.430=Thaumcraft @@ -267,7 +286,7 @@ curse.category.393=16x curse.category.403=Tradicional curse.category.394=32x curse.category.404=Animado -curse.category.4465=Soporte de Mod. +curse.category.4465=Soporte de Mod curse.category.402=Medieval curse.category.401=Moderno @@ -301,57 +320,87 @@ curse.sort.popularity=Popularidad curse.sort.total_downloads=Descargas totales download=Descargar -download.hint=Instalar juegos y modpacks o descargar mods, paquetes de recursos y mapas +download.hint=Instalar juegos y modpacks o descargar mods, paquetes de recursos y mundos. download.code.404=Archivo no encontrado en el servidor remoto: %s download.content=Complementos -download.existing=El archivo no se puede guardar porque ya existe. Puedes usar 'Guardar como' para guardar el archivo en otro lugar. +download.curseforge.unavailable=La versión Nightly de HMCL no admite el acceso a CurseForge. Utilice las versiones Release o Beta para descargarlas. +download.existing=El archivo no se puede guardar porque ya existe. Puedes hacer clic en "Guardar como" para guardar el archivo en otro lugar. download.external_link=Abrir sitio web -download.failed=Falló la descarga de %1$s, código de respuesta: %2$d +download.failed=Falló la descarga de %1$s, código de respuesta: %2$d. download.failed.empty=No hay versiones disponibles, por favor haga clic aquí para volver. +download.failed.no_code=No se ha podido descargar download.failed.refresh=No se ha podido obtener la lista de versiones. Por favor, haga clic aquí para volver a intentarlo. -download.game=Juego +download.game=Nuevo juego download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) -download.provider.mojang=Mojang (OptiFine es proporcionado por BMCLAPI) +download.provider.mojang=Oficial (OptiFine es proporcionado por BMCLAPI) download.provider.official=De fuentes oficiales download.provider.balanced=De la fuente más rápida disponible download.provider.mirror=Desde espejo -download.javafx=Descargar las dependencias para el launcher... +download.java=Descargando Java +download.java.override=Esta versión de Java ya existe. ¿Desea desinstalarla y volver a instalarla? +download.javafx=Descargando dependencias para el launcher... download.javafx.notes=Estamos descargando dependencias para HMCL desde Internet.\n\ -\n\ -Puede hacer clic en "Cambiar fuente de descarga" para seleccionar el espejo de descarga o hacer clic en "Cancelar" para detener y salir.\n\ -Nota: Si su velocidad de descarga es demasiado lenta, puede intentar cambiar a otro espejo. + \n\ + Puede hacer clic en "Cambiar fuente de descarga" para seleccionar el\nespejo de descarga o hacer clic en "Cancelar" para detener y salir.\n\ + Nota: Si su velocidad de descarga es demasiado lenta, puede intentar cambiar a otro espejo. download.javafx.component=Descargando módulo %s download.javafx.prepare=Preparando la descarga -exception.access_denied=HMCL no puede acceder al archivo %s, puede estar bloqueado por otro proceso.\n\ -\n\ -Para los usuarios de Windows, puede abrir el 'Monitor de Recursos' para comprobar si otro proceso lo está utilizando actualmente. Si es así, puede intentarlo de nuevo después de cerrar ese proceso.\n\ -Si no es así, comprueba si tu cuenta tiene suficientes privilegios para acceder a él. -exception.artifact_malformed=No se puede verificar la integridad de los archivos descargados . -exception.ssl_handshake=No se puede establecer una conexión SSL debido a que faltan certificados SSL en la instalación actual de Java. Puede intentar ejecutar HMCL en otra versión de Java y luego volver a intentarlo. +exception.access_denied=HMCL no puede acceder al archivo %s. Puede estar bloqueado por otro proceso.\n\ + \n\ + Para los usuarios de Windows, puede abrir el "Monitor de Recursos" para comprobar si otro proceso lo está utilizando actualmente. Si es así, puede intentarlo de nuevo después de cerrar ese proceso.\n\ + Si no es así, comprueba si tu cuenta tiene permisos suficientes para acceder a ella. +exception.artifact_malformed=No se puede verificar la integridad de los archivos descargados. +exception.ssl_handshake=No se pudo establecer una conexión SSL porque falta el certificado SSL en la instalación actual de Java. Puede intentar abrir HMCL con otro Java y volver a intentarlo. -extension.bat=Fichero por lotes de DOS +extension.bat=Archivo por lotes de Windows (.bat) extension.mod=Archivo mod. extension.png=Archivo de imagen -extension.ps1=Fichero de Cmdlet de Windows PowerShell -extension.sh=Script de Shell Bash +extension.ps1=Script de Windows PowerShell (.ps1) +extension.sh=Script de Shell Script (.sh) fatal.javafx.incompatible=No se encontró un entorno JavaFX.\n\ -HMCL no puede instalar automáticamente JavaFX con versiones de Java inferiores a la 11.\n\ -Por favor, intente cambiar a versiones de Java como Oracle Java 8 que tiene JavaFX incorporado, o actualice a la versión 11 o superior. + Hello Minecraft! Launcher no puede instalar automáticamente JavaFX con versiones de Java inferiores a la 11.\n\ + Por favor, actualice su Java a la versión 11 o posterior. +fatal.javafx.incomplete=El entorno JavaFX está incompleto.\n\ + Por favor, intente reemplazar su Java o reinstalar OpenJFX. fatal.javafx.missing=No se encontró un entorno JavaFX.\n\ -Si está utilizando Java 11 o superior, por favor, descargue Oracle JRE 8 (java.com), o instale BellSoft Liberica Full JRE (bell-sw.com/pages/downloads).\n\ -O, si está utilizando distribuciones de OpenJDK, asegúrese de que tiene incluido OpenJFX. -fatal.config_loading_failure=No se pueden cargar los archivos de configuración.\nPara macOS, intente colocar HMCL en un lugar con permiso que no sea "Escritorio", "Descargas" y "Documentos" y vuelva a intentarlo.\n\ -¡Por favor, asegúrese de que "Hello Minecraft! Launcher" tiene acceso de lectura y escritura a "%s" y a los archivos que contiene. + Por favor, abra Hello Minecraft! Launcher con Java, que incluye OpenJFX. +fatal.config_change_owner_root=Estás utilizando la cuenta root para abrir Hello Minecraft! Launcher. Esto puede hacer que no pueda abrir HMCL con otra cuenta en el futuro.\n\ + ¿Todavía quieres continuar? +fatal.config_in_temp_dir=Estás abriendo Hello Minecraft! Launcher en un directorio temporal. Tus ajustes y datos de juego pueden perderse.\n\ + Se recomienda trasladar el HMCL a otro lugar y reabrirlo.\n\ + ¿Todavía quieres continuar? +fatal.config_loading_failure=No se pueden cargar los archivos de configuración.\n\ + Por favor, asegúrese de que Hello Minecraft! Launcher tiene acceso de lectura y escritura a "%s" y a los archivos que contiene.\n\ + Para macOS, intente colocar HMCL en un lugar con permiso que no sea "Escritorio", "Descargas" y "Documentos" y vuelva a intentarlo. +fatal.config_loading_failure.unix=No se pudo cargar el archivo de configuración porque fue creado por el usuario "%1$s".\n\ + Por favor, abra HMCL como usuario root (no recomendado), o ejecute el siguiente comando en el terminal para cambiar la propiedad del archivo de configuración al usuario actual:\n%2$s +fatal.mac_app_translocation=El sistema operativo aísla Hello Minecraft! Launcher en un directorio temporal debido a los mecanismos de seguridad de macOS.\n\ + Por favor, mueve HMCL a un directorio diferente antes de intentar abrirlo. De lo contrario, tus ajustes y datos de juego podrían perderse tras reiniciar.\n\ + ¿Todavía quieres continuar? fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher ha sido actualizado. Por favor, reinicie el launcher. fatal.apply_update_failure=Lo sentimos, pero Hello Minecraft! Launcher no puede actualizarse.\n\ -\n\ -Usted puede actualizar manualmente mediante la descarga de una versión más reciente del launcher de %s.\n\ -Si el problema persiste, por favor considere reportarlo a nosotros. -fatal.samba=Si ha iniciado HMCL desde una unidad de red Samba, es posible que algunas funciones no funcionen. Por favor, intente actualizar su versión de Java o copie y ejecute el launcher en una carpeta local. -fatal.illegal_char=Su ruta de usuario contiene un carácter ilegal '\=', por lo que algunas características podrían no funcionar correctamente.\n\ -Por ejemplo, no podrá utilizar authlib-injector o cambiar el skin de su cuenta offline. + \n\ + Puedes actualizar manualmente descargando una versión más reciente del launcher desde %s.\n\ + Si el problema persiste, por favor considere reportarlo a nosotros. +fatal.apply_update_need_win7=Hello Minecraft! Launcher no puede actualizarse automáticamente en Windows XP/Vista.\n\ + \n\ + Puedes actualizar manualmente descargando una versión más reciente del launcher desde %s. +fatal.samba=Si ha abierto Hello Minecraft! Launcher desde una unidad de red Samba, es posible que algunas funciones no funcionen. Intenta actualizar tu Java o mover el launcher a otro directorio. +fatal.illegal_char=Su ruta de usuario contiene un carácter ilegal "=", por lo que algunas características podrían no funcionar correctamente.\n\ + Por ejemplo, no podrá utilizar authlib-injector o cambiar el skin de su cuenta offline. +fatal.unsupported_platform=Minecraft aún no es totalmente compatible con tu plataforma, por lo que es posible que te falten funciones o incluso que no puedas iniciar el juego.\n\ + \n\ + Si no puedes iniciar Minecraft 1.17 y versiones posteriores, puedes probar a cambiar el "Renderizador" a "Software" en "Config. Global/Específica de instancia → Configuración avanzada" para utilizar el renderizado de la CPU y mejorar la compatibilidad. +fatal.unsupported_platform.loongarch=Hello Minecraft! Launcher ha prestado apoyo a la plataforma Loongson.\n\ + Si tienes problemas al jugar, puedes visitar https://docs.hmcl.net/groups.html para obtener ayuda. +fatal.unsupported_platform.osx_arm64=Hello Minecraft! Launcher ha proporcionado soporte para la plataforma de chips de Apple, utilizando Java nativo de ARM para ejecutar juegos y conseguir una experiencia de juego más fluida.\n\ + Si tienes problemas al jugar a un juego, ejecutarlo con Java de arquitectura x86-64 puede tener mejor compatibilidad. +fatal.unsupported_platform.windows_arm64=Hello Minecraft! Launcher ha proporcionado soporte nativo para la plataforma Windows en Arm. Si tiene problemas al jugar a un juego, intente iniciarlo con Java de arquitectura x86.\n\ + \n\ + Si utilizas la plataforma Qualcomm, es posible que tengas que instalar el paquete de compatibilidad OpenGL antes de jugar.\n\ + Haz clic en el enlace para ir a Microsoft Store e instalar el paquete de compatibilidad. feedback=Comentarios feedback.channel=Canal de comentarios @@ -365,20 +414,21 @@ feedback.qq_group.statement=¡Únase a nuestro grupo QQ de usuarios! file=Archivo folder.config=Configuraciones -folder.game=Directorio de juego -folder.mod=Abrir carpeta de mods -folder.resourcepacks=Resource packs -folder.shaderpacks=Shader packs -folder.saves=Guardados +folder.game=Directorio de trabajo +folder.logs=Logs +folder.mod=Mods +folder.resourcepacks=Paquetes de recursos +folder.shaderpacks=Paquetes de sombreados +folder.saves=Mundos folder.screenshots=Capturas de pantalla -game=Juego -game.crash.feedback=¡Por favor, no comparta capturas de pantalla de esta interfaz con otras personas! Si solicita ayuda a otros, haga clic para exportar la información del bloqueo del juego en la esquina inferior izquierda y envíe el archivo exportado a otros para que lo analicen. +game=Juegos +game.crash.feedback=¡Por favor, no comparta capturas de pantalla de esta interfaz con otras personas! Si pide ayuda a otras personas, por favor haga clic en "Exportar registros de errores" y envíe el archivo exportado a otras personas para su análisis. game.crash.info=Información sobre el fallo game.crash.reason=Causa del fallo game.crash.reason.analyzing=Analizando... -game.crash.reason.multiple=Se detectaron múltiples razones:\n\n -game.crash.reason.block=El juego se ha bloqueado debido a un error.\ +game.crash.reason.multiple=Se han detectado varias razones:\n\n +game.crash.reason.block=El juego se ha bloqueado debido a un error.\n\ \n\ Puede tratar de eliminar este bloque utilizando MCEdit o eliminar el mod que lo ha añadido.\n\ \n\ @@ -549,53 +599,56 @@ game.directory=Ruta del juego game.version=Versión del juego help=Ayuda -help.doc=Documentación de ¡Hello Minecraft! Launcher -help.detail=Para los creadores de datapacks y modpacks. +help.doc=Documentación de Hello Minecraft! Launcher +help.detail=Para los creadores de paquetes de datos y mods. input.email=El nombre de usuario debe ser una dirección de correo electrónico. input.number=La entrada debe ser un número. input.not_empty=Este es un campo obligatorio. input.url=La entrada debe ser una URL válida. -install=Instalar +install=Nueva instancia install.change_version=Cambiar versión install.change_version.confirm=¿Está seguro de querer cambiar %s de la versión %s a %s? install.failed=Fallo en la instalación -install.failed.downloading=No podemos descargar algunos de los archivos necesarios. +install.failed.downloading=No se han podido descargar algunos archivos necesarios. install.failed.downloading.detail=No se ha podido descargar el archivo: %s -install.failed.downloading.timeout=Tiempo de descarga agotado en la búsqueda: %s +install.failed.downloading.timeout=Tiempo de espera de la descarga: %s install.failed.install_online=No se ha podido identificar el archivo proporcionado. Si está instalando un mod, vaya a la página "Mods". -install.failed.malformed=Los archivos descargados están dañados. Puedes intentar solucionar este problema cambiando a otra espejo de descarga. -install.failed.optifine_conflict=No se puede instalar Fabric, OptiFine y Forge en Minecraft 1.13 o superior. -install.failed.optifine_forge_1.17=Para Minecraft versión 1.17.1 o inferior, Forge sólo soporta OptiFine H1 Pre2 o más reciente. Puedes instalarlos en la pestaña de versiones instantáneas. -install.failed.version_mismatch=Esta biblioteca requiere la versión del juego %s, pero la instalada es %s. -install.installer.change_version=La versión %s no es compatible con la versión actual del juego. Haga clic aquí para sustituirla por otra versión o eliminarla. +install.failed.malformed=Los archivos descargados están dañados. Puedes intentar resolver este problema cambiando a otra fuente de descarga en "Ajustes → Descarga → Fuente de descarga". +install.failed.optifine_conflict=No se puede instalar tanto OptiFine como Fabric en Minecraft 1.13 o posterior. +install.failed.optifine_forge_1.17=Para Minecraft 1.17.1, Forge sólo es compatible con OptiFine H1 pre2 o posterior. Puedes instalarlos marcando "Snapshots" al elegir una versión de OptiFine en HMCL. +install.failed.version_mismatch=Este cargador requiere la versión del juego %s, pero la instalada es %s. +install.installer.change_version=%s Incompatible install.installer.choose=Elija su versión %s install.installer.depend=Requiere %s install.installer.fabric=Fabric install.installer.fabric-api=Fabric API install.installer.fabric-api.warning=Atención: Fabric API es un mod, y se instalará en el directorio de mods de la instancia del juego. Por favor, no cambies el directorio de trabajo del juego, o el Fabric API no funcionará. Si quieres cambiar esta configuración, debes reinstalarlo. install.installer.forge=Forge +install.installer.neoforge=NeoForge install.installer.game=Minecraft install.installer.incompatible=Incompatible con %s install.installer.install=Instalar %s install.installer.install_offline=Instalar/actualizar desde archivo local -install.installer.install_offline.extension=Instalador de Forge/OptiFine -install.installer.install_offline.tooltip=Apoyamos el uso del instalador local de Forge/OptiFine. +install.installer.install_offline.extension=Instalador de (Neo)Forge/OptiFine +install.installer.install_offline.tooltip=Apoyamos el uso del instalador local de (Neo)Forge/OptiFine. install.installer.install_online=Instalación en línea -install.installer.install_online.tooltip=Actualmente soportamos Fabric, Forge, OptiFine y LiteLoader. +install.installer.install_online.tooltip=Actualmente soportamos Forge, NeoForge, OptiFine, Fabric, Quilt y LiteLoader. install.installer.liteloader=LiteLoader -install.installer.not_installed=No seleccionado +install.installer.not_installed=No instalar install.installer.optifine=OptiFine install.installer.quilt=Quilt install.installer.quilt-api=QSL/QFAPI install.installer.version=%s -install.modpack=Instalar un Modpack +install.installer.external_version=%s (Instalado por un proceso externo, que no se puede configurar) +install.modpack=Añadir modpack +install.name.invalid=El nombre contiene caracteres no ASCII (como emoji o caracteres CJK).\n\nSe recomienda cambiar el nombre para que sólo incluya letras, números y guiones bajos en inglés para evitar posibles problemas al iniciar el juego.\n\n¿Desea continuar con la instalación? install.new_game=Añadir instancia install.new_game.already_exists=Esta instancia ya existe. Por favor, utilice otro nombre. install.new_game.current_game_version=Versión actual de la instancia -install.new_game.malformed=Nombre no válido -install.select=Seleccione una operación +install.new_game.malformed=Nombre no válido. +install.select=Elegir una operación install.success=Instalado con éxito. java.add=Añadir Java @@ -606,7 +659,8 @@ java.disabled.management=Java desactivado java.disabled.management.remove=Eliminar este Java de la lista java.disabled.management.restore=Activar este Java java.download=Descargar Java -java.download.load_list.failed=Error al cargar la lista de versiones +java.download.banshanjdk-8=Descargar Banshan JDK 8 +java.download.load_list.failed=No se ha podido cargar la lista de versiones java.download.more=Más distribuciones de Java java.download.prompt=Elija la versión de Java que desea descargar: java.download.distribution=Distribución @@ -631,48 +685,49 @@ java.uninstall.confirm=¿Está seguro de que desea desinstalar este Java? ¡Esta lang=Español lang.default=Usar idioma del sistema -launch.advice.java.auto=La versión actual de la máquina virtual de Java no cumple los requisitos del juego.\n\ -\n\ -Haga clic en "Sí" para elegir automáticamente la versión de Java VM más compatible. O bien, puede ir a la configuración de la instancia para seleccionar una usted mismo. +launch.advice=%s ¿Todavía quieres continuar? +launch.advice.multi=Se han detectado los siguientes problemas:\n\n%s\n\nEstos problemas pueden impedir que inicies el juego o afectar a la experiencia de juego.\n\n¿Todavía quieres continuar? +launch.advice.java.auto=La versión actual de la máquina virtual de Java no cumple los requisitos del juego.\n\nHaga clic en "Sí" para elegir automáticamente la versión de Java VM más compatible. O bien, puede navegar hasta "Config. Global/Específica de instancia → Java" para elegir uno usted mismo. launch.advice.java.modded_java_7=Minecraft 1.7.2 y versiones anteriores requieren Java 7 o anterior. -launch.advice.corrected=Hemos solucionado el problema de la máquina virtual de Java. Si todavía quieres usar la versión de Java que elijas, puedes desactivar las comprobaciones de compatibilidad en los ajustes de juego del launcher. -launch.advice.uncorrected=Si todavía quieres utilizar la versión de Java que elijas, puedes desactivar las comprobaciones de compatibilidad en los ajustes de juego del launcher. +launch.advice.corrected=Hemos solucionado el problema de la máquina virtual de Java. Si todavía quieres utilizar la versión de Java que elijas, puedes desactivar la opción "No comprobar la compatibilidad de la JVM" en "Config. Global/Específica de instancia → Configuración avanzada". +launch.advice.uncorrected=Si todavía quieres utilizar la versión de Java que elijas, puedes desactivar la opción "No comprobar la compatibilidad de la JVM" en "Config. Global/Específica de instancia → Configuración avanzada". launch.advice.different_platform=Se recomienda la versión de 64 bits de Java para tu dispositivo, pero has instalado una de 32 bits. -launch.advice.forge2760_liteloader=La versión 2760 o superior de Forge no es compatible con LiteLoader, por favor considera actualizar Forge a la versión 2773 o superior. -launch.advice.forge28_2_2_optifine=La versión 28.2.2 de Forge o posterior no es compatible con OptiFine. Considere la posibilidad de degradar la versión de Forge a la 28.2.1 o inferior. -launch.advice.forge37_0_60=Las versiones de Forge anteriores a la 37.0.60 no son compatibles con Java 17. Por favor, actualiza Forge a la versión 37.0.60 o superior, o inicia el juego con Java 16. -launch.advice.java8_1_13=Minecraft 1.13 y posteriores sólo pueden ejecutarse con Java 8 o posterior. Por favor, utiliza Java 8 o versiones más recientes. +launch.advice.forge2760_liteloader=La versión 2760 o posterior de Forge no es compatible con LiteLoader, por favor considere actualizar Forge a la versión 2773 o posterior. +launch.advice.forge28_2_2_optifine=La versión 28.2.2 o posterior de Forge no es compatible con OptiFine. Considere la posibilidad de actualizar Forge a la versión 28.2.1 o anterior. +launch.advice.forge37_0_60=Las versiones de Forge anteriores a la 37.0.60 no son compatibles con Java 17. Por favor, actualiza Forge a la versión 37.0.60 o posterior, o inicia el juego con Java 16. +launch.advice.java8_1_13=Minecraft 1.13 y posteriores sólo se pueden ejecutar en Java 8 o posterior. Por favor, utilice Java 8 o versiones posteriores. launch.advice.java8_51_1_13=Minecraft 1.13 puede fallar en versiones de Java 8 anteriores a la 1.8.0_51. Por favor, instala la última versión de Java 8. launch.advice.java9=No puedes ejecutar Minecraft 1.12 o anterior con Java 9 o más reciente, por favor, utiliza Java 8 en su lugar. -launch.advice.modlauncher8=La versión de Forge que estás utilizando no es compatible con la versión actual de Java. Por favor, intenta actualizar Forge, o ejecutar el juego con Java 8u312/11.0.13/17.0.1 o anterior. -launch.advice.newer_java=Se recomienda Java 8 para una experiencia de juego más fluida. Y para Minecraft 1.12 o superior, y la mayoría de los mods, es obligatorio. +launch.advice.modded_java=Algunos mods pueden no ser compatibles con las nuevas versiones de Java. Se recomienda utilizar Java %s para iniciar Minecraft %s. +launch.advice.modlauncher8=La versión de Forge que estás utilizando no es compatible con la versión actual de Java. Por favor, intenta actualizar Forge. +launch.advice.newer_java=Estás utilizando una versión antigua de Java para iniciar el juego. Se recomienda actualizar a Java 8, de lo contrario algunos mods pueden hacer que el juego se bloquee. launch.advice.not_enough_space=Has asignado un tamaño de memoria mayor que los %d MB reales de memoria instalados en tu máquina. Es posible que el rendimiento del juego se vea afectado, o incluso que no puedas iniciar el juego. +launch.advice.require_newer_java_version=La versión actual del juego requiere Java %s, pero no hemos podido encontrar uno. ¿Quieres descargar uno ahora? launch.advice.too_large_memory_for_32bit=Has asignado un tamaño de memoria mayor que la limitación de memoria de la instalación de Java de 32 bits. Es posible que no puedas iniciar el juego. -launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 o inferior sólo admite Java 8 para la plataforma Linux x86-64, porque las versiones posteriores no pueden cargar las bibliotecas nativas de 32 bits como liblwjgl.so\n\ -\n\ -Por favor, descárguelo de java.com, o instale OpenJDK 8. -launch.advice.vanilla_x86.translation=Minecraft no proporciona actualmente soporte oficial para arquitecturas distintas de x86 y x86-64.\n\ -Por favor, instale Java para x86-64 para jugar a Minecraft a través del entorno de traducción Rosetta, o descargue sus bibliotecas nativas correspondientes y especifique su ruta. +launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 o inferior sólo admite Java 8 para la plataforma Linux x86-64, porque las versiones posteriores no pueden cargar las bibliotecas nativas de 32 bits como liblwjgl.so\n\nPor favor, descárguelo de java.com, o instale OpenJDK 8. +launch.advice.vanilla_x86.translation=Minecraft no proporciona actualmente soporte oficial para arquitecturas distintas de x86 y x86-64.\n\nPor favor, instale Java para x86-64 para jugar a Minecraft a través del entorno de traducción Rosetta, o descargue sus bibliotecas nativas correspondientes y especifique su ruta. +launch.advice.unknown=El juego no puede iniciarse por las siguientes razones: launch.failed=No se puede ejecutar launch.failed.cannot_create_jvm=No podemos crear una máquina virtual Java. Puede deberse a un problema con los argumentos de ejecución proporcionados, puede intentar solucionarlo eliminando todos los argumentos que haya añadido en la configuración de la instancia. -launch.failed.creating_process=No podemos crear un nuevo proceso, por favor compruebe la ruta de Java. +launch.failed.creating_process=No podemos crear un nuevo proceso, por favor compruebe la ruta de Java.\n launch.failed.command_too_long=La longitud del comando excede la longitud máxima de un script bat. Por favor, intente exportarlo como un script de PowerShell. -launch.failed.decompressing_natives=No se han podido descomprimir las bibliotecas nativas. +launch.failed.decompressing_natives=No se han podido descomprimir las bibliotecas nativas.\n launch.failed.download_library=No se pudo descargar la biblioteca %s. launch.failed.executable_permission=No se pudo hacer ejecutable el script de ejecución. launch.failed.execution_policy=Configuración de la política de ejecución launch.failed.execution_policy.failed_to_set=No se pudo establecer la política de ejecución -launch.failed.execution_policy.hint=La política de ejecución actual impide la ejecución de scripts de PowerShell.\n\ -\n\ -Haga clic en "Aceptar" para permitir que el usuario actual ejecute scripts de PowerShell, o haga clic en "Cancelar" para mantenerlo como está. +launch.failed.execution_policy.hint=La política de ejecución actual impide la ejecución de scripts de PowerShell.\n\nHaga clic en "Aceptar" para permitir que el usuario actual ejecute scripts de PowerShell, o haga clic en "Cancelar" para mantenerlo como está. launch.failed.exited_abnormally=El juego se ha bloqueado. Por favor, consulte el registro de errores para más detalles. +launch.failed.java_version_too_low=La versión de Java que ha especificado es demasiado baja. Por favor, reajuste la versión de Java. launch.failed.no_accepted_java=No se ha podido encontrar una versión de Java compatible. Si crees que has descargado una compatible, puedes establecerla manualmente en los ajustes. +launch.failed.sigkill=El juego fue terminado a la fuerza por el usuario o el sistema. launch.state.dependencies=Resolviendo dependencias launch.state.done=Completando el inicio launch.state.java=Comprobando la versión de Java launch.state.logging_in=Iniciando sesión launch.state.modpack=Descargando dependencias launch.state.waiting_launching=Esperando la ejecución del juego +launch.invalid_java=Ruta Java inválida. Por favor, restablezca la ruta de Java. launcher=Launcher launcher.agreement=Términos de servicio y EULA @@ -683,18 +738,19 @@ launcher.background=Imagen de fondo launcher.background.choose=Elige una imagen de fondo launcher.background.classic=Clásico launcher.background.default=Por defecto -launcher.background.default.tooltip=o background.png/.jpg/.gif/.webp, o imágenes en la carpeta bg +launcher.background.default.tooltip=O "background.png/.jpg/.gif/.webp", o imágenes en la carpeta "bg" launcher.background.network=Desde la URL launcher.background.translucent=Translúcido launcher.cache_directory=Directorio de la caché launcher.cache_directory.clean=Borrar caché launcher.cache_directory.choose=Elegir el directorio de la caché -launcher.cache_directory.default=Por defecto (%APPDATA%/.minecraft o ~/.minecraft) +launcher.cache_directory.default=Por defecto ("%APPDATA%/.minecraft" o "~/.minecraft") launcher.cache_directory.disabled=Desactivado launcher.cache_directory.invalid=No se ha podido crear el directorio de la caché, volviendo a los valores por defecto. launcher.contact=Contacta con nosotros -launcher.crash=¡Hello Minecraft! Launcher ha encontrado un error fatal. Por favor, copie el siguiente registro y pida ayuda en nuestra comunidad en Discord, GitHub o Minecraft Forums. -launcher.crash.hmcl_out_dated=¡Hello Minecraft! Launcher ha encontrado un error fatal. Su launcher está desactualizado. Por favor, ¡actualícelo!. +launcher.crash=Hello Minecraft! Launcher ha encontrado un error fatal. Por favor, copie el siguiente registro y pida ayuda en nuestra comunidad en Discord, GitHub o Minecraft Forums. +launcher.crash.java_internal_error=Hello Minecraft! Launcher ha encontrado un error fatal porque su Java está dañado. Por favor, desinstala tu Java y descarga un Java adecuado aquí. +launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher ha encontrado un error fatal. Su launcher está desactualizado. Por favor, ¡actualícelo! launcher.update_java=Por favor, actualice su versión de Java. login.empty_username=¡Todavía no has puesto tu nombre de usuario! @@ -707,14 +763,13 @@ logwindow.help=Puede ir a la comunidad HMCL y encontrar a otros para ayudar logwindow.autoscroll=Desplazamiento automático logwindow.export_game_crash_logs=Exportar registros de errores logwindow.export_dump=Exportar volcado de pila de juegos -logwindow.export_dump.no_dependency=Su Java no contiene las dependencias para crear el volcado de pila. Dirígete a HMCL QQ o HMCL Discord para obtener ayuda. - +logwindow.export_dump.no_dependency=Su Java no contiene las dependencias para crear el volcado de pila. Dirígete a nuestro Discord o grupo QQ para obtener ayuda. main_page=Inicio message.cancelled=La operación se ha cancelado message.confirm=Confirmar -message.copied=Copiado en el portapapeles +message.copied=Copiado al portapapeles message.default=Por defecto message.doing=Por favor, espere message.downloading=Descargando @@ -725,36 +780,38 @@ message.success=Operación completada con éxito message.unknown=Desconocido message.warning=Atención -modpack=Modpack -modpack.choose=Seleccionar un modpack +modpack=Modpacks +modpack.choose=Elija Modpack modpack.choose.local=Importar desde un archivo local modpack.choose.local.detail=Puede arrastrar y soltar el archivo modpack aquí modpack.choose.remote=Descargar desde Internet modpack.choose.remote.detail=Se requiere un enlace de descarga directa al archivo modpack remoto modpack.choose.remote.tooltip=Por favor, introduzca la URL de su modpack -modpack.completion=Descargar las dependencias +modpack.choose.repository=Descargar Modpack de CurseForge o Modrinth +modpack.choose.repository.detail=Recuerda volver a esta página y soltar aquí el archivo del modpack una vez descargado. +modpack.completion=Descargando dependencias modpack.desc=Describa su modpack, incluyendo una introducción y probablemente algún registro de cambios. Actualmente se admiten Markdown e imágenes desde URL. modpack.description=Descripción -modpack.download=Descargar el modpack +modpack.download=Descargar Modpacks modpack.enter_name=Introduzca un nombre para este modpack. modpack.export=Exportar modpack modpack.export.as=Exportar Modpack como... modpack.file_api=Prefijo de la URL del modpack modpack.files.blueprints=Plantillas de BuildCraft -modpack.files.config=Configuración de los Mods +modpack.files.config=Archivo de configuración del Mod modpack.files.dumps=Archivo de salida de depuración NEI modpack.files.hmclversion_cfg=Archivo de configuración del launcher -modpack.files.liteconfig=Archivo de configuración del Mod +modpack.files.liteconfig=Archivos relacionados con LiteLoader modpack.files.mods=Mods modpack.files.mods.voxelmods=Opciones de VoxelMods modpack.files.options_txt=Archivo de configuración de Minecraft modpack.files.optionsshaders_txt=Archivo de configuración de shaders -modpack.files.resourcepacks=Resource packs/texturas -modpack.files.saves=Juegos guardados +modpack.files.resourcepacks=Paquetes de recursos/texturas +modpack.files.saves=Mundos de juego modpack.files.scripts=Archivo de configuración de MineTweaker modpack.files.servers_dat=Archivo de lista de servidores modpack.install=Instalar Modpack %s -modpack.installing=Instalar Modpack +modpack.installing=Instalando Modpack modpack.introduction=Actualmente se soportan los modpacks CurseForge, Modrinth, MultiMC y MCBBS. modpack.invalid=Modpack inválido, puede intentar volver a descargarlo. modpack.mismatched_type=Tipo de modpack erróneo, la instancia actual es del tipo %s, pero la proporcionada es del tipo %s. @@ -772,65 +829,113 @@ modpack.type.curse.error=No se han podido descargar las dependencias de CurseFor modpack.type.curse.not_found=Algunas dependencias ya no están disponibles, por favor intenta instalar una versión más reciente del modpack. modpack.type.manual.warning=Este archivo contiene una copia completa de una instancia de Minecraft. La mayoría de las veces, sólo tienes que descomprimirlo y ejecutar el juego usando su launcher incorporado. Pero, HMCL todavía puede importarlo, sin garantía de su utilidad, ¿aún continúa? modpack.type.mcbbs=Tipo MCBBS -modpack.type.mcbbs.export=Puede ser importado por ¡Hello Minecraft! Launcher +modpack.type.mcbbs.export=Puede ser importado por Hello Minecraft! Launcher modpack.type.modrinth=Modrinth modpack.type.multimc=MultiMC modpack.type.multimc.export=Puede ser importado por Hello Minecraft! Launcher y MultiMC modpack.type.server=Actualización automática del modpack desde el servidor modpack.type.server.export=Permite al propietario del servidor actualizar la instancia del juego de forma remota -modpack.type.server.malformed=Manifiesto de modpack inválido, por favor, consulte al creador del modpack del servidor para solucionar este problema. +modpack.type.server.malformed=Manifiesto de modpack inválido. Por favor, ponte en contacto con el creador del modpack para resolver este problema. modpack.unsupported=Hello Minecraft! Launcher no admite el formato del paquete de integración -modpack.update=Actualización del modpack +modpack.update=Actualizando modpack modpack.wizard=Asistente de exportación de modpack modpack.wizard.step.1=Configuración básica modpack.wizard.step.1.title=Algunos ajustes básicos para el modpack. -modpack.wizard.step.2=Seleccionar archivos -modpack.wizard.step.2.title=Seleccione los archivos que desea añadir al modpack. +modpack.wizard.step.2=Elegir archivos +modpack.wizard.step.2.title=Elige los archivos que quieras añadir al modpack. modpack.wizard.step.3=Tipo de modpack modpack.wizard.step.3.title=Elija el tipo de modpack que desea exportar. modpack.wizard.step.initialization.exported_version=Versión del juego a exportar modpack.wizard.step.initialization.force_update=Forzar la actualización del modpack a la última versión (necesitarás un servicio de alojamiento de archivos) modpack.wizard.step.initialization.include_launcher=Incluir el launcher modpack.wizard.step.initialization.save=Exportar a... -modpack.wizard.step.initialization.warning=Antes de crear un modpack, por favor asegúrate de que el juego se ejecuta, y que es una versión de lanzamiento en lugar de una versión instantánea. El launcher guardará su configuración de descarga.\n\ -\n\ -Ten en cuenta que no se te permite añadir mods y resource packs que se digan explícitamente que no se pueden distribuir o poner en un modpack. +modpack.wizard.step.initialization.warning=Antes de hacer un modpack, por favor asegúrate de que el juego puede ser lanzado normalmente y Minecraft es una versión de lanzamiento en lugar de una snapshot. El launcher guardará tu configuración de descarga.\n\ + \n\ + Ten en cuenta que no se te permite añadir mods y paquetes de recursos que se digan explícitamente que no se pueden distribuir o poner en un modpack. modpack.wizard.step.initialization.server=Haga clic aquí para ver más tutoriales para hacer un modpack de servidor que se pueda actualizar automáticamente. modrinth.category.adventure=Aventura +modrinth.category.audio=Audio +modrinth.category.blocks=Bloqueos +modrinth.category.bukkit=Bukkit +modrinth.category.bungeecord=BungeeCord modrinth.category.challenging=Desafío +modrinth.category.core-shaders=Sombreadores de núcleo modrinth.category.combat=Combate modrinth.category.cursed=Maldición modrinth.category.decoration=Decoración +modrinth.category.economy=Economía +modrinth.category.entities=Entidades +modrinth.category.environment=Medio ambiente modrinth.category.equipment=Equipo modrinth.category.fabric=Fabric +modrinth.category.fonts=Fonts modrinth.category.food=Alimentos modrinth.category.forge=Forge -modrinth.category.kitchen-sink=Cocina +modrinth.category.game-mechanics=Mecánica de juego +modrinth.category.gui=GUI +modrinth.category.items=Objetos +modrinth.category.kitchen-sink=Fregadero de cocina modrinth.category.library=Biblioteca -modrinth.category.lightweight=Ligero +modrinth.category.lightweight=Peso ligero +modrinth.category.liteloader=LiteLoader +modrinth.category.locale=Locale modrinth.category.magic=Magia +modrinth.category.management=Gestión +modrinth.category.minecraft=Minecraft +modrinth.category.minigame=Minijuego modrinth.category.misc=Misceláneo -modrinth.category.modloader=Modloader +modrinth.category.mobs=Creaturas +modrinth.category.modded=Modificado +modrinth.category.models=Modelos +modrinth.category.modloader=Cargador de mods modrinth.category.multiplayer=Multijugador +modrinth.category.neoforge=NeoForge modrinth.category.optimization=Optimización -modrinth.category.quests=Quests +modrinth.category.paper=Paper +modrinth.category.purpur=Purpur +modrinth.category.quests=Misiones modrinth.category.quilt=Quilt +modrinth.category.realistic=Realista modrinth.category.rift=Rift +modrinth.category.simplistic=Simplista +modrinth.category.social=Social +modrinth.category.spigot=Spigot +modrinth.category.sponge=Sponge modrinth.category.storage=Almacenamiento modrinth.category.technology=Tecnología +modrinth.category.themed=Temática +modrinth.category.transportation=Transporte +modrinth.category.tweaks=Ajustes modrinth.category.utility=Utilidad +modrinth.category.vanilla-like=Similar a la vainilla +modrinth.category.velocity=Velocity +modrinth.category.waterfall=Waterfall modrinth.category.worldgen=Generación de mundos -modrinth.category.datapack=Datapack +modrinth.category.datapack=Paquete de datos modrinth.category.folia=Folia +modrinth.category.8x-=8x- +modrinth.category.16x=16x +modrinth.category.32x=32x +modrinth.category.48x=48x +modrinth.category.64x=64x +modrinth.category.128x=128x +modrinth.category.256x=256x +modrinth.category.512x+=512x+ mods=Mods mods.add=Añadir mods -mods.add.failed=Fallo en la instalación del mod %s. -mods.add.success=%s fue instalado con éxito. +mods.add.failed=No se ha podido añadir el mod %s. +mods.add.success=%s se ha añadido correctamente. +mods.broken_dependency.title=Dependencia rota +mods.broken_dependency.desc=Esta dependencia existía antes, pero ahora no existe. Intente utilizar otra fuente de descarga. mods.category=Categoría +mods.channel.alpha=Alpha +mods.channel.beta=Beta +mods.channel.release=Release mods.check_updates=Comprobar actualizaciones mods.check_updates.current_version=Versión actual +mods.check_updates.empty=Todos los mods están actualizados mods.check_updates.failed_check=No se ha podido comprobar si hay actualizaciones. mods.check_updates.failed_download=No se han podido descargar algunos de los archivos. mods.check_updates.file=Archivo @@ -839,45 +944,93 @@ mods.check_updates.target_version=Versión de destino mods.check_updates.update=Actualización mods.choose_mod=Elige un mod mods.curseforge=CurseForge +mods.dependency.embedded=Dependencias incorporadas (Already packaged in the mod file by the author. No need to download separately) +mods.dependency.optional=Dependencias opcionales (If missing, the game will run normally, but the mod features may be missing) +mods.dependency.required=Dependencias necesarias (Must be downloaded separately. Missing may cause the game to fail to launch) +mods.dependency.tool=Dependencias necesarias (Must be downloaded separately. Missing may cause the game to fail to launch) +mods.dependency.include=Dependencias incorporadas (Already packaged in the mod file by the author, no need to download separately) +mods.dependency.incompatible=Mods incompatibles (Installing these mods at the same time will cause the game to fail to launch) +mods.dependency.broken=Dependencias rotas (This mod existed before, but it does not exist now. Try using another download source.) mods.disable=Desactivar -mods.download=Descarga de mods -mods.download.title=Descarga de mods - %1s -mods.enable=Habilitar -mods.manage=Administrar Mods +mods.download=Descargar mod +mods.download.title=Descargar mod - %1s +mods.download.recommend=Versión recomendada - Minecraft %1s +mods.enable=Activar +mods.manage=Mods mods.mcbbs=MCBBS -mods.mcmod=MCMOD -mods.mcmod.page=Página de MCMOD -mods.mcmod.search=Búsqueda en MCMOD +mods.mcmod=MCMod +mods.mcmod.page=Página de MCMod +mods.mcmod.search=Búsqueda en MCMod mods.modrinth=Modrinth mods.name=Nombre -mods.not_modded=¡Debes instalar primero un cargador de mods (Fabric, Forge o LiteLoader) para gestionar tus mods! +mods.not_modded=¡Debes instalar primero un cargador de mods (Forge, NeoForge, Fabric, Quilt o LiteLoader) para gestionar tus mods! mods.restore=Restaurar mods.url=Página oficial mods.update_modpack_mod.warning=Actualizar mods en un modpack puede generar resultados irreparables, posiblemente corrompiendo el modpack para que no pueda iniciarse. ¿Seguro que quieres actualizar? +mods.install=Instalar +mods.save_as=Guardar como + +nbt.entries=%s entradas +nbt.open.failed=No se ha podido abrir el archivo +nbt.save.failed=No se ha podido guardar el archivo +nbt.title=Ver archivo - %s -datapack=Datapacks -datapack.add=Instalar datapacks -datapack.choose_datapack=Seleccionar un paquet de datos para importar -datapack.extension=Datapacks -datapack.title=Mundos %s - Datapacks +datapack=Paquetes de datos +datapack.add=Instalar paquetes de datos +datapack.choose_datapack=Elija el paquete de datos que desea importar +datapack.extension=Paquete de datos +datapack.title=Mundo [%s] - Paquetes de datos + +web.failed=No se ha podido cargar la página +web.open_in_browser=Desea abrir esta dirección en un navegador:\n%s +web.view_in_browser=Ver en navegador world=Mundos world.add=Añadir un mundo (.zip) -world.datapack=Gestionar datapacks -world.datapack.1_13=Sólo Minecraft 1.13 o superior soporta datapacks. -world.description=%s. Jugado por última vez en %s. Versión del juego: %s. -world.download=Descargar un mundo -world.export=Exportar un mundo -world.export.title=Selecciona un directorio para este mundo exportado -world.export.location=Exportar a +world.datapack=Gestionar paquetes de datos +world.datapack.1_13=Sólo Minecraft 1.13 o posterior soporta paquetes de datos. +world.description=%s | Jugado por última vez en %s | Versión del juego: %s +world.download=Descargar Mundo +world.export=Exportar el mundo +world.export.title=Elija el directorio para este mundo exportado +world.export.location=Guardar como world.export.wizard=Exportar Mundo %s world.extension=Archivo del mundo world.game_version=Versión del juego world.import.already_exists=Este mundo ya existe. -world.import.choose=Selecciona el archivo de guardado que quieres importar +world.import.choose=Elija el archivo de mundo que desea importar world.import.failed=No se ha podido importar este mundo: %s -world.import.invalid=No se ha podido analizar el archivo guardado. -world.manage=Mundos / Datapacks +world.import.invalid=No se ha podido analizar el mundo. +world.info.title=Mundo [%s] - Información +world.info.basic=Información básica +world.info.allow_cheats=Permitir comandos/trucos +world.info.dimension.the_nether=El Nether +world.info.dimension.the_end=El End +world.info.difficulty=Dificultad +world.info.difficulty.peaceful=Pacífico +world.info.difficulty.easy=Fácil +world.info.difficulty.normal=Normal +world.info.difficulty.hard=Difícil +world.info.failed=No se ha podido leer la información del mundo +world.info.game_version=Versión del juego +world.info.last_played=Jugado por última vez +world.info.generate_features=Generar estructuras +world.info.player=Información del jugador +world.info.player.food_level=Nivel de hambre +world.info.player.game_type=Modo de juego +world.info.player.game_type.adventure=Aventura +world.info.player.game_type.creative=Creativo +world.info.player.game_type.spectator=Espectador +world.info.player.game_type.survival=Supervivencia +world.info.player.health=Salud +world.info.player.last_death_location=Lugar de la última muerte +world.info.player.location=Ubicación +world.info.player.spawn=Ubicación de desove +world.info.player.xp_level=Nivel de experiencia +world.info.random_seed=Semilla +world.info.time=Tiempo de juego +world.info.time.format=%s días +world.manage=Mundos world.name=Nombre del mundo world.name.enter=Introducir el nombre del mundo world.reveal=Abrir en el Explorador @@ -887,9 +1040,9 @@ world.time=EEE, MMM d, yyyy HH\:mm\:ss profile=Directorios del juego profile.already_exists=Este nombre ya existe, por favor, utilice un nombre diferente. profile.default=Directorio actual -profile.home=Por defecto -profile.instance_directory=Directorio de la instancia -profile.instance_directory.choose=Seleccionar directorio de instancia +profile.home=Minecraft Launcher +profile.instance_directory=Directorio ded juego +profile.instance_directory.choose=Elegir directorio de juegos profile.manage=Lista de directorios de instancia profile.name=Nombre profile.new=Nuevo directorio @@ -901,82 +1054,97 @@ repositories.custom=Repositorio Maven personalizado (%s) repositories.maven_central=Universal (Maven Central) repositories.tencentcloud_mirror=Espejo de China continental (Repositorio Maven Tencent Cloud) repositories.chooser=HMCL requiere JavaFX para funcionar.\n\ -\n\ -Por favor, haga clic en "Aceptar" para descargar JavaFX desde el repositorio especificado, o haga clic en "Cancelar" para salir.\n\ -\n\ -Repositorios\: -repositories.chooser.title=Seleccione un espejo del que descargar JavaFX + \n\ + Por favor, haga clic en "Aceptar" para descargar JavaFX desde el repositorio especificado, o haga clic en "Cancelar" para salir.\n\ + \n\ + Repositorios: +repositories.chooser.title=Elija la fuente de descarga de JavaFX -resourcepack=Resource packs +resourcepack=Paquetes de recursos search=Búsqueda -search.hint.chinese=Las consultas de búsqueda admiten chino e inglés -search.hint.english=Sólo se admite el inglés -search.enter=Вводите здесь +search.hint.chinese=Buscar en inglés y chino +search.hint.english=Buscar sólo en inglés +search.enter=Introduzca aquí el texto search.sort=Ordenar por +search.first_page=Primera +search.previous_page=Previo +search.next_page=Siguiente +search.last_page=Last +search.page_n=%d / %s selector.choose=Elegir -selector.choose_file=Seleccionar un archivo +selector.choose_file=Elegir archivo selector.custom=Personalizar settings=Configuración settings.advanced=Configuración avanzada +settings.advanced.modify=Editar configuración avanzada settings.advanced.title=Configuración avanzada - %s settings.advanced.custom_commands=Comandos personalizados -settings.advanced.custom_commands.hint=Se proporcionan las siguientes variables de entorno\:\n\ - - $INST_NAME: nombre de la versión\n\ - - $INST_ID: id de la versión\n\ - - $INST_DIR: ruta absoluta de la versión\n\ - - $INST_MC_DIR: ruta absoluta de minecraft\n\ - - $INST_JAVA: binario de java utilizado para la ejecución\n\ - - $INST_FORGE: se establece si Forge está instalado\n\ - - $INST_NEOFORGE: se establece si NeoForge está instalado\n\ - - $INST_LITELOADER: se establece si LiteLoader está instalado\n\ - - $INST_OPTIFINE: establecer si se ha instalado OptiFine\n\ - - $INST_FABRIC: establecer si está instalado Fabric\n\ - - $INST_QUILT: establecer si está instalado Quilt +settings.advanced.custom_commands.hint=Se proporcionan las siguientes variables de entorno:\n\ + \ · $INST_NAME: nombre de la instancia.\n\ + \ · $INST_ID: nombre de la instancia.\n\ + \ · $INST_DIR: ruta absoluta del directorio de trabajo de la instancia.\n\ + \ · $INST_MC_DIR: ruta absoluta del directorio del juego.\n\ + \ · $INST_JAVA: binario de java utilizado para la ejecución\n\ + \ · $INST_FORGE: disponible si Forge está instalado.\n\ + \ · $INST_NEOFORGE: disponible si NeoForge está instalado.\n\ + \ · $INST_LITELOADER: disponible si LiteLoader está instalado.\n\ + \ · $INST_OPTIFINE: disponible si OptiFine está instalado.\n\ + \ · $INST_FABRIC: disponible si Fabric está instalado.\n\ + \ · $INST_QUILT: disponible si Quilt está instalado. settings.advanced.dont_check_game_completeness=No chequear integridad del juego settings.advanced.dont_check_jvm_validity=No comprobar la compatibilidad de la JVM -settings.advanced.game_dir.default=Por defecto (.minecraft/) -settings.advanced.game_dir.independent=Aislado (.minecraft/versions//, excepto para los activos y las bibliotecas) +settings.advanced.dont_patch_natives=No intente sustituir automáticamente las bibliotecas nativas +settings.advanced.environment_variables=Variables de entorno +settings.advanced.game_dir.default=Por defecto (".minecraft/") +settings.advanced.game_dir.independent=Aislar (".minecraft/versions//", excepto para los activos y las bibliotecas) settings.advanced.java_permanent_generation_space=Espacio PermGen settings.advanced.java_permanent_generation_space.prompt=en MB settings.advanced.jvm=Opciones de la máquina virtual de Java settings.advanced.jvm_args=Argumentos de la máquina virtual de Java -settings.advanced.jvm_args.prompt=Introduzca aquí para anular las opciones predeterminadas +settings.advanced.jvm_args.prompt=\ · Si los argumentos introducidos en "Argumentos de la máquina virtual de Java" son los mismos que los argumentos por defecto, no se añadirán.\n\ + \ · Introduzca cualquier argumento GC en "Argumentos de la máquina virtual de Java", y se desactivará el argumento G1 de los argumentos por defecto.\n\ + \ · Activa "No añadir argumentos por defecto de JVM" para ejecutar el juego sin añadir argumentos por defecto. settings.advanced.launcher_visibility.close=Cerrar el launcher después de ejecutar el juego. settings.advanced.launcher_visibility.hide=Ocultar el launcher después de ejecutar el juego. settings.advanced.launcher_visibility.hide_and_reopen=Ocultar el launcher y volver a abrirlo cuando se cierra el juego. settings.advanced.launcher_visibility.keep=Mantener visible el launcher. settings.advanced.launcher_visible=Visibilidad del launcher -settings.advanced.minecraft_arguments=Argumentos del launcher +settings.advanced.minecraft_arguments=Argumentos de lanzamiento settings.advanced.minecraft_arguments.prompt=Por defecto settings.advanced.natives_directory=Ruta de la biblioteca nativa -settings.advanced.natives_directory.choose=Selecciona dónde se encuentra tu biblioteca nativa deseada +settings.advanced.natives_directory.choose=Elija la ubicación de la biblioteca nativa deseada settings.advanced.natives_directory.custom=Personalizado settings.advanced.natives_directory.default=Por defecto settings.advanced.natives_directory.hint=Esta opción está pensada sólo para usuarios de Apple M1 u otras plataformas no soportadas oficialmente. Por favor, no modifique esta opción a menos que sepa lo que está haciendo.\n\ -\n\ -Antes de proceder, por favor, asegúrese de que todas las bibliotecas (por ejemplo, lwjgl.dll, libopenal.so) se proporcionan en su directorio deseado. -settings.advanced.no_jvm_args=No añadir argumentos JVM por defecto -settings.advanced.precall_command=Comandos de preejecución -settings.advanced.precall_command.prompt=Comandos a ejecutar antes del inicio del juego + \n\ + Antes de proceder, por favor, asegúrese de que todas las bibliotecas (por ejemplo, lwjgl.dll, libopenal.so) se proporcionan en su directorio deseado. +settings.advanced.no_jvm_args=No añadir argumentos por defecto de JVM +settings.advanced.precall_command=Comando pre-lanzamiento: +settings.advanced.precall_command.prompt=El comando se ejecuta antes de que los juegos se lance settings.advanced.process_priority=Prioridad del proceso settings.advanced.process_priority.low=Bajo -settings.advanced.process_priority.below_normal=Bajo normal +settings.advanced.process_priority.below_normal=Por debajo de lo normal settings.advanced.process_priority.normal=Normal -settings.advanced.process_priority.above_normal=Superior a lo normal +settings.advanced.process_priority.above_normal=Por encima de lo normal settings.advanced.process_priority.high=Alta settings.advanced.post_exit_command=Comando post-salida -settings.advanced.post_exit_command.prompt=Comandos a ejecutar tras la salida del juego +settings.advanced.post_exit_command.prompt=El comando se ejecuta después de que el juego se detenga +settings.advanced.renderer=Renderizador +settings.advanced.renderer.default=OpenGL (Por defecto) +settings.advanced.renderer.d3d12=DirectX 12 (Rendimiento y compatibilidad deficientes) +settings.advanced.renderer.llvmpipe=Software (Bajo rendimiento, máxima compatibilidad) +settings.advanced.renderer.zink=Vulkan (Máximo rendimiento, baja compatibilidad) settings.advanced.server_ip=Dirección del servidor settings.advanced.server_ip.prompt=Entrar automáticamente después de ejecutar el juego settings.advanced.use_native_glfw=[Sólo Linux/FreeBSD] Utilizar GLFW nativo settings.advanced.use_native_openal=[Sólo Linux/FreeBSD] Utilizar OpenAL nativo settings.advanced.workaround=Métodos alternativos settings.advanced.workaround.warning=Éstas opciones están pensadas sólo para usuarios expertos. Jugar con estas opciones puede romper el juego. A menos que sepas lo que estás haciendo, por favor no modifiques estas opciones. -settings.advanced.wrapper_launcher=Wrapper Launcher +settings.advanced.wrapper_launcher=Comando Wrapper settings.advanced.wrapper_launcher.prompt=Permite ejecutar el juego usando un programa extra como 'optirun' en Linux. settings.custom=Personalizado @@ -986,19 +1154,20 @@ settings.game.current=Juego settings.game.dimension=Resolución settings.game.exploration=Explorar settings.game.fullscreen=Pantalla completa -settings.game.java_directory=Ruta de Java -settings.game.java_directory.auto=Seleccionar automáticamente +settings.game.java_directory=Java +settings.game.java_directory.auto=Elegir automáticamente settings.game.java_directory.auto.not_found=No se ha instalado ninguna versión de Java adecuada. settings.game.java_directory.bit=%s bit -settings.game.java_directory.choose=Seleccione la ruta de Java. +settings.game.java_directory.choose=Elija Java settings.game.java_directory.invalid=Ruta de Java incorrecta. settings.game.java_directory.template=%s (%s) +settings.game.java_directory.version=Especifique la versión de Java settings.game.management=Gestionar settings.game.working_directory=Directorio de trabajo -settings.game.working_directory.choose=Seleccionar directorio de trabajo -settings.game.working_directory.hint=Activar la opción 'Aislado' en 'Directorio de trabajo' para permitir que la instancia actual almacene sus configuraciones, guardados y mods en un directorio separado.\n\ -\n\ -Se recomienda activar esta opción para evitar conflictos con los mods, pero tendrás que mover tus guardados manualmente. +settings.game.working_directory.choose=Elija el directorio de trabajo +settings.game.working_directory.hint=Activar la opción "Aislar" en "Directorio de trabajo" para permitir que la instancia actual almacene sus configuraciones, mundos y mods en un directorio separado.\n\ + \n\ + Se recomienda activar esta opción para evitar conflictos con los mods, pero tendrás que mover tus guardados manualmente. settings.icon=Icono @@ -1018,7 +1187,8 @@ settings.launcher.general=General settings.launcher.language=Idioma settings.launcher.launcher_log.export=Exportar registros del launcher settings.launcher.launcher_log.export.failed=No se han podido exportar los registros -settings.launcher.launcher_log.export.success=Los registros se han exportado a %s +settings.launcher.launcher_log.export.success=Los registros se han exportado a "%s" +settings.launcher.launcher_log.reveal=Revelar registros en el Explorador settings.launcher.log=Registro settings.launcher.log.font=Fuente settings.launcher.proxy=Proxy @@ -1029,31 +1199,32 @@ settings.launcher.proxy.http=HTTP settings.launcher.proxy.none=Sin proxy settings.launcher.proxy.password=Contraseña settings.launcher.proxy.port=Puerto -settings.launcher.proxy.socks=SOCKS +settings.launcher.proxy.socks=Socks settings.launcher.proxy.username=Nombre de usuario settings.launcher.theme=Tema settings.launcher.title_transparent=Barra de título transparente +settings.launcher.turn_off_animations=Desactivar animación (Se aplica después de reiniciar) settings.launcher.version_list_source=Lista de versiones settings.memory=Memoria -settings.memory.allocate.auto=%1$.1f GB mínimo / %2$.1f GB asignado +settings.memory.allocate.auto=%1$.1f GB Mínimo / %2$.1f GB Asignado settings.memory.allocate.auto.exceeded=%1$.1f GB Mínimo / %2$.1f GB Asignado (%3$.1f GB Disponible) settings.memory.allocate.manual=%1$.1f GB Asignados settings.memory.allocate.manual.exceeded=%1$.1f GB Asignados (%3$.1f GB Disponibles) settings.memory.auto_allocate=Asignar automáticamente settings.memory.lower_bound=Memoria mínima -settings.memory.used_per_total=%1$.1f GB utilizados / %2$.1f GB totales +settings.memory.used_per_total=%1$.1f GB Utilizados / %2$.1f GB Totales settings.physical_memory=Tamaño de la memoria física settings.show_log=Mostrar registros settings.skin=Ahora se admiten los skins para las cuentas sin conexión. Puedes ir a la configuración de la cuenta para cambiar tu skin y tu capa, pero otros jugadores no podrán verlo en el multijugador. -settings.tabs.installers=Modloaders / OptiFine +settings.tabs.installers=Cargadores settings.take_effect_after_restart=Se aplica después de reiniciar settings.type=Tipo de configuración de la instancia settings.type.global=Config. Global (compartida) settings.type.global.manage=Config. Global -settings.type.global.edit=Editar ajustes globales +settings.type.global.edit=Editar Config. Global settings.type.special.enable=Habilitar ajustes personalizados para la instancia actual -settings.type.special.edit=Editar ajustes de la instancia actual +settings.type.special.edit=Editar configuración de la instancia actual settings.type.special.edit.hint=La instancia actual [%s] tiene activada la configuración por instancia, todas las opciones de esta página NO afectarán a esa instancia. Haga clic aquí para modificar sus propias opciones. sponsor=Donantes @@ -1063,6 +1234,8 @@ sponsor.hmcl=Hello Minecraft! Launcher es un launcher FOSS de Minecraft que perm system.architecture=Arquitectura system.operating_system=Sistema operativo +unofficial.hint=Está utilizando una versión no oficial de HMCL. No podemos garantizar su seguridad. + update=Actualizar update.accept=Actualizar update.changelog=Registro de cambios @@ -1089,45 +1262,50 @@ update.no_browser=No se puede abrir en el navegador del sistema. Pero, hemos cop update.tooltip=Actualización version=Juegos -version.cannot_read=No se ha podido analizar la versión del juego, la instalación automática no puede continuar. +version.name=Nombre de instancia +version.cannot_read=No se ha podido analizar la instancia del juego, la instalación no puede continuar. version.empty=No hay instancias version.empty.add=Añadir una instancia -version.empty.launch=No hay instancias, puedes instalar una en la pestaña 'Descargar'. +version.empty.launch=No hay instancias. Puedes instalar una en "Descargar → Nuevo juego". version.empty.hint=No hay instancias de Minecraft aquí. Puedes intentar cambiar a otro directorio del juego o hacer clic aquí para descargar una. version.game.old=Histórico -version.game.release=Estable +version.game.release=Lanzamiento version.game.releases=Lanzamientos version.game.snapshot=Snapshot version.game.snapshots=Snapshots version.launch=Iniciar Minecraft version.launch.test=Probar instalación -version.switch=Cambiar versión +version.switch=Cambiar Instancia version.launch_script=Exportar script de ejecución version.launch_script.failed=No se ha podido exportar el script de ejecución. version.launch_script.save=Exportar script de ejecución version.launch_script.success=Exportado el script de ejecución como %s. version.manage=Todas las instancias -version.manage.clean=Borrar archivos de registro -version.manage.clean.tooltip=Eliminar registros e informes de errores. +version.manage.clean=Eliminar archivos de registros +version.manage.clean.tooltip=Eliminar los archivos de los directorios "logs" y "crash-reports". version.manage.duplicate=Duplicar instancia -version.manage.duplicate.duplicate_save=Guardar duplicado -version.manage.duplicate.prompt=Introducir el nombre de la instancia +version.manage.duplicate.duplicate_save=Duplicar mundos +version.manage.duplicate.prompt=Introduzca el nombre de la nueva instancia version.manage.duplicate.confirm=La instancia duplicada tendrá una copia de todos los archivos de esta instancia, con un directorio de juego y una configuración aislados. -version.manage.manage=Gestionar instancias -version.manage.manage.title=Gestionar instancia - %1s +version.manage.manage=Editar instancia +version.manage.manage.title=Editar instancia - %1s version.manage.redownload_assets_index=Actualizar activos del juego -version.manage.remove=Borrar instancia -version.manage.remove.confirm=¿Está seguro de que quiere eliminar permanentemente la versión %s? ¡Esta acción no se puede deshacer! -version.manage.remove.confirm.trash=¿Estás seguro de que quieres eliminar la versión %s? Todavía puedes encontrar sus archivos en tu papelera de reciclaje con el nombre de %s. +version.manage.remove=Eliminar instancia +version.manage.remove.confirm=¿Está seguro de que quiere eliminar permanentemente la instancia "%s"? ¡Esta operación no se puede deshacer! +version.manage.remove.confirm.trash=¿Estás seguro de que quieres eliminar la instancia "%s"? Todavía puedes encontrar sus archivos en tu papelera de reciclaje con el nombre de «%s». version.manage.remove.confirm.independent=Dado que esta instancia está almacenada en un directorio aislado, al eliminarla también se eliminarán sus guardados y otros datos. ¿Aún quieres borrar la instancia %s? version.manage.remove_assets=Borrar todas las activos del juego version.manage.remove_libraries=Borrar todas las bibliotecas version.manage.rename=Renombrar instancia -version.manage.rename.message=Por favor, introduzca el nuevo nombre de esta instancia +version.manage.rename.message=Introduzca el nombre de la nueva instancia version.manage.rename.fail=No se ha podido renombrar la instancia, algunos archivos pueden estar en uso o el nombre contiene un carácter no válido. version.settings=Configuración version.update=Actualizar Modpack +wiki.tooltip=Página de Minecraft Wiki +wiki.version.game.release=https://es.minecraft.wiki/w/Java_Edition_%s +wiki.version.game.snapshot=https://es.minecraft.wiki/w/Java_Edition_%s + wizard.prev=< Previo wizard.failed=Falló wizard.finish=Finalizar From 01f9a452f16f97feaab8ab77696f4151a354635a Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Mon, 6 Jan 2025 03:40:49 +0800 Subject: [PATCH 160/169] Update ISSUE_TEMPLATE [skip ci] (#3446) * Update ISSUE_TEMPLATE [skip ci] * Apply suggestions from yushijinhun Co-authored-by: yushijinhun --------- Co-authored-by: yushijinhun --- .github/ISSUE_TEMPLATE/bug-report.yml | 44 +++++++++++++++------------ .github/ISSUE_TEMPLATE/config.yml | 8 ++--- .github/ISSUE_TEMPLATE/feature.yml | 14 ++++++--- 3 files changed, 39 insertions(+), 27 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 331b5e472b..cfe697b62a 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,6 +1,6 @@ -name: Bug 反馈 | Bug Feedback +name: Bug 反馈 | Bug Report description: - 反馈一个 HMCL 错误。| Bug Feedback. + 反馈一个 HMCL 错误。| File a bug report for HMCL. title: "[Bug] " labels: bug body: @@ -8,29 +8,35 @@ body: attributes: value: | 提交前请确认: - * 该问题确实是 **HMCL 的错误**,而**不是 Minecraft 非正常退出**,如果你的 Minecraft 非正常退出,请前往 [QQ 群](https://docs.hmcl.net/groups.html)/[Discord 频道](https://discord.gg/jVvC7HfM6U) 中获取帮助。 - * 你的启动器版本是**最新的快照版本**,可以点击 [此处](https://zkitefly.github.io/HMCL-Snapshot-Update/) 下载最新快照版本。 - - 如果你的问题并不属于上述两类,你可以选取另一种 Issue 类型,或者直接前往 [QQ 群](https://docs.hmcl.net/groups.html)/[Discord 频道](https://discord.gg/jVvC7HfM6U) 中获取帮助。 - + + * 该问题确实是 **HMCL 的错误**,而**不是 Minecraft 非正常退出**,如果你的 Minecraft 非正常退出,请前往 [QQ 群](https://docs.hmcl.net/groups.html)/[Discord 服务器](https://discord.gg/jVvC7HfM6U) 获取帮助。 + * 你的启动器版本是**最新的预览版本**,可以点击 [此处](https://zkitefly.github.io/HMCL-Snapshot-Update/) 下载最新预览版本。 + + 如果你的问题并不属于上述两类,你可以选取另一种 Issue 类型,或者直接前往 [QQ 群](https://docs.hmcl.net/groups.html)/[Discord 服务器](https://discord.gg/jVvC7HfM6U) 获取帮助。 + Before submitting, please confirm: - * The issue is indeed **an error of HMCL**, not **Minecraft abnormal exit**. If your Minecraft exits abnormally, please go to the [QQ group](https://docs.hmcl.net/groups.html) or [Discord channel](https://discord.gg/jVvC7HfM6U) for help. - * Your launcher version is **the latest snapshot version**. You can click [here](https://github.com/burningtnt/HMCL-Snapshot-Update/raw/master/datas/HMCL-dev.jar) to download the latest snapshot version. - - If your issue does not fall into the above two categories, you can choose another type of issue or directly go to the [QQ group](https://docs.hmcl.net/groups.html) or [Discord channel](https://discord.gg/jVvC7HfM6U) for help. + + * The issue is indeed **a bug of HMCL**, not **Minecraft abnormal exit**. If your Minecraft exits abnormally, please go to the [QQ group](https://docs.hmcl.net/groups.html) or [Discord server](https://discord.gg/jVvC7HfM6U) for help. + * Your launcher is the **latest nightly build**. You can click [here](https://zkitefly.github.io/HMCL-Snapshot-Update/en) to download the latest nightly build. + + If your issue does not fall into the above two categories, you can choose another type of issue or directly go to the [QQ group](https://docs.hmcl.net/groups.html) or [Discord server](https://discord.gg/jVvC7HfM6U) for help. - type: input id: platform attributes: label: 平台 | Platform - description: 请输入您遇到 BUG 的平台。 Please enter the platform on which you encountered the bug. + description: | + 请输入你遇到问题的平台。 + Please enter the platform on which you encountered the bug. placeholder: e.g. Windows 11 validations: required: true - type: textarea id: bug-report attributes: - label: 问题描述 | Problem Description - description: 请尽可能地详细描述你所遇到的问题,并描述如何重新触发这个问题。 Please describe the problem you met in as much detail as possible. Besides, please describe how to trigger this problem again. + label: 问题描述 | Bug Description + description: | + 请尽可能地详细描述你所遇到的问题,并描述如何重新触发这个问题。 + Please describe the bug you met in as much detail as possible. Additionally, describe the steps to reproduce this bug. placeholder: | 1. 点击 HMCL 上的某个按钮 | Click a button named ... 2. 向下翻页 | Scroll down @@ -42,12 +48,12 @@ body: attributes: label: 启动器崩溃报告 / 启动器日志文件 | Launcher Crash Report / Launcher Log File description: | - 如果您的启动器崩溃了,请将崩溃报告填入(或将文件拖入)下方。 - 如果您的启动器没有崩溃,请在遇到问题后不要退出启动器,在启动器的【设置】>【通用】>【调试】一栏中点击“导出启动器日志”,并将导出的日志拖到下方的输入栏中。 + 如果你的启动器崩溃了,请将崩溃报告填入(或将文件拖入)下方。 + 如果你的启动器没有崩溃,请在遇到问题后**不要退出启动器**,在启动器的 “设置 → 通用 → 调试” 一栏中点击 “导出启动器日志”,并将导出的日志拖到下方的输入栏中。 **请注意:启动器崩溃报告或日志文件是诊断问题的重要依据,请务必上传!** - If your launcher crashes, please fill it in (or drag the file in) below. - If your launcher doesn't crash, please DO NOT EXIT your launcher, click "Export Launcher Log" in the [Settings] > [General] > [Debug] column of the launcher, and drag the exported log to the input field below. - **Attention: The crash report or the log file is the key to solve the problem. Please update it!** + If your launcher crashes, please fill in (or drag the file in) the following input field with the crash report. + If your launcher does not crash, please DO NOT EXIT your launcher, click "Export Launcher Logs" in the "Settings → General → Debug" of the launcher, and drag the exported log to the following input field. + **ATTENTION: The crash report or log file is the key to resolving the bug. Please upload them!** validations: required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 9136328d37..421efa07ab 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,11 +1,11 @@ blank_issues_enabled: false contact_links: - - name: QQ 群 | QQ Groups + - name: QQ 群 | QQ Group url: https://docs.hmcl.net/groups.html - about: Hello Minecraft! Launcher 的官方 QQ 交流群。| The official QQ groups of Hello Minecraft! Laucher. - - name: Discord 频道 | Discord Channel + about: Hello Minecraft! Launcher 的官方 QQ 交流群。| The official QQ group of Hello Minecraft! Launcher. + - name: Discord 服务器 | Discord Server url: https://discord.gg/jVvC7HfM6U - about: Hello Minecraft! Launcher 的官方 Discord 频道。| The official Discord channel of Hello Minecraft! Launcher. + about: Hello Minecraft! Launcher 的官方 Discord 服务器。| The official Discord server of Hello Minecraft! Launcher. - name: 其他反馈 | Others url: https://github.com/HMCL-dev/HMCL/discussions/new/choose about: 通过 Discussions 反馈其他问题。| Report other problems in Discussions. diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index 5bab343941..13808fc650 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -1,22 +1,28 @@ name: 新功能 | Feature Request -description: 为 HMCL 提出新功能 | A new feature for HMCL +description: 为 HMCL 提出新功能。| Suggest a new feature or enhancement for HMCL. title: "[Feature] " labels: enhancement body: - type: markdown attributes: - value: 请确认 Issues 列表无重复的项目。| Please make sure that no duplicated issues has already been delivered. + value: | + 请确认 Issues 列表无重复的项目。 + Please make sure that no duplicate issues have already been submitted. - type: textarea id: description attributes: label: 描述 | Description - description: 请详细描述你想加入的新功能。| Please describe the new feature detaily. + description: | + 请详细描述你想加入的新功能。 + Please describe the new feature in detail. validations: required: true - type: textarea id: reason attributes: label: 原因 | Reason - description: 请描述该功能带来的好处及原因。| Please describe why you want to add the feature into HMCL. + description: | + 请描述该功能带来的好处及原因。 + Please describe why you want to add the feature or enhancement to HMCL. validations: required: true From 72d8b7564349ec3535ca59a8fd2fcf20304c4304 Mon Sep 17 00:00:00 2001 From: Haowei Wen Date: Thu, 16 Jan 2025 11:15:29 +0800 Subject: [PATCH 161/169] =?UTF-8?q?=E6=A8=A1=E7=BB=84=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E9=A1=B5=E4=B8=AD=E6=8C=89=E4=B8=8B=20Esc=20=E6=97=B6=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E9=80=89=E4=B8=AD=20(#3523)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 模组列表页中按下 Esc 时取消选中 目前在模组列表页中选中模组后,按下 Esc 是不会有任何反应的,因为 [ListView](https://github.com/openjdk/jfx/blob/5b074c4c2b4f539301813322a6589cec28121553/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java#L108) 会处理这个事件,认为是取消编辑,而不论是否处于编辑模式中。 这个 PR 添加了 `FXUtils.ignoreEvent()` 函数,用于忽略掉对特定事件的处理。然后,我们就可以让 ListView 不处理 Esc 按下事件,然后在模组页添加 Esc 处理逻辑(必须让 ListView 忽略掉这个事件,不然就会被它优先处理)。 理论上所有用了 ListView / JFXListView 的地方都会有这个问题,即当焦点在 ListView 中时,按下 Esc 不会触发正常的事件处理(如返回上一页、关闭对话框)。比如在游戏下载页面中,对某个版本按下右键后,焦点就会转移到其上,此时再按 Esc 就毫无反应。 * 修复 Esc 在版本下载页/模组下载页/数据包页不工作 --- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 19 +++++++++++++++++++ .../hmcl/ui/download/VersionsPage.java | 6 ++++++ .../ui/versions/DatapackListPageSkin.java | 6 ++++++ .../hmcl/ui/versions/DownloadListPage.java | 6 ++++++ .../hmcl/ui/versions/ModListPageSkin.java | 17 +++++++++++++++++ 5 files changed, 54 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index 7759337bbd..20efb21eb1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -27,6 +27,9 @@ import javafx.beans.property.BooleanProperty; import javafx.beans.property.Property; import javafx.beans.value.*; +import javafx.event.Event; +import javafx.event.EventDispatcher; +import javafx.event.EventType; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Cursor; @@ -86,6 +89,7 @@ import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -234,6 +238,21 @@ public static void removeListener(Node node, String key) { }); } + @SuppressWarnings("unchecked") + public static void ignoreEvent(Node node, EventType type, Predicate filter) { + EventDispatcher oldDispatcher = node.getEventDispatcher(); + node.setEventDispatcher((event, tail) -> { + EventType t = event.getEventType(); + while (t != null && t != type) + t = t.getSuperType(); + if (t == type && filter.test((T) event)) { + return tail.dispatchEvent(event); + } else { + return oldDispatcher.dispatchEvent(event, tail); + } + }); + } + public static void setupCellValueFactory(JFXTreeTableColumn column, Function> mapper) { column.setCellValueFactory(param -> { if (column.validateValue(param)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index 8a94ab9703..754ad121c1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -29,6 +29,8 @@ import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.ListCell; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; import javafx.scene.layout.*; import javafx.util.Duration; import org.jackhuang.hmcl.download.DownloadProvider; @@ -66,6 +68,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.ui.FXUtils.ignoreEvent; import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.wrap; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -150,6 +153,9 @@ public VersionsPage(Navigation navigation, String title, String gameVersion, Dow list.getStyleClass().add("jfx-list-view-float"); VBox.setVgrow(list, Priority.ALWAYS); + // ListViewBehavior would consume ESC pressed event, preventing us from handling it, so we ignore it here + ignoreEvent(list, KeyEvent.KEY_PRESSED, e -> e.getCode() == KeyCode.ESCAPE); + centrePane.getContent().setAll(checkPane, list); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DatapackListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DatapackListPageSkin.java index 4baa9f3164..dc6241f230 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DatapackListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DatapackListPageSkin.java @@ -27,6 +27,8 @@ import javafx.geometry.Pos; import javafx.scene.control.SelectionMode; import javafx.scene.control.SkinBase; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Region; @@ -38,6 +40,7 @@ import org.jackhuang.hmcl.ui.construct.TwoLineListItem; import org.jackhuang.hmcl.util.StringUtils; +import static org.jackhuang.hmcl.ui.FXUtils.ignoreEvent; import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.createToolbarButton; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -110,6 +113,9 @@ protected void updateControl(DatapackInfoObject dataItem, boolean empty) { listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); Bindings.bindContent(listView.getItems(), skinnable.getItems()); + // ListViewBehavior would consume ESC pressed event, preventing us from handling it, so we ignore it here + ignoreEvent(listView, KeyEvent.KEY_PRESSED, e -> e.getCode() == KeyCode.ESCAPE); + center.setContent(listView); root.setCenter(center); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java index dffe893a3f..e1fe3ae8fe 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java @@ -36,6 +36,8 @@ import javafx.scene.control.Skin; import javafx.scene.control.SkinBase; import javafx.scene.image.ImageView; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; import javafx.scene.layout.*; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.mod.RemoteMod; @@ -64,6 +66,7 @@ import java.util.Optional; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.ui.FXUtils.ignoreEvent; import static org.jackhuang.hmcl.ui.FXUtils.stringConverter; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor; @@ -493,6 +496,9 @@ protected ModDownloadListPageSkin(DownloadListPage control) { RemoteMod selectedItem = listView.getSelectionModel().getSelectedItem(); Controllers.navigate(new DownloadPage(getSkinnable(), selectedItem, getSkinnable().getProfileVersion(), getSkinnable().callback)); }); + + // ListViewBehavior would consume ESC pressed event, preventing us from handling it, so we ignore it here + ignoreEvent(listView, KeyEvent.KEY_PRESSED, e -> e.getCode() == KeyCode.ESCAPE); listView.setCellFactory(x -> new FloatListCell(listView) { TwoLineListItem content = new TwoLineListItem(); ImageView imageView = new ImageView(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index 61674d3ed9..66d3d6e1da 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -31,6 +31,8 @@ import javafx.scene.control.SkinBase; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.StackPane; @@ -70,6 +72,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.ui.FXUtils.ignoreEvent; import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.createToolbarButton2; import static org.jackhuang.hmcl.util.Lang.mapOf; @@ -170,6 +173,16 @@ class ModListPageSkin extends SkinBase { changeToolbar(toolbarSelecting); }); root.getContent().add(toolbarPane); + + // Clear selection when pressing ESC + root.addEventHandler(KeyEvent.KEY_PRESSED, e -> { + if (e.getCode() == KeyCode.ESCAPE) { + if (listView.getSelectionModel().getSelectedItem() != null) { + listView.getSelectionModel().clearSelection(); + e.consume(); + } + } + }); } { @@ -196,6 +209,10 @@ class ModListPageSkin extends SkinBase { } }); + // ListViewBehavior would consume ESC pressed event, preventing us from handling it + // So we ignore it here + ignoreEvent(listView, KeyEvent.KEY_PRESSED, e -> e.getCode() == KeyCode.ESCAPE); + center.setContent(listView); root.getContent().add(center); } From a609d32081bb2bde1ae8a1456de166baae57e99e Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Thu, 16 Jan 2025 11:26:31 +0800 Subject: [PATCH 162/169] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9D=83?= =?UTF-8?q?=E5=B9=B4=E4=BB=BD=E8=87=B32025=20(#3527)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/build.gradle.kts | 2 +- HMCL/src/main/resources/assets/lang/I18N.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_es.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_ja.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_ru.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/HMCL/build.gradle.kts b/HMCL/build.gradle.kts index 86bda3f8f1..aca92b7af3 100644 --- a/HMCL/build.gradle.kts +++ b/HMCL/build.gradle.kts @@ -121,7 +121,7 @@ tasks.getByName("sha manifest { attributes( - "Created-By" to "Copyright(c) 2013-2024 huangyuhui.", + "Created-By" to "Copyright(c) 2013-2025 huangyuhui.", "Main-Class" to "org.jackhuang.hmcl.Main", "Multi-Release" to "true", "Implementation-Version" to project.version, diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 37cbc4e40a..d99162ac6b 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2024 huangyuhui and contributors +# Copyright (C) 2025 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ about=About about.copyright=Copyright -about.copyright.statement=Copyright © 2024 huangyuhui +about.copyright.statement=Copyright © 2025 huangyuhui about.author=Author about.author.statement=bilibili @huanghongxun about.claim=EULA diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 6dd5db0cf0..538ca7efdf 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2024 huangyuhui and contributors +# Copyright (C) 2025 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ about=Acerca de about.copyright=Copyright -about.copyright.statement=Copyright © 2024 huangyuhui. +about.copyright.statement=Copyright © 2025 huangyuhui. about.author=Autor about.author.statement=bilibili @huanghongxun about.claim=EULA diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 170d0c691f..c21d74ee51 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2024 huangyuhui and contributors +# Copyright (C) 2025 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ about=について about.copyright=著作権 -about.copyright.statement=Copyright © 2024 huangyuhui +about.copyright.statement=Copyright © 2025 huangyuhui about.author=著者 about.author.statement=bilibili @huanghongxun about.claim=EULA diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 15f88033d9..1937c901ac 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2024 huangyuhui and contributors +# Copyright (C) 2025 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ about=О лаунчере about.copyright=Авторские права -about.copyright.statement=Авторские права © 2024 huangyuhui. +about.copyright.statement=Авторские права © 2025 huangyuhui. about.author=Автор about.author.statement=bilibili @huanghongxun about.claim=EULA diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index f6bcc77c28..4be11306ff 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2024 huangyuhui and contributors +# Copyright (C) 2025 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ about=關於 about.copyright=著作權 -about.copyright.statement=著作權所有 © 2024 huangyuhui +about.copyright.statement=著作權所有 © 2025 huangyuhui about.author=作者 about.author.statement=bilibili @huanghongxun about.claim=使用者協議 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 e516c160d9..eb2f683784 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1,6 +1,6 @@ # # Hello Minecraft! Launcher -# Copyright (C) 2024 huangyuhui and contributors +# Copyright (C) 2025 huangyuhui and contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ about=关于 about.copyright=版权 -about.copyright.statement=版权所有 © 2024 huangyuhui +about.copyright.statement=版权所有 © 2025 huangyuhui about.author=作者 about.author.statement=bilibili @huanghongxun about.claim=用户协议 From 35b288b800444a0c0cd4c60ffaa5145fb5d6a056 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 20 Jan 2025 14:03:11 +0800 Subject: [PATCH 163/169] =?UTF-8?q?Fix=20#3529:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=9C=A8=20FreeBSD=20x86-64=20=E5=B9=B3=E5=8F=B0=E6=9C=AA?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E6=9B=BF=E6=8D=A2=20LWJGL=20=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E5=BA=93=E7=9A=84=E9=97=AE=E9=A2=98=20(#3531)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #3529: 修复在 FreeBSD x86-64 平台未正确替换 LWJGL 本地库的问题 * update * update * update --- HMCL/src/main/resources/assets/natives.json | 204 ++++++++++++++++++-- PLATFORM.md | 24 +-- PLATFORM_cn.md | 24 +-- PLATFORM_tw.md | 24 +-- 4 files changed, 226 insertions(+), 50 deletions(-) diff --git a/HMCL/src/main/resources/assets/natives.json b/HMCL/src/main/resources/assets/natives.json index 2c3c4d50b1..13c2a1d74c 100644 --- a/HMCL/src/main/resources/assets/natives.json +++ b/HMCL/src/main/resources/assets/natives.json @@ -5274,7 +5274,7 @@ } } }, - "org.lwjgl:lwjgl:3.3.1:natives": { + "org.lwjgl:lwjgl:3.3.1:natives-linux": { "name": "org.lwjgl:lwjgl:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5296,7 +5296,7 @@ } } }, - "org.lwjgl:lwjgl-jemalloc:3.3.1:natives": { + "org.lwjgl:lwjgl-jemalloc:3.3.1:natives-linux": { "name": "org.lwjgl:lwjgl-jemalloc:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5318,7 +5318,7 @@ } } }, - "org.lwjgl:lwjgl-openal:3.3.1:natives": { + "org.lwjgl:lwjgl-openal:3.3.1:natives-linux": { "name": "org.lwjgl:lwjgl-openal:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5340,7 +5340,7 @@ } } }, - "org.lwjgl:lwjgl-opengl:3.3.1:natives": { + "org.lwjgl:lwjgl-opengl:3.3.1:natives-linux": { "name": "org.lwjgl:lwjgl-opengl:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5362,7 +5362,7 @@ } } }, - "org.lwjgl:lwjgl-glfw:3.3.1:natives": { + "org.lwjgl:lwjgl-glfw:3.3.1:natives-linux": { "name": "org.lwjgl:lwjgl-glfw:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5384,7 +5384,7 @@ } } }, - "org.lwjgl:lwjgl-stb:3.3.1:natives": { + "org.lwjgl:lwjgl-stb:3.3.1:natives-linux": { "name": "org.lwjgl:lwjgl-stb:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5406,7 +5406,7 @@ } } }, - "org.lwjgl:lwjgl-tinyfd:3.3.1:natives": { + "org.lwjgl:lwjgl-tinyfd:3.3.1:natives-linux": { "name": "org.lwjgl:lwjgl-tinyfd:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5428,7 +5428,7 @@ } } }, - "org.lwjgl:lwjgl:3.3.2:natives": { + "org.lwjgl:lwjgl:3.3.2:natives-linux": { "name": "org.lwjgl:lwjgl:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5450,7 +5450,7 @@ } } }, - "org.lwjgl:lwjgl-jemalloc:3.3.2:natives": { + "org.lwjgl:lwjgl-jemalloc:3.3.2:natives-linux": { "name": "org.lwjgl:lwjgl-jemalloc:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5472,7 +5472,7 @@ } } }, - "org.lwjgl:lwjgl-openal:3.3.2:natives": { + "org.lwjgl:lwjgl-openal:3.3.2:natives-linux": { "name": "org.lwjgl:lwjgl-openal:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5494,7 +5494,7 @@ } } }, - "org.lwjgl:lwjgl-opengl:3.3.2:natives": { + "org.lwjgl:lwjgl-opengl:3.3.2:natives-linux": { "name": "org.lwjgl:lwjgl-opengl:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5516,7 +5516,7 @@ } } }, - "org.lwjgl:lwjgl-glfw:3.3.2:natives": { + "org.lwjgl:lwjgl-glfw:3.3.2:natives-linux": { "name": "org.lwjgl:lwjgl-glfw:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5538,7 +5538,7 @@ } } }, - "org.lwjgl:lwjgl-stb:3.3.2:natives": { + "org.lwjgl:lwjgl-stb:3.3.2:natives-linux": { "name": "org.lwjgl:lwjgl-stb:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5560,7 +5560,7 @@ } } }, - "org.lwjgl:lwjgl-tinyfd:3.3.2:natives": { + "org.lwjgl:lwjgl-tinyfd:3.3.2:natives-linux": { "name": "org.lwjgl:lwjgl-tinyfd:3.3.4:natives-freebsd", "downloads": { "artifact": { @@ -5571,6 +5571,182 @@ } } }, + "org.lwjgl:lwjgl:3.3.3": { + "name": "org.lwjgl:lwjgl:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl/3.3.4/lwjgl-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl/3.3.4/lwjgl-3.3.4.jar", + "sha1": "b86c3e4832426e8a6b466013b7cb34b40e9ce956", + "size": 800127 + } + } + }, + "org.lwjgl:lwjgl:3.3.3:natives-linux": { + "name": "org.lwjgl:lwjgl:3.3.4:natives-freebsd", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl/3.3.4/lwjgl-3.3.4-natives-freebsd.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl/3.3.4/lwjgl-3.3.4-natives-freebsd.jar", + "sha1": "610d14530e637564d97d74af7cb98a737e70b77b", + "size": 96209 + } + } + }, + "org.lwjgl:lwjgl-jemalloc:3.3.3": { + "name": "org.lwjgl:lwjgl-jemalloc:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-jemalloc/3.3.4/lwjgl-jemalloc-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-jemalloc/3.3.4/lwjgl-jemalloc-3.3.4.jar", + "sha1": "e3f5dcb8e13f3a5ed3f740fd30a114cee2a80bc4", + "size": 46430 + } + } + }, + "org.lwjgl:lwjgl-jemalloc:3.3.3:natives-linux": { + "name": "org.lwjgl:lwjgl-jemalloc:3.3.4:natives-freebsd", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-jemalloc/3.3.4/lwjgl-jemalloc-3.3.4-natives-freebsd.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-jemalloc/3.3.4/lwjgl-jemalloc-3.3.4-natives-freebsd.jar", + "sha1": "5ee27f3bad4715067cef0630682da4bb5a1b88ac", + "size": 157297 + } + } + }, + "org.lwjgl:lwjgl-openal:3.3.3": { + "name": "org.lwjgl:lwjgl-openal:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-openal/3.3.4/lwjgl-openal-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-openal/3.3.4/lwjgl-openal-3.3.4.jar", + "sha1": "9b74d3ea380c83353d42af43ad9659e04dabe84a", + "size": 113103 + } + } + }, + "org.lwjgl:lwjgl-openal:3.3.3:natives-linux": { + "name": "org.lwjgl:lwjgl-openal:3.3.4:natives-freebsd", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-openal/3.3.4/lwjgl-openal-3.3.4-natives-freebsd.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-openal/3.3.4/lwjgl-openal-3.3.4-natives-freebsd.jar", + "sha1": "3863f8268f5515c27f1364257f8a018f0c6afa79", + "size": 597486 + } + } + }, + "org.lwjgl:lwjgl-opengl:3.3.3": { + "name": "org.lwjgl:lwjgl-opengl:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-opengl/3.3.4/lwjgl-opengl-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-opengl/3.3.4/lwjgl-opengl-3.3.4.jar", + "sha1": "2852ac7d9f6fc71349f1ce28e2708ff1977f18af", + "size": 931960 + } + } + }, + "org.lwjgl:lwjgl-opengl:3.3.3:natives-linux": { + "name": "org.lwjgl:lwjgl-opengl:3.3.4:natives-freebsd", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-opengl/3.3.4/lwjgl-opengl-3.3.4-natives-freebsd.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-opengl/3.3.4/lwjgl-opengl-3.3.4-natives-freebsd.jar", + "sha1": "579071d2a3714f5662522f7d3edf58e941580587", + "size": 81028 + } + } + }, + "org.lwjgl:lwjgl-glfw:3.3.3": { + "name": "org.lwjgl:lwjgl-glfw:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-glfw/3.3.4/lwjgl-glfw-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-glfw/3.3.4/lwjgl-glfw-3.3.4.jar", + "sha1": "7e46ecdec85db8738053cfde1414352cd62dab74", + "size": 147044 + } + } + }, + "org.lwjgl:lwjgl-glfw:3.3.3:natives-linux": { + "name": "org.lwjgl:lwjgl-glfw:3.3.4:natives-freebsd", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-glfw/3.3.4/lwjgl-glfw-3.3.4-natives-freebsd.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-glfw/3.3.4/lwjgl-glfw-3.3.4-natives-freebsd.jar", + "sha1": "f67b9b6c29451d8fea66db17aaba2f65e908c7e9", + "size": 104415 + } + } + }, + "org.lwjgl:lwjgl-stb:3.3.3": { + "name": "org.lwjgl:lwjgl-stb:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-stb/3.3.4/lwjgl-stb-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-stb/3.3.4/lwjgl-stb-3.3.4.jar", + "sha1": "5821735d5ef23f6da8542887344e57eb181b7cac", + "size": 143112 + } + } + }, + "org.lwjgl:lwjgl-stb:3.3.3:natives-linux": { + "name": "org.lwjgl:lwjgl-stb:3.3.4:natives-freebsd", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-stb/3.3.4/lwjgl-stb-3.3.4-natives-freebsd.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-stb/3.3.4/lwjgl-stb-3.3.4-natives-freebsd.jar", + "sha1": "f5551338a1e2035ff747053f0e985dc93db1235c", + "size": 226093 + } + } + }, + "org.lwjgl:lwjgl-tinyfd:3.3.3": { + "name": "org.lwjgl:lwjgl-tinyfd:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-tinyfd/3.3.4/lwjgl-tinyfd-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-tinyfd/3.3.4/lwjgl-tinyfd-3.3.4.jar", + "sha1": "2d73789ffd8962b38d9d599cc38b2383ce818c7a", + "size": 15928 + } + } + }, + "org.lwjgl:lwjgl-tinyfd:3.3.3:natives-linux": { + "name": "org.lwjgl:lwjgl-tinyfd:3.3.4:natives-freebsd", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-tinyfd/3.3.4/lwjgl-tinyfd-3.3.4-natives-freebsd.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-tinyfd/3.3.4/lwjgl-tinyfd-3.3.4-natives-freebsd.jar", + "sha1": "acd5e1b9b9b99ce4d21867058ee468ee45a859e5", + "size": 40104 + } + } + }, + "org.lwjgl:lwjgl-freetype:3.3.3": { + "name": "org.lwjgl:lwjgl-freetype:3.3.4", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-freetype/3.3.4/lwjgl-freetype-3.3.4.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-freetype/3.3.4/lwjgl-freetype-3.3.4.jar", + "sha1": "23f7bf165068ef2ca80ae1b79fd905af20498600", + "size": 453489 + } + } + }, + "org.lwjgl:lwjgl-freetype:3.3.3:natives-linux": { + "name": "org.lwjgl:lwjgl-freetype:3.3.4:natives-freebsd", + "downloads": { + "artifact": { + "path": "org/lwjgl/lwjgl-freetype/3.3.4/lwjgl-freetype-3.3.4-natives-freebsd.jar", + "url": "https://repo1.maven.org/maven2/org/lwjgl/lwjgl-freetype/3.3.4/lwjgl-freetype-3.3.4-natives-freebsd.jar", + "sha1": "67d6775292771087cb3d5ba1239bf9bf42fb3bd7", + "size": 1176759 + } + } + }, "net.java.jinput:jinput-platform:2.0.5:natives": null, "com.mojang:text2speech:1.10.3:natives": null, "com.mojang:text2speech:1.11.3:natives": null, diff --git a/PLATFORM.md b/PLATFORM.md index d82dd8a501..8e21b74a9e 100644 --- a/PLATFORM.md +++ b/PLATFORM.md @@ -2,18 +2,18 @@ **English** | [简体中文](PLATFORM_cn.md) | [繁體中文](PLATFORM_tw.md) -| | Windows | Linux | macOS | FreeBSD | -| -------------------------- | :----------------------------------------------- | :------------------------ | :--------------------------------------------------------------------- | :------------------------ | -| x86-64 | ✅️ | ✅️ | ✅️ | 👌 (Minecraft 1.13~1.21.1) | -| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | -| ARM64 | 👌 (Minecraft 1.8~1.18.2)
    ✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21) | 👌 (Minecraft 1.6~1.18.2)
    ✅ (Minecraft 1.19+)
    ✅ (use Rosetta 2) | ❔ | -| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | -| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | -| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.1) | / | / | -| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | -| LoongArch64 (Old World) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | -| PowerPC-64 (Little-Endian) | / | ❔ | / | / | -| S390x | / | ❔ | / | / | +| | Windows | Linux | macOS | FreeBSD | +|----------------------------|:--------------------------------------------------|:---------------------------|:------------------------------------------------------------------------|:---------------------------| +| x86-64 | ✅️ | ✅️ | ✅️ | 👌 (Minecraft 1.13~1.21.4) | +| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | +| ARM64 | 👌 (Minecraft 1.8~1.18.2)
    ✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21.4) | 👌 (Minecraft 1.6~1.18.2)
    ✅ (Minecraft 1.19+)
    ✅ (use Rosetta 2) | ❔ | +| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | +| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | +| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.4) | / | / | +| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.4) | / | / | +| LoongArch64 (Old World) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | +| PowerPC-64 (Little-Endian) | / | ❔ | / | / | +| S390x | / | ❔ | / | / | Legend: diff --git a/PLATFORM_cn.md b/PLATFORM_cn.md index 660f5a319e..60c546af2f 100644 --- a/PLATFORM_cn.md +++ b/PLATFORM_cn.md @@ -2,18 +2,18 @@ [English](PLATFORM.md) | **简体中文** | [繁體中文](PLATFORM_tw.md) -| | Windows | Linux | macOS | FreeBSD | -| -------------------------- | :----------------------------------------------- | :------------------------ | :---------------------------------------------------------------------- | :----------------------- | -| x86-64 | ✅️ | ✅️ | ✅️ | 👌(Minecraft 1.13~1.21.1) | -| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | -| ARM64 | 👌 (Minecraft 1.8~1.18.2)
    ✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21) | 👌 (Minecraft 1.6~1.18.2)
    ✅ (Minecraft 1.19+)
    ✅ (使用 Rosetta 2) | ❔ | -| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | -| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | -| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.1) | / | / | -| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | -| LoongArch64 (旧世界) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | -| PowerPC-64 (Little-Endian) | / | ❔ | / | / | -| S390x | / | ❔ | / | / | +| | Windows | Linux | macOS | FreeBSD | +|----------------------------|:--------------------------------------------------|:---------------------------|:-----------------------------------------------------------------------|:--------------------------| +| x86-64 | ✅️ | ✅️ | ✅️ | 👌(Minecraft 1.13~1.21.4) | +| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | +| ARM64 | 👌 (Minecraft 1.8~1.18.2)
    ✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21.4) | 👌 (Minecraft 1.6~1.18.2)
    ✅ (Minecraft 1.19+)
    ✅ (使用 Rosetta 2) | ❔ | +| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | +| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | +| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.4) | / | / | +| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.4) | / | / | +| LoongArch64 (旧世界) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | +| PowerPC-64 (Little-Endian) | / | ❔ | / | / | +| S390x | / | ❔ | / | / | 图例: diff --git a/PLATFORM_tw.md b/PLATFORM_tw.md index 58f20451d5..8c81e7d67b 100644 --- a/PLATFORM_tw.md +++ b/PLATFORM_tw.md @@ -2,18 +2,18 @@ [English](PLATFORM.md) | [简体中文](PLATFORM_cn.md) | **繁體中文** -| | Windows | Linux | macOS | FreeBSD | -| -------------------------- | :----------------------------------------------- | :------------------------ | :---------------------------------------------------------------------- | :----------------------- | -| x86-64 | ✅️ | ✅️ | ✅️ | 👌(Minecraft 1.13~1.21.1) | -| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | -| ARM64 | 👌 (Minecraft 1.8~1.18.2)
    ✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21) | 👌 (Minecraft 1.6~1.18.2)
    ✅ (Minecraft 1.19+)
    ✅ (使用 Rosetta 2) | ❔ | -| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | -| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | -| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.1) | / | / | -| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.1) | / | / | -| LoongArch64 (舊世界) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | -| PowerPC-64 (Little-Endian) | / | ❔ | / | / | -| S390x | / | ❔ | / | / | +| | Windows | Linux | macOS | FreeBSD | +|----------------------------|:--------------------------------------------------|:---------------------------|:-----------------------------------------------------------------------|:--------------------------| +| x86-64 | ✅️ | ✅️ | ✅️ | 👌(Minecraft 1.13~1.21.4) | +| x86 | ✅️ (~1.20.4) | ✅️ (~1.20.4) | / | / | +| ARM64 | 👌 (Minecraft 1.8~1.18.2)
    ✅ (Minecraft 1.19+) | 👌 (Minecraft 1.8~1.21.4) | 👌 (Minecraft 1.6~1.18.2)
    ✅ (Minecraft 1.19+)
    ✅ (使用 Rosetta 2) | ❔ | +| ARM32 | /️ | 👌 (Minecraft 1.8~1.20.1) | / | / | +| MIPS64el | / | 👌 (Minecraft 1.8~1.20.1) | / | / | +| RISC-V 64 | / | 👌 (Minecraft 1.13~1.21.4) | / | / | +| LoongArch64 | / | 👌 (Minecraft 1.6~1.21.4) | / | / | +| LoongArch64 (舊世界) | / | 👌 (Minecraft 1.6~1.20.1) | / | / | +| PowerPC-64 (Little-Endian) | / | ❔ | / | / | +| S390x | / | ❔ | / | / | 圖例: From c5e7ee8aef07f851f61dd86baa0eac6e615bbc86 Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 23 Jan 2025 10:23:27 +0800 Subject: [PATCH 164/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AF=B9=20Linux=20R?= =?UTF-8?q?ISC-V=2064=20=E5=B9=B3=E5=8F=B0=E7=9A=84=E6=94=AF=E6=8C=81=20(#?= =?UTF-8?q?3536)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/resources/assets/HMCLauncher.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/resources/assets/HMCLauncher.sh b/HMCL/src/main/resources/assets/HMCLauncher.sh index 824c0aa552..8cb064861a 100644 --- a/HMCL/src/main/resources/assets/HMCLauncher.sh +++ b/HMCL/src/main/resources/assets/HMCLauncher.sh @@ -33,6 +33,8 @@ case "$(uname -m)" in _HMCL_ARCH="arm64";; arm|arm32|aarch32|armv7*) _HMCL_ARCH="arm32";; + riscv64) + _HMCL_ARCH="riscv64";; loongarch64) _HMCL_ARCH="loongarch64";; *) @@ -123,7 +125,7 @@ else fi case "$_HMCL_OS-$_HMCL_ARCH" in - windows-x86|windows-x86_64|windows-arm64|linux-x86|linux-x86_64|linux-arm32|linux-arm64|linux-loongarch64|macos-x86_64|macos-arm64) + windows-x86|windows-x86_64|windows-arm64|linux-x86|linux-x86_64|linux-arm32|linux-arm64|linux-riscv64|linux-loongarch64|macos-x86_64|macos-arm64) if [ "$_HMCL_USE_CHINESE" == true ]; then echo "运行 HMCL 需要 Java 运行时环境,请安装 Java 并设置环境变量后重试。" 1>&2 echo "https://docs.hmcl.net/downloads/$_HMCL_DOWNLOAD_PAGE_OS/$_HMCL_HMCL_ARCH.html" 1>&2 From 0562042218767ec1a6116f73f6b8d359a5222d2b Mon Sep 17 00:00:00 2001 From: Zkitefly <2573874409@qq.com> Date: Thu, 23 Jan 2025 13:17:33 +0800 Subject: [PATCH 165/169] Update HMCLauncher.sh (#3265) * Update HMCLauncher.sh * update * update --------- Co-authored-by: Glavo --- HMCL/src/main/resources/assets/HMCLauncher.sh | 73 +++++++++++++------ 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/HMCL/src/main/resources/assets/HMCLauncher.sh b/HMCL/src/main/resources/assets/HMCLauncher.sh index 8cb064861a..675476ea0e 100644 --- a/HMCL/src/main/resources/assets/HMCLauncher.sh +++ b/HMCL/src/main/resources/assets/HMCLauncher.sh @@ -58,17 +58,42 @@ else _HMCL_VM_OPTIONS="-XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=15" fi +function show_warning_console() { + echo -e "\033[1;31m$1\033[0m" >&2 +} + +function show_warning_dialog() { + if [ -n "$3" ]; then + if [ -n "$(command -v xdg-open)" ]; then + if [ -n "$(command -v zenity)" ]; then + zenity --question --title="$1" --text="$2" && xdg-open "$3" + elif [ -n "$(command -v kdialog)" ]; then + kdialog --title "$1" --warningyesno "$2" && xdg-open "$3" + fi + fi + else + if [ -n "$(command -v zenity)" ]; then + zenity --info --title="$1" --text="$2" + elif [ -n "$(command -v kdialog)" ]; then + kdialog --title "$1" --msgbox "$2" + fi + fi +} + +function show_warning() { + show_warning_console "$1: $2" + show_warning_dialog "$1" "$2" +} + # First, find Java in HMCL_JAVA_HOME if [ -n "${HMCL_JAVA_HOME+x}" ]; then if [ -x "$HMCL_JAVA_HOME/bin/$_HMCL_JAVA_EXE_NAME" ]; then exec "$HMCL_JAVA_HOME/bin/$_HMCL_JAVA_EXE_NAME" $_HMCL_VM_OPTIONS -jar "$_HMCL_PATH" else if [ "$_HMCL_USE_CHINESE" == true ]; then - echo "环境变量 HMCL_JAVA_HOME 的值无效,请设置为合法的 Java 路径。" 1>&2 - echo "你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。" 1>&2 + show_warning "错误" "环境变量 HMCL_JAVA_HOME 的值无效,请设置为合法的 Java 路径。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。" else - echo "The value of the environment variable HMCL_JAVA_HOME is invalid, please set it to a valid Java path." 1>&2 - echo "You can visit the https://docs.hmcl.net/help.html page for help." 1>&2 + show_warning "Error" "The value of the environment variable HMCL_JAVA_HOME is invalid, please set it to a valid Java path.\nYou can visit the https://docs.hmcl.net/help.html page for help." fi exit 1 fi @@ -126,27 +151,27 @@ fi case "$_HMCL_OS-$_HMCL_ARCH" in windows-x86|windows-x86_64|windows-arm64|linux-x86|linux-x86_64|linux-arm32|linux-arm64|linux-riscv64|linux-loongarch64|macos-x86_64|macos-arm64) - if [ "$_HMCL_USE_CHINESE" == true ]; then - echo "运行 HMCL 需要 Java 运行时环境,请安装 Java 并设置环境变量后重试。" 1>&2 - echo "https://docs.hmcl.net/downloads/$_HMCL_DOWNLOAD_PAGE_OS/$_HMCL_HMCL_ARCH.html" 1>&2 - echo "你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。" 1>&2 - else - echo "The Java runtime environment is required to run HMCL. " 1>&2 - echo "Please install Java and set the environment variables and try again." 1>&2 - echo "https://docs.hmcl.net/downloads/$_HMCL_DOWNLOAD_PAGE_OS/$_HMCL_HMCL_ARCH.html" 1>&2 - echo "You can visit the https://docs.hmcl.net/help.html page for help." 1>&2 - fi - ;; - *) - if [ "$_HMCL_USE_CHINESE" == true ]; then - echo "运行 HMCL 需要 Java 运行时环境,请安装 Java 并设置环境变量后重试。" 1>&2 - echo "你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。" 1>&2 - else - echo "The Java runtime environment is required to run HMCL. " 1>&2 - echo "Please install Java and set the environment variables and try again." 1>&2 - echo "You can visit the https://docs.hmcl.net/help.html page for help." 1>&2 - fi + _HMCL_JAVA_DOWNLOAD_PAGE="https://docs.hmcl.net/downloads/$_HMCL_DOWNLOAD_PAGE_OS/$_HMCL_ARCH.html" ;; esac +if [ "$_HMCL_USE_CHINESE" == true ]; then + _HMCL_WARNING_MESSAGE="运行 HMCL 需要 Java 运行时环境,请安装 Java 并设置环境变量后重试。" + + if [ -n "$_HMCL_JAVA_DOWNLOAD_PAGE" ]; then + show_warning_console "错误: $_HMCL_WARNING_MESSAGE\n你可以前往此处下载:\n$_HMCL_JAVA_DOWNLOAD_PAGE" + show_warning_dialog "错误" "$_HMCL_WARNING_MESSAGE\n\n是否要前往 Java 下载页面?" "$_HMCL_JAVA_DOWNLOAD_PAGE" + else + show_warning "错误" "$_HMCL_WARNING_MESSAGE\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。" + fi +else + _HMCL_WARNING_MESSAGE="The Java runtime environment is required to run HMCL.\nPlease install Java and set the environment variables and try again." + if [ -n "$_HMCL_JAVA_DOWNLOAD_PAGE" ]; then + show_warning_console "Error: $_HMCL_WARNING_MESSAGE\nYou can download it from here:\n$_HMCL_JAVA_DOWNLOAD_PAGE" + show_warning_dialog "Error" "$_HMCL_WARNING_MESSAGE\n\nDo you want to go to the Java download page?" "$_HMCL_JAVA_DOWNLOAD_PAGE" + else + show_warning "Error" "$_HMCL_WARNING_MESSAGE\nYou can visit the https://docs.hmcl.net/help.html page for help." + fi +fi + exit 1 From 38897fbd2a763c349187cb1ea4e76eedaeccf914 Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Thu, 23 Jan 2025 13:51:55 +0800 Subject: [PATCH 166/169] =?UTF-8?q?Fix=20#3063=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E6=A8=A1=E7=BB=84=E7=AE=A1=E7=90=86=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E6=B0=B4=E5=B9=B3=E6=BB=9A=E5=8A=A8=E6=9D=A1=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=BC=82=E5=B8=B8=E7=9A=84=E9=97=AE=E9=A2=98=20(#3463?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jackhuang/hmcl/ui/construct/MDListCell.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MDListCell.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MDListCell.java index fe2f3263f4..156e62d12b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MDListCell.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MDListCell.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.ui.construct; import com.jfoenix.controls.JFXListView; +import javafx.beans.binding.DoubleBinding; import javafx.css.PseudoClass; import javafx.scene.control.ListCell; import javafx.scene.layout.Region; @@ -45,9 +46,11 @@ public MDListCell(JFXListView listView, Holder lastCell) { Region clippedContainer = (Region) listView.lookup(".clipped-container"); setPrefWidth(0); if (clippedContainer != null) { - maxWidthProperty().bind(clippedContainer.widthProperty()); - prefWidthProperty().bind(clippedContainer.widthProperty()); - minWidthProperty().bind(clippedContainer.widthProperty()); + DoubleBinding converted = clippedContainer.widthProperty().subtract(1); + + maxWidthProperty().bind(converted); + prefWidthProperty().bind(converted); + minWidthProperty().bind(converted); } } From 5afeb3d019f15f0d9195493bddca993cd515492d Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 23 Jan 2025 18:21:29 +0800 Subject: [PATCH 167/169] =?UTF-8?q?=E4=BC=98=E5=8C=96=20HMCLauncher.sh=20(?= =?UTF-8?q?#3538)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/resources/assets/HMCLauncher.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/HMCL/src/main/resources/assets/HMCLauncher.sh b/HMCL/src/main/resources/assets/HMCLauncher.sh index 675476ea0e..4b61be0031 100644 --- a/HMCL/src/main/resources/assets/HMCLauncher.sh +++ b/HMCL/src/main/resources/assets/HMCLauncher.sh @@ -124,6 +124,11 @@ case "$_HMCL_ARCH" in exec "$_HMCL_DIR/jre-arm32/bin/$_HMCL_JAVA_EXE_NAME" $_HMCL_VM_OPTIONS -jar "$_HMCL_PATH" fi ;; + riscv64) + if [ -x "$_HMCL_DIR/jre-riscv64/bin/$_HMCL_JAVA_EXE_NAME" ]; then + exec "$_HMCL_DIR/jre-riscv64/bin/$_HMCL_JAVA_EXE_NAME" $_HMCL_VM_OPTIONS -jar "$_HMCL_PATH" + fi + ;; loongarch64) if [ -x "$_HMCL_DIR/jre-loongarch64/bin/$_HMCL_JAVA_EXE_NAME" ]; then exec "$_HMCL_DIR/jre-loongarch64/bin/$_HMCL_JAVA_EXE_NAME" $_HMCL_VM_OPTIONS -jar "$_HMCL_PATH" @@ -141,6 +146,10 @@ if [ -x "$(command -v $_HMCL_JAVA_EXE_NAME)" ]; then exec $_HMCL_JAVA_EXE_NAME $_HMCL_VM_OPTIONS -jar "$_HMCL_PATH" fi +if [ "$_HMCL_OS" == "freebsd" ] && [ -x "$(command -v javavm)" ]; then + exec javavm $_HMCL_VM_OPTIONS -jar "$_HMCL_PATH" +fi + # Java not found if [ "$_HMCL_OS" == "osx" ]; then From f972c4976244e9820f078181eae6c31183dda7aa Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 24 Jan 2025 09:11:22 +0800 Subject: [PATCH 168/169] =?UTF-8?q?Fix=20#3539:=20=E5=AE=89=E8=A3=85=20Mul?= =?UTF-8?q?tiMC=20=E6=95=B4=E5=90=88=E5=8C=85=E5=90=8E=E5=BA=94=E5=BD=93?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=9B=BE=E6=A0=87=20(#3541)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jackhuang/hmcl/ui/export/ExportWizardProvider.java | 3 ++- .../hmcl/mod/multimc/MultiMCInstanceConfiguration.java | 10 +++++++++- .../hmcl/mod/multimc/MultiMCModpackInstallTask.java | 8 ++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java index 12ee29fc52..aa6c04bd69 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java @@ -192,7 +192,8 @@ public void execute() { /* overrideJavaArgs */ true, /* overrideConsole */ true, /* overrideCommands */ true, - /* overrideWindow */ true + /* overrideWindow */ true, + /* iconKey */ null // TODO ), modpackFile); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java index 8a24499294..bd61ca231b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCInstanceConfiguration.java @@ -58,6 +58,7 @@ public final class MultiMCInstanceConfiguration implements ModpackManifest { private final boolean overrideConsole; // OverrideConsole private final boolean overrideCommands; // OverrideCommands private final boolean overrideWindow; // OverrideWindow + private final String iconKey; private final MultiMCManifest mmcPack; @@ -94,6 +95,7 @@ public final class MultiMCInstanceConfiguration implements ModpackManifest { wrapperCommand = readValue(p, "WrapperCommand"); name = defaultName; notes = Optional.ofNullable(readValue(p, "notes")).orElse(""); + iconKey = readValue(p, "iconKey"); } /** @@ -112,7 +114,7 @@ private String readValue(Properties p, String key) { return value; } - public MultiMCInstanceConfiguration(String instanceType, String name, String gameVersion, Integer permGen, String wrapperCommand, String preLaunchCommand, String postExitCommand, String notes, String javaPath, String jvmArgs, boolean fullscreen, Integer width, Integer height, Integer maxMemory, Integer minMemory, boolean showConsole, boolean showConsoleOnError, boolean autoCloseConsole, boolean overrideMemory, boolean overrideJavaLocation, boolean overrideJavaArgs, boolean overrideConsole, boolean overrideCommands, boolean overrideWindow) { + public MultiMCInstanceConfiguration(String instanceType, String name, String gameVersion, Integer permGen, String wrapperCommand, String preLaunchCommand, String postExitCommand, String notes, String javaPath, String jvmArgs, boolean fullscreen, Integer width, Integer height, Integer maxMemory, Integer minMemory, boolean showConsole, boolean showConsoleOnError, boolean autoCloseConsole, boolean overrideMemory, boolean overrideJavaLocation, boolean overrideJavaArgs, boolean overrideConsole, boolean overrideCommands, boolean overrideWindow, String iconKey) { this.instanceType = instanceType; this.name = name; this.gameVersion = gameVersion; @@ -138,6 +140,7 @@ public MultiMCInstanceConfiguration(String instanceType, String name, String gam this.overrideCommands = overrideCommands; this.overrideWindow = overrideWindow; this.mmcPack = null; + this.iconKey = iconKey; } public String getInstanceType() { @@ -310,6 +313,10 @@ public boolean isOverrideWindow() { return overrideWindow; } + public String getIconKey() { + return iconKey; + } + public Properties toProperties() { Properties p = new Properties(); if (instanceType != null) p.setProperty("InstanceType", instanceType); @@ -336,6 +343,7 @@ public Properties toProperties() { if (wrapperCommand != null) p.setProperty("WrapperCommand", wrapperCommand); if (name != null) p.setProperty("name", name); if (notes != null) p.setProperty("notes", notes); + if (iconKey != null) p.setProperty("iconKey", iconKey); return p; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java index 973da7726e..900f3a01a9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/multimc/MultiMCModpackInstallTask.java @@ -199,6 +199,14 @@ public void execute() throws Exception { Path jarmods = root.resolve("jarmods"); if (Files.exists(jarmods)) FileUtils.copyDirectory(jarmods, repository.getVersionRoot(name).toPath().resolve("jarmods")); + + String iconKey = this.manifest.getIconKey(); + if (iconKey != null) { + Path iconFile = root.resolve(iconKey + ".png"); + if (Files.exists(iconFile)) { + FileUtils.copyFile(iconFile, repository.getVersionRoot(name).toPath().resolve("icon.png")); + } + } } dependencies.add(repository.saveAsync(version)); From 38adb48051a3684402845f0815acf4ad2f89478d Mon Sep 17 00:00:00 2001 From: 3gf8jv4dv <3gf8jv4dv@gmail.com> Date: Sat, 25 Jan 2025 16:38:55 +0800 Subject: [PATCH 169/169] Fix qq badge in readme (#3544) ref: https://shields.io/blog/simple-icons-14 --- README.md | 2 +- README_cn.md | 2 +- README_tw.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b8eff4bad5..e0174ae520 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![Downloads](https://img.shields.io/github/downloads/HMCL-dev/HMCL/total?style=flat) ![Stars](https://img.shields.io/github/stars/HMCL-dev/HMCL?style=flat) [![Discord](https://img.shields.io/discord/995291757799538688.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/jVvC7HfM6U) -[![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=tencentqq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) +[![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=qq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) **English** | [简体中文](README_cn.md) | [繁體中文](README_tw.md) diff --git a/README_cn.md b/README_cn.md index 2bd1a02711..9b8928f360 100644 --- a/README_cn.md +++ b/README_cn.md @@ -4,7 +4,7 @@ ![Downloads](https://img.shields.io/github/downloads/HMCL-dev/HMCL/total?style=flat) ![Stars](https://img.shields.io/github/stars/HMCL-dev/HMCL?style=flat) [![Discord](https://img.shields.io/discord/995291757799538688.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/jVvC7HfM6U) -[![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=tencentqq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) +[![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=qq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) [English](README.md) | **简体中文** | [繁體中文](README_tw.md) diff --git a/README_tw.md b/README_tw.md index 79c31a3f35..6136081f88 100644 --- a/README_tw.md +++ b/README_tw.md @@ -4,7 +4,7 @@ ![Downloads](https://img.shields.io/github/downloads/HMCL-dev/HMCL/total?style=flat) ![Stars](https://img.shields.io/github/stars/HMCL-dev/HMCL?style=flat) [![Discord](https://img.shields.io/discord/995291757799538688.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/jVvC7HfM6U) -[![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=tencentqq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) +[![QQ Group](https://img.shields.io/badge/QQ-HMCL-bright?label=&logo=qq&logoColor=ffffff&color=1EBAFC&labelColor=1DB0EF&logoSize=auto)](https://docs.hmcl.net/groups.html) [English](README.md) | [简体中文](README_cn.md) | **繁體中文**