From 70461dbde3012d63a0d8de94ca990142a77e90b1 Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Fri, 28 Mar 2025 11:27:12 +0800 Subject: [PATCH 01/16] AssetsCleaner --- .../jackhuang/hmcl/ui/main/SettingsView.java | 8 +- .../shulker/assetscleaner/AssetsCleaner.java | 79 +++++++++++++++++++ .../shulker/assetscleaner/TestCleaner.java | 7 ++ 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java create mode 100644 HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java 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 5f57b36a02..e67ed3c018 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 neko.shulker.assetscleaner.TestCleaner; import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.setting.EnumCommonDirectory; import org.jackhuang.hmcl.setting.Theme; @@ -196,13 +197,18 @@ public SettingsView() { openLogFolderButton.setOnAction(e -> openLogFolder()); openLogFolderButton.getStyleClass().add("jfx-button-border"); + // 测试Clean + JFXButton testCleanerButton = new JFXButton(i18n("testCleaner")); + testCleanerButton.setOnAction(e -> {TestCleaner.test();}); + testCleanerButton.getStyleClass().add("jfx-button-border"); + JFXButton logButton = new JFXButton(i18n("settings.launcher.launcher_log.export")); logButton.setOnAction(e -> onExportLogs()); logButton.getStyleClass().add("jfx-button-border"); HBox buttonBox = new HBox(); buttonBox.setSpacing(10); - buttonBox.getChildren().addAll(openLogFolderButton, logButton); + buttonBox.getChildren().addAll(openLogFolderButton, testCleanerButton, logButton); BorderPane.setAlignment(buttonBox, Pos.CENTER_RIGHT); debugPane.setRight(buttonBox); diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java new file mode 100644 index 0000000000..fb02b3e26b --- /dev/null +++ b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java @@ -0,0 +1,79 @@ +package neko.shulker.assetscleaner; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.lang.reflect.Type; + +public class AssetsCleaner { + public static void clean(String indexesDirectory, String assetsDirectory) { + // 用于存储所有 index 中 hash 键值的 Map + Map> hashMap = new HashMap<>(); + + try { + // 遍历 indexesDirectory 目录下的所有 JSON 文件 + Path dirPath = Paths.get(indexesDirectory); + Files.walk(dirPath) + .filter(Files::isRegularFile) + .filter(path -> path.toString().endsWith(".json")) + .forEach(jsonFile -> { + try (FileReader reader = new FileReader(jsonFile.toString())) { + // 解析每个 JSON 文件 + Gson gson = new Gson(); + Type type = new TypeToken>>>() {}.getType(); + Map>> jsonData = gson.fromJson(reader, type); + + // 提取 hash 的键值 + Map> objects = jsonData.get("objects"); + if (objects != null) { + for (Map.Entry> entry : objects.entrySet()) { + String filePath = entry.getKey(); + Map fileData = entry.getValue(); + String hash = (String) fileData.get("hash"); + if (hash != null && !hashMap.containsKey(hash)) { + hashMap.put(hash, fileData); + } + } + } + } catch (IOException e) { + System.err.println("[AssetsCleaner]: Error reading JSON file: " + jsonFile); + e.printStackTrace(); + } + }); + + // 输出 hashMap 中保存的所有 hash 值 + System.out.println("[AssetsCleaner]: 所有 hash 值:"); + for (String hash : hashMap.keySet()) { + System.out.println(hash); + } + + // 遍历目标处理目录文件 + Path assetsDirPath = Paths.get(assetsDirectory); + Files.walk(assetsDirPath) + .filter(Files::isRegularFile) + .forEach(file -> { + String fileName = file.getFileName().toString(); + // 判断文件是否在 hashMap 中 + if (!hashMap.containsKey(fileName)) { + // 如果不在则删除 + try { + Files.delete(file); + System.out.println("[AssetsCleaner]: Deleted file: " + file); + } catch (IOException e) { + System.err.println("[AssetsCleaner]: Error deleting file: " + file); + e.printStackTrace(); + } + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java new file mode 100644 index 0000000000..0d1d9e5f15 --- /dev/null +++ b/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java @@ -0,0 +1,7 @@ +package neko.shulker.assetscleaner; + +public class TestCleaner { + public static void test(){ + AssetsCleaner.clean("/home/shulker/ttt/assets/indexes/", "/home/shulker/ttt/assets/objects"); + } +} From 669dd6edd87ba8e5f47d08d504fa3ae3adab102a Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Fri, 28 Mar 2025 12:41:53 +0800 Subject: [PATCH 02/16] Style Check --- .../java/org/jackhuang/hmcl/ui/main/SettingsView.java | 8 +------- .../java/neko/shulker/assetscleaner/AssetsCleaner.java | 4 ++-- .../main/java/neko/shulker/assetscleaner/TestCleaner.java | 4 ++-- 3 files changed, 5 insertions(+), 11 deletions(-) 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 e67ed3c018..5f57b36a02 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,7 +30,6 @@ import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; import javafx.scene.text.TextFlow; -import neko.shulker.assetscleaner.TestCleaner; import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.setting.EnumCommonDirectory; import org.jackhuang.hmcl.setting.Theme; @@ -197,18 +196,13 @@ public SettingsView() { openLogFolderButton.setOnAction(e -> openLogFolder()); openLogFolderButton.getStyleClass().add("jfx-button-border"); - // 测试Clean - JFXButton testCleanerButton = new JFXButton(i18n("testCleaner")); - testCleanerButton.setOnAction(e -> {TestCleaner.test();}); - testCleanerButton.getStyleClass().add("jfx-button-border"); - JFXButton logButton = new JFXButton(i18n("settings.launcher.launcher_log.export")); logButton.setOnAction(e -> onExportLogs()); logButton.getStyleClass().add("jfx-button-border"); HBox buttonBox = new HBox(); buttonBox.setSpacing(10); - buttonBox.getChildren().addAll(openLogFolderButton, testCleanerButton, logButton); + buttonBox.getChildren().addAll(openLogFolderButton, logButton); BorderPane.setAlignment(buttonBox, Pos.CENTER_RIGHT); debugPane.setRight(buttonBox); diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java index fb02b3e26b..d1394aab8d 100644 --- a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java +++ b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java @@ -12,7 +12,7 @@ import java.util.Map; import java.lang.reflect.Type; -public class AssetsCleaner { +class AssetsCleaner { public static void clean(String indexesDirectory, String assetsDirectory) { // 用于存储所有 index 中 hash 键值的 Map Map> hashMap = new HashMap<>(); @@ -76,4 +76,4 @@ public static void clean(String indexesDirectory, String assetsDirectory) { e.printStackTrace(); } } -} \ No newline at end of file +} diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java index 0d1d9e5f15..d17c9060eb 100644 --- a/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java +++ b/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java @@ -1,7 +1,7 @@ package neko.shulker.assetscleaner; -public class TestCleaner { - public static void test(){ +class TestCleaner { + public static void test() { AssetsCleaner.clean("/home/shulker/ttt/assets/indexes/", "/home/shulker/ttt/assets/objects"); } } From eeb4303ec075837fcf964b4e4fafbc39269087a3 Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Fri, 28 Mar 2025 13:08:29 +0800 Subject: [PATCH 03/16] Style Check --- .../java/neko/shulker/assetscleaner/AssetsCleaner.java | 5 ++++- .../main/java/neko/shulker/assetscleaner/TestCleaner.java | 7 ------- 2 files changed, 4 insertions(+), 8 deletions(-) delete mode 100644 HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java index d1394aab8d..3b91e875ae 100644 --- a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java +++ b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java @@ -12,7 +12,10 @@ import java.util.Map; import java.lang.reflect.Type; -class AssetsCleaner { +public final class AssetsCleaner { + private AssetsCleaner( ) { + throw new UnsupportedOperationException(); + } public static void clean(String indexesDirectory, String assetsDirectory) { // 用于存储所有 index 中 hash 键值的 Map Map> hashMap = new HashMap<>(); diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java deleted file mode 100644 index d17c9060eb..0000000000 --- a/HMCLCore/src/main/java/neko/shulker/assetscleaner/TestCleaner.java +++ /dev/null @@ -1,7 +0,0 @@ -package neko.shulker.assetscleaner; - -class TestCleaner { - public static void test() { - AssetsCleaner.clean("/home/shulker/ttt/assets/indexes/", "/home/shulker/ttt/assets/objects"); - } -} From 5146f4f337a0220b72ce50d4fe07b3c0c523a54c Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Fri, 28 Mar 2025 13:16:21 +0800 Subject: [PATCH 04/16] Style Check --- .../src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java index 3b91e875ae..2debea3aeb 100644 --- a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java +++ b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java @@ -13,9 +13,11 @@ import java.lang.reflect.Type; public final class AssetsCleaner { + private AssetsCleaner( ) { throw new UnsupportedOperationException(); } + public static void clean(String indexesDirectory, String assetsDirectory) { // 用于存储所有 index 中 hash 键值的 Map Map> hashMap = new HashMap<>(); From fa48ad7e4406fef4a9327a9d445149372ec3efec Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Sun, 30 Mar 2025 21:47:40 +0800 Subject: [PATCH 05/16] =?UTF-8?q?=E6=B7=BB=E5=8A=A0indexes=E6=B8=85?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shulker/assetscleaner/AssetsCleaner.java | 182 +++++++++++++----- 1 file changed, 132 insertions(+), 50 deletions(-) diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java index 2debea3aeb..6842ce9d8d 100644 --- a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java +++ b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java @@ -3,55 +3,120 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import java.io.File; import java.io.FileReader; +import java.io.FilenameFilter; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; +import java.io.Reader; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.lang.reflect.Type; public final class AssetsCleaner { - private AssetsCleaner( ) { + private AssetsCleaner() { throw new UnsupportedOperationException(); } - - public static void clean(String indexesDirectory, String assetsDirectory) { + + private static List getIndexes(String versionsDirectory) { + List indexes = new ArrayList<>(); + File versionsDir = new File(versionsDirectory); + + // 遍历 versionsDirectory 中的所有文件夹 + if (versionsDir.exists() && versionsDir.isDirectory()) { + File[] versionFolders = versionsDir.listFiles(File::isDirectory); + if (versionFolders != null) { + for (File versionFolder : versionFolders) { + String versionName = versionFolder.getName(); + File jsonFile = new File(versionFolder, versionName + ".json"); + + if (jsonFile.exists() && jsonFile.isFile()) { + try (Reader reader = new FileReader(jsonFile)) { + // 解析 JSON 文件 + Gson gson = new Gson(); + Map versionData = gson.fromJson(reader, Map.class); + + // 提取 "assets" 的值 + Object assetsValue = versionData.get("assets"); + if (assetsValue instanceof String) { + String assets = (String) assetsValue; + indexes.add(assets); + } + } catch (IOException e) { + System.err.println("[AssetsCleaner]: Error reading JSON file: " + jsonFile); + e.printStackTrace(); + } + } + } + } + } + + return indexes; + } + + public static void clean(String repoDirectory) { + // 构造路径 + String versionsDirectory = Paths.get(repoDirectory, "versions").toString(); + String indexesDirectory = Paths.get(repoDirectory, "assets", "indexes").toString(); + String objectsDirectory = Paths.get(repoDirectory, "assets", "objects").toString(); + + // 获取 indexes + List requiredIndexes = getIndexes(versionsDirectory); + // 用于存储所有 index 中 hash 键值的 Map Map> hashMap = new HashMap<>(); try { // 遍历 indexesDirectory 目录下的所有 JSON 文件 - Path dirPath = Paths.get(indexesDirectory); - Files.walk(dirPath) - .filter(Files::isRegularFile) - .filter(path -> path.toString().endsWith(".json")) - .forEach(jsonFile -> { - try (FileReader reader = new FileReader(jsonFile.toString())) { - // 解析每个 JSON 文件 - Gson gson = new Gson(); - Type type = new TypeToken>>>() {}.getType(); - Map>> jsonData = gson.fromJson(reader, type); - - // 提取 hash 的键值 - Map> objects = jsonData.get("objects"); - if (objects != null) { - for (Map.Entry> entry : objects.entrySet()) { - String filePath = entry.getKey(); - Map fileData = entry.getValue(); - String hash = (String) fileData.get("hash"); - if (hash != null && !hashMap.containsKey(hash)) { - hashMap.put(hash, fileData); - } + File indexesDir = new File(indexesDirectory); + if (!indexesDir.exists() || !indexesDir.isDirectory()) { + System.err.println("[AssetsCleaner]: Indexes directory does not exist: " + indexesDir); + return; + } + + // 获取 indexesDirectory 中的所有 JSON 文件 + File[] indexFiles = indexesDir.listFiles((FilenameFilter) (dir, name) -> name.endsWith(".json")); + if (indexFiles != null) { + for (File indexFile : indexFiles) { + String indexFileName = indexFile.getName(); + String indexName = indexFileName.substring(0, indexFileName.lastIndexOf('.')); + + // 检查该 index 是否在 requiredIndexes 中 + if (!requiredIndexes.contains(indexName)) { + // 如果不在 requiredIndexes 中,则删除该 index 文件 + if (!indexFile.delete()) { + System.err.println("[AssetsCleaner]: Error deleting index file: " + indexFile); + } else { + System.out.println("[AssetsCleaner]: Deleted unnecessary index: " + indexFile); + } + continue; + } + + // 解析 JSON 文件 + try (Reader reader = new FileReader(indexFile)) { + Gson gson = new Gson(); + Map>> jsonData = gson.fromJson(reader, new TypeToken>>>() {}.getType()); + + // 提取 hash 的键值 + Map> objects = jsonData.get("objects"); + if (objects != null) { + for (Map.Entry> entry : objects.entrySet()) { + String filePath = entry.getKey(); + Map fileData = entry.getValue(); + String hash = (String) fileData.get("hash"); + if (hash != null && !hashMap.containsKey(hash)) { + hashMap.put(hash, fileData); } } - } catch (IOException e) { - System.err.println("[AssetsCleaner]: Error reading JSON file: " + jsonFile); - e.printStackTrace(); } - }); + } catch (IOException e) { + System.err.println("[AssetsCleaner]: Error reading JSON file: " + indexFile); + e.printStackTrace(); + } + } + } // 输出 hashMap 中保存的所有 hash 值 System.out.println("[AssetsCleaner]: 所有 hash 值:"); @@ -60,25 +125,42 @@ public static void clean(String indexesDirectory, String assetsDirectory) { } // 遍历目标处理目录文件 - Path assetsDirPath = Paths.get(assetsDirectory); - Files.walk(assetsDirPath) - .filter(Files::isRegularFile) - .forEach(file -> { - String fileName = file.getFileName().toString(); - // 判断文件是否在 hashMap 中 - if (!hashMap.containsKey(fileName)) { - // 如果不在则删除 - try { - Files.delete(file); - System.out.println("[AssetsCleaner]: Deleted file: " + file); - } catch (IOException e) { - System.err.println("[AssetsCleaner]: Error deleting file: " + file); - e.printStackTrace(); - } - } - }); - } catch (IOException e) { + File objectsDir = new File(objectsDirectory); + if (!objectsDir.exists() || !objectsDir.isDirectory()) { + System.err.println("[AssetsCleaner]: Objects directory does not exist: " + objectsDir); + return; + } + + // 递归遍历 objectsDirectory + traverseAndCleanDirectory(objectsDir, hashMap); + } catch (Exception e) { e.printStackTrace(); } } -} + + private static void traverseAndCleanDirectory(File directory, Map> hashMap) { + if (!directory.exists() || !directory.isDirectory()) { + return; + } + + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + traverseAndCleanDirectory(file, hashMap); + } else { + String fileName = file.getName(); + // 判断文件是否在 hashMap 中 + if (!hashMap.containsKey(fileName)) { + // 如果不在则删除 + if (!file.delete()) { + System.err.println("[AssetsCleaner]: Error deleting file: " + file); + } else { + System.out.println("[AssetsCleaner]: Deleted file: " + file); + } + } + } + } + } + } +} \ No newline at end of file From 2317b6951443b857bb2dd6b3a716fbf228bc3bd0 Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Sun, 30 Mar 2025 21:52:45 +0800 Subject: [PATCH 06/16] =?UTF-8?q?=E6=B7=BB=E5=8A=A0indexes=E6=B8=85?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java index 6842ce9d8d..b2386b3ca4 100644 --- a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java +++ b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java @@ -163,4 +163,4 @@ private static void traverseAndCleanDirectory(File directory, Map Date: Thu, 17 Jul 2025 14:25:52 +0800 Subject: [PATCH 07/16] Added username length detection --- .../org/jackhuang/hmcl/ui/account/CreateAccountPane.java | 5 ++++- HMCL/src/main/resources/assets/lang/I18N.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) 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 ff04f3bbaa..893fb275d1 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 @@ -267,7 +267,10 @@ private void onAccept() { }).executor(true); }; - if (factory instanceof OfflineAccountFactory && username != null && !USERNAME_CHECKER_PATTERN.matcher(username).matches()) { + if (factory instanceof OfflineAccountFactory && username != null && !USERNAME_CHECKER_PATTERN.matcher(username).matches() || username.length() > 16) { + System.out.println(username); + System.out.println("USERNAME LENGTH: " + username.length()); + System.out.println(username.length() > 16); JFXButton btnYes = new JFXButton(i18n("button.ok")); btnYes.getStyleClass().add("dialog-error"); btnYes.setOnAction(e -> doCreate.run()); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 09f9932cc8..4b2d9a1b02 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -124,7 +124,7 @@ account.methods.microsoft.purchase=Buy Minecraft 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=Using only English letters, numbers, and underscores is recommended +account.methods.offline.name.special_characters=Use only letters, numbers, and underscores (max 16 chars). account.methods.offline.name.invalid=It is recommended to use only English letters, numbers and underscores for the username, and the length should not exceed 16 characters.\n\ \n\ \ · Legitimate: HuangYu, huang_Yu, Huang_Yu_123;\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 4a7459a848..7511785331 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -131,7 +131,7 @@ account.methods.ban_query=查詢帳戶是否被封禁 account.methods.microsoft.snapshot=你正在使用第三方提供的 HMCL。請下載官方版本進行登入。 account.methods.microsoft.snapshot.website=官方網站 account.methods.offline=離線模式 -account.methods.offline.name.special_characters=建議使用英文字母、數字以及底線命名 +account.methods.offline.name.special_characters=建議使用英文字母、數字以及底線命名,且長度不超過 16 個字元。 account.methods.offline.name.invalid=遊戲使用者名稱建議僅使用英文字母、數字及底線,且長度不超過 16 個字元。\n\ \n\ \ · 一些有效的使用者名稱:HuangYu、huang_Yu、Huang_Yu_123;\n\ 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 b39b8064b4..e438cc5bdc 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -139,7 +139,7 @@ account.methods.ban_query=检测账户是否被封禁 account.methods.microsoft.snapshot=你正在使用第三方提供的 HMCL。请下载官方版本来登录微软账户。 account.methods.microsoft.snapshot.website=官方网站 account.methods.offline=离线模式 -account.methods.offline.name.special_characters=建议使用英文字符、数字以及下划线命名 +account.methods.offline.name.special_characters=建议使用英文字符、数字以及下划线命名,且长度不超过 16 个字符。 account.methods.offline.name.invalid=游戏用户名建议仅使用英文字母、数字及下划线,且长度不超过 16 个字符。\n\ \n\ \ · 一些合法用户名:HuangYu、huang_Yu、Huang_Yu_123;\n\ From 447583d07c584ec981eb88be0789c8bd4aa46709 Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Thu, 17 Jul 2025 14:31:17 +0800 Subject: [PATCH 08/16] Delete test code --- .../java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java | 3 --- 1 file changed, 3 deletions(-) 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 893fb275d1..11756f8bc6 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 @@ -268,9 +268,6 @@ private void onAccept() { }; if (factory instanceof OfflineAccountFactory && username != null && !USERNAME_CHECKER_PATTERN.matcher(username).matches() || username.length() > 16) { - System.out.println(username); - System.out.println("USERNAME LENGTH: " + username.length()); - System.out.println(username.length() > 16); JFXButton btnYes = new JFXButton(i18n("button.ok")); btnYes.getStyleClass().add("dialog-error"); btnYes.setOnAction(e -> doCreate.run()); From 052a950ed386d755f3020c4f85d4666abd484a11 Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Thu, 17 Jul 2025 14:47:32 +0800 Subject: [PATCH 09/16] Deleted testing asstes cleaner module --- .../shulker/assetscleaner/AssetsCleaner.java | 166 ------------------ 1 file changed, 166 deletions(-) delete mode 100644 HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java diff --git a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java b/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java deleted file mode 100644 index b2386b3ca4..0000000000 --- a/HMCLCore/src/main/java/neko/shulker/assetscleaner/AssetsCleaner.java +++ /dev/null @@ -1,166 +0,0 @@ -package neko.shulker.assetscleaner; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -import java.io.File; -import java.io.FileReader; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.Reader; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public final class AssetsCleaner { - - private AssetsCleaner() { - throw new UnsupportedOperationException(); - } - - private static List getIndexes(String versionsDirectory) { - List indexes = new ArrayList<>(); - File versionsDir = new File(versionsDirectory); - - // 遍历 versionsDirectory 中的所有文件夹 - if (versionsDir.exists() && versionsDir.isDirectory()) { - File[] versionFolders = versionsDir.listFiles(File::isDirectory); - if (versionFolders != null) { - for (File versionFolder : versionFolders) { - String versionName = versionFolder.getName(); - File jsonFile = new File(versionFolder, versionName + ".json"); - - if (jsonFile.exists() && jsonFile.isFile()) { - try (Reader reader = new FileReader(jsonFile)) { - // 解析 JSON 文件 - Gson gson = new Gson(); - Map versionData = gson.fromJson(reader, Map.class); - - // 提取 "assets" 的值 - Object assetsValue = versionData.get("assets"); - if (assetsValue instanceof String) { - String assets = (String) assetsValue; - indexes.add(assets); - } - } catch (IOException e) { - System.err.println("[AssetsCleaner]: Error reading JSON file: " + jsonFile); - e.printStackTrace(); - } - } - } - } - } - - return indexes; - } - - public static void clean(String repoDirectory) { - // 构造路径 - String versionsDirectory = Paths.get(repoDirectory, "versions").toString(); - String indexesDirectory = Paths.get(repoDirectory, "assets", "indexes").toString(); - String objectsDirectory = Paths.get(repoDirectory, "assets", "objects").toString(); - - // 获取 indexes - List requiredIndexes = getIndexes(versionsDirectory); - - // 用于存储所有 index 中 hash 键值的 Map - Map> hashMap = new HashMap<>(); - - try { - // 遍历 indexesDirectory 目录下的所有 JSON 文件 - File indexesDir = new File(indexesDirectory); - if (!indexesDir.exists() || !indexesDir.isDirectory()) { - System.err.println("[AssetsCleaner]: Indexes directory does not exist: " + indexesDir); - return; - } - - // 获取 indexesDirectory 中的所有 JSON 文件 - File[] indexFiles = indexesDir.listFiles((FilenameFilter) (dir, name) -> name.endsWith(".json")); - if (indexFiles != null) { - for (File indexFile : indexFiles) { - String indexFileName = indexFile.getName(); - String indexName = indexFileName.substring(0, indexFileName.lastIndexOf('.')); - - // 检查该 index 是否在 requiredIndexes 中 - if (!requiredIndexes.contains(indexName)) { - // 如果不在 requiredIndexes 中,则删除该 index 文件 - if (!indexFile.delete()) { - System.err.println("[AssetsCleaner]: Error deleting index file: " + indexFile); - } else { - System.out.println("[AssetsCleaner]: Deleted unnecessary index: " + indexFile); - } - continue; - } - - // 解析 JSON 文件 - try (Reader reader = new FileReader(indexFile)) { - Gson gson = new Gson(); - Map>> jsonData = gson.fromJson(reader, new TypeToken>>>() {}.getType()); - - // 提取 hash 的键值 - Map> objects = jsonData.get("objects"); - if (objects != null) { - for (Map.Entry> entry : objects.entrySet()) { - String filePath = entry.getKey(); - Map fileData = entry.getValue(); - String hash = (String) fileData.get("hash"); - if (hash != null && !hashMap.containsKey(hash)) { - hashMap.put(hash, fileData); - } - } - } - } catch (IOException e) { - System.err.println("[AssetsCleaner]: Error reading JSON file: " + indexFile); - e.printStackTrace(); - } - } - } - - // 输出 hashMap 中保存的所有 hash 值 - System.out.println("[AssetsCleaner]: 所有 hash 值:"); - for (String hash : hashMap.keySet()) { - System.out.println(hash); - } - - // 遍历目标处理目录文件 - File objectsDir = new File(objectsDirectory); - if (!objectsDir.exists() || !objectsDir.isDirectory()) { - System.err.println("[AssetsCleaner]: Objects directory does not exist: " + objectsDir); - return; - } - - // 递归遍历 objectsDirectory - traverseAndCleanDirectory(objectsDir, hashMap); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private static void traverseAndCleanDirectory(File directory, Map> hashMap) { - if (!directory.exists() || !directory.isDirectory()) { - return; - } - - File[] files = directory.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory()) { - traverseAndCleanDirectory(file, hashMap); - } else { - String fileName = file.getName(); - // 判断文件是否在 hashMap 中 - if (!hashMap.containsKey(fileName)) { - // 如果不在则删除 - if (!file.delete()) { - System.err.println("[AssetsCleaner]: Error deleting file: " + file); - } else { - System.out.println("[AssetsCleaner]: Deleted file: " + file); - } - } - } - } - } - } -} From f77e47e80f0f377ef25c031a385957690f66e866 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 28 Jul 2025 15:55:46 +0800 Subject: [PATCH 10/16] update --- HMCL/src/main/resources/assets/lang/I18N.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 2 +- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 4b2d9a1b02..6503800817 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -124,7 +124,7 @@ account.methods.microsoft.purchase=Buy Minecraft 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=Use only letters, numbers, and underscores (max 16 chars). +account.methods.offline.name.special_characters=Use only letters, numbers, and underscores (max 16 chars) account.methods.offline.name.invalid=It is recommended to use only English letters, numbers and underscores for the username, and the length should not exceed 16 characters.\n\ \n\ \ · Legitimate: HuangYu, huang_Yu, Huang_Yu_123;\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 7511785331..c7b3c14bd3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -131,7 +131,7 @@ account.methods.ban_query=查詢帳戶是否被封禁 account.methods.microsoft.snapshot=你正在使用第三方提供的 HMCL。請下載官方版本進行登入。 account.methods.microsoft.snapshot.website=官方網站 account.methods.offline=離線模式 -account.methods.offline.name.special_characters=建議使用英文字母、數字以及底線命名,且長度不超過 16 個字元。 +account.methods.offline.name.special_characters=建議使用英文字母、數字以及底線命名,且長度不超過 16 個字元 account.methods.offline.name.invalid=遊戲使用者名稱建議僅使用英文字母、數字及底線,且長度不超過 16 個字元。\n\ \n\ \ · 一些有效的使用者名稱:HuangYu、huang_Yu、Huang_Yu_123;\n\ 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 e438cc5bdc..1775f45114 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -139,7 +139,7 @@ account.methods.ban_query=检测账户是否被封禁 account.methods.microsoft.snapshot=你正在使用第三方提供的 HMCL。请下载官方版本来登录微软账户。 account.methods.microsoft.snapshot.website=官方网站 account.methods.offline=离线模式 -account.methods.offline.name.special_characters=建议使用英文字符、数字以及下划线命名,且长度不超过 16 个字符。 +account.methods.offline.name.special_characters=建议使用英文字符、数字以及下划线命名,且长度不超过 16 个字符 account.methods.offline.name.invalid=游戏用户名建议仅使用英文字母、数字及下划线,且长度不超过 16 个字符。\n\ \n\ \ · 一些合法用户名:HuangYu、huang_Yu、Huang_Yu_123;\n\ From 90558ebd0cd7207d5e592b26127cf8baa741d9f5 Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 28 Jul 2025 16:01:45 +0800 Subject: [PATCH 11/16] update --- .../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 11756f8bc6..9b4bd3f09c 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 @@ -267,7 +267,7 @@ private void onAccept() { }).executor(true); }; - if (factory instanceof OfflineAccountFactory && username != null && !USERNAME_CHECKER_PATTERN.matcher(username).matches() || username.length() > 16) { + if (factory instanceof OfflineAccountFactory && username != null && (!USERNAME_CHECKER_PATTERN.matcher(username).matches() || username.length() > 16)) { JFXButton btnYes = new JFXButton(i18n("button.ok")); btnYes.getStyleClass().add("dialog-error"); btnYes.setOnAction(e -> doCreate.run()); From dbfc67cbdf425b36cf8cdd73d3d4c8841a886ee0 Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Sat, 2 May 2026 23:58:13 +0800 Subject: [PATCH 12/16] FixSkinModel --- .../main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java | 8 ++++---- .../org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java index 208d6f57a8..f4122e4ece 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java @@ -58,14 +58,14 @@ public static int[] createFaces() { 5, 0, 4, 1, 0, 5, //P5,T0, P4,T1, P0,T5 5, 0, 0, 5, 1, 4, //P5,T0, P0,T5, P1,T4 // RIGHT - 0, 5, 4, 6, 6, 11, //P0,T4 ,P4,T3, P6,T8 - 0, 5, 6, 11, 2, 10, //P0,T4 ,P6,T8, P2,T9 + 5, 3, 1, 4, 3, 9, //P5,T6, P1,T5, P3,T10 + 5, 3, 3, 9, 7, 8, //P5,T6, P3,T10,P7,T11 // FRONT 1, 4, 0, 5, 2, 10, //P1,T5, P0,T4, P2,T9 1, 4, 2, 10, 3, 9, //P1,T5, P2,T9, P3,T10 // LEFT - 5, 3, 1, 4, 3, 9, //P5,T6, P1,T5, P3,T10 - 5, 3, 3, 9, 7, 8, //P5,T6, P3,T10,P7,T11 + 0, 5, 4, 6, 6, 11, //P0,T4 ,P4,T3, P6,T8 + 0, 5, 6, 11, 2, 10, //P0,T4 ,P6,T8, P2,T9 // BACK 4, 6, 5, 7, 7, 12, //P4,T6, P5,T7, P7,T12 4, 6, 7, 12, 6, 11, //P4,T6, P7,T12,P6,T11 diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java index 4e9e1b4b19..2f6caaabda 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java @@ -128,17 +128,18 @@ public void updateSkin(Image skin) { b.setTranslateY(-((height - 1) / 2.0 - p.getY()) * b.getHeight()); b.setTranslateZ(-(depth * length + thick) / 2.0); })); - // LEFT + // LEFT (左面,X-) —— 原来在 X+,改到 X- getChildren().add(new Face(skin, start_x + width_interval + depth_interval, start_y + depth_interval, depth, height, interval, false, false, () -> new Box(thick, length, length), (b, p) -> { - b.setTranslateX((width * length + thick) / 2.0); + b.setTranslateX(-(width * length + thick) / 2.0); // ← 改为负值 b.setTranslateY(-((height - 1) / 2.0 - p.getY()) * b.getHeight()); b.setTranslateZ(((depth - 1) / 2.0 - p.getX()) * b.getDepth()); })); - // RIGHT + + // RIGHT (右面,X+) —— 原来在 X-,改到 X+ getChildren().add(new Face(skin, start_x, start_y + depth_interval, depth, height, interval, true, false, () -> new Box(thick, length, length), (b, p) -> { - b.setTranslateX(-(width * length + thick) / 2.0); + b.setTranslateX((width * length + thick) / 2.0); // ← 改为正值 b.setTranslateY(-((height - 1) / 2.0 - p.getY()) * b.getHeight()); b.setTranslateZ(((depth - 1) / 2.0 - p.getX()) * b.getDepth()); })); From 35615a574f1601829fcd904bbc98ac73e4414de7 Mon Sep 17 00:00:00 2001 From: ShulkerSakura <50770360+ShulkerSakura@users.noreply.github.com> Date: Sun, 3 May 2026 12:06:55 +0800 Subject: [PATCH 13/16] Refactor comments --- .../org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java index 2f6caaabda..8990c4d947 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinMultipleCubes.java @@ -128,18 +128,18 @@ public void updateSkin(Image skin) { b.setTranslateY(-((height - 1) / 2.0 - p.getY()) * b.getHeight()); b.setTranslateZ(-(depth * length + thick) / 2.0); })); - // LEFT (左面,X-) —— 原来在 X+,改到 X- + // LEFT getChildren().add(new Face(skin, start_x + width_interval + depth_interval, start_y + depth_interval, depth, height, interval, false, false, () -> new Box(thick, length, length), (b, p) -> { - b.setTranslateX(-(width * length + thick) / 2.0); // ← 改为负值 + b.setTranslateX(-(width * length + thick) / 2.0); b.setTranslateY(-((height - 1) / 2.0 - p.getY()) * b.getHeight()); b.setTranslateZ(((depth - 1) / 2.0 - p.getX()) * b.getDepth()); })); - // RIGHT (右面,X+) —— 原来在 X-,改到 X+ + // RIGHT getChildren().add(new Face(skin, start_x, start_y + depth_interval, depth, height, interval, true, false, () -> new Box(thick, length, length), (b, p) -> { - b.setTranslateX((width * length + thick) / 2.0); // ← 改为正值 + b.setTranslateX((width * length + thick) / 2.0); b.setTranslateY(-((height - 1) / 2.0 - p.getY()) * b.getHeight()); b.setTranslateZ(((depth - 1) / 2.0 - p.getX()) * b.getDepth()); })); From f230bc4d40a6dbc32deb4c0b15553c589fcc25fd Mon Sep 17 00:00:00 2001 From: ShulkerSakura <50770360+ShulkerSakura@users.noreply.github.com> Date: Sun, 3 May 2026 17:03:03 +0800 Subject: [PATCH 14/16] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java index f4122e4ece..ffbdb3271d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/skin/SkinCube.java @@ -58,8 +58,8 @@ public static int[] createFaces() { 5, 0, 4, 1, 0, 5, //P5,T0, P4,T1, P0,T5 5, 0, 0, 5, 1, 4, //P5,T0, P0,T5, P1,T4 // RIGHT - 5, 3, 1, 4, 3, 9, //P5,T6, P1,T5, P3,T10 - 5, 3, 3, 9, 7, 8, //P5,T6, P3,T10,P7,T11 + 5, 3, 1, 4, 3, 9, //P5,T3, P1,T4, P3,T9 + 5, 3, 3, 9, 7, 8, //P5,T3, P3,T9, P7,T8 // FRONT 1, 4, 0, 5, 2, 10, //P1,T5, P0,T4, P2,T9 1, 4, 2, 10, 3, 9, //P1,T5, P2,T9, P3,T10 From cafdd0a8c7bd57a112a9fe819dfc47fcdd5f7a20 Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Tue, 5 May 2026 22:21:36 +0800 Subject: [PATCH 15/16] AddedScamNotification --- .../org/jackhuang/hmcl/ui/Controllers.java | 29 +++++++++---------- .../resources/assets/lang/I18N.properties | 2 +- .../resources/assets/lang/I18N_ar.properties | 2 +- .../resources/assets/lang/I18N_es.properties | 2 +- .../resources/assets/lang/I18N_ja.properties | 2 +- .../resources/assets/lang/I18N_ru.properties | 2 +- .../resources/assets/lang/I18N_uk.properties | 2 +- .../resources/assets/lang/I18N_zh.properties | 2 +- .../assets/lang/I18N_zh_CN.properties | 2 +- 9 files changed, 21 insertions(+), 24 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 f68bedac09..70508123c2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -443,22 +443,19 @@ public static void initialize(Stage stage) { .build()); } - if (globalConfig().getAgreementVersion() < 1) { - JFXDialogLayout agreementPane = new JFXDialogLayout(); - agreementPane.setHeading(new Label(i18n("launcher.agreement"))); - agreementPane.setBody(new Label(i18n("launcher.agreement.hint"))); - JFXHyperlink agreementLink = new JFXHyperlink(i18n("launcher.agreement")); - agreementLink.setExternalLink(Metadata.EULA_URL); - JFXButton yesButton = new JFXButton(i18n("launcher.agreement.accept")); - yesButton.getStyleClass().add("dialog-accept"); - yesButton.setOnAction(e -> { - globalConfig().setAgreementVersion(1); - agreementPane.fireEvent(new DialogCloseEvent()); - }); - JFXButton noButton = new JFXButton(i18n("launcher.agreement.decline")); - noButton.getStyleClass().add("dialog-cancel"); - noButton.setOnAction(e -> javafx.application.Platform.exit()); - agreementPane.setActions(agreementLink, yesButton, noButton); + if (globalConfig().getAgreementVersion() < 2 ) { + MessageDialogPane agreementPane = new MessageDialogPane.Builder( + i18n("launcher.agreement.hint"), + i18n("launcher.agreement"), + MessageDialogPane.MessageType.INFO + ) + .addHyperLink(i18n("launcher.agreement"), Metadata.EULA_URL) + .addAction(i18n("launcher.agreement.accept"), () -> { + globalConfig().setAgreementVersion(2); + }) + .addCancel(i18n("launcher.agreement.decline"), Platform::exit) + .build(); + Controllers.dialog(agreementPane); } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 731eaee788..52620f4c4e 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -851,7 +851,7 @@ launcher=Launcher launcher.agreement=ToS and EULA launcher.agreement.accept=Accept launcher.agreement.decline=Decline -launcher.agreement.hint=You must agree to the EULA to use this software. +launcher.agreement.hint=You must agree to the EULA to use this software.\nHMCL is free and open-source software and has never authorized any third party to sell it.\nIf you paid to obtain this software, we recommend requesting a refund from the relevant platform and reporting the seller to avoid being scammed. launcher.april_fools.switch_lzh=HMCL Launcher now supports Classical Chinese, do you want to switch to Classical Chinese mode?\nYou can switch back to English in "置設 → 貫用 → 文". launcher.april_fools.switch_lzh.confirm=Confirm switching to Classical Chinese mode?\nClick "OK" to exit HMCL and restart it in Classical Chinese mode; click "Cancel" to keep the current language and enter HMCL homepage. launcher.background=Background Image diff --git a/HMCL/src/main/resources/assets/lang/I18N_ar.properties b/HMCL/src/main/resources/assets/lang/I18N_ar.properties index 9bdbda0d82..ce3541eca9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ar.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ar.properties @@ -830,7 +830,7 @@ launcher=المشغّل launcher.agreement=الشروط واتفاقية الترخيص launcher.agreement.accept=قبول launcher.agreement.decline=رفض -launcher.agreement.hint=يجب الموافقة على اتفاقية الترخيص لاستخدام هذا البرنامج. +launcher.agreement.hint=يجب الموافقة على اتفاقية الترخيص لاستخدام هذا البرنامج.\nHMCL برنامج مجاني مفتوح المصدر، لم يُصرح لأي طرف ثالث ببيعه.\nإذا دفعت مقابل الحصول على هذا البرنامج، يُنصح بطلب استرداد الأموال والإبلاغ عن المنصة لتجنب الاحتيال. launcher.background=صورة الخلفية launcher.background.choose=اختر صورة الخلفية launcher.background.classic=كلاسيكي diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 703802d89c..646a0fc097 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -791,7 +791,7 @@ launcher=Launcher launcher.agreement=Términos de servicio y EULA launcher.agreement.accept=Aceptar launcher.agreement.decline=Rechazar -launcher.agreement.hint=Debe aceptar el EULA para utilizar este software. +launcher.agreement.hint=Debe aceptar el EULA para utilizar este software.\nHMCL es software libre y gratuito, nunca se ha autorizado a terceros su venta.\nSi pagó por obtener este software, se recomienda solicitar el reembolso e informar a la plataforma para evitar fraudes. launcher.background=Imagen de fondo launcher.background.choose=Elige una imagen de fondo launcher.background.classic=Clásico diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 6d0a58eb07..cc5eb473e8 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -517,7 +517,7 @@ launcher=ランチャー launcher.agreement=EULA launcher.agreement.accept=同意します launcher.agreement.decline=同意しません -launcher.agreement.hint=このソフトウェアを使用するには、EULAに同意する必要があります。 +launcher.agreement.hint=このソフトウェアを使用するには、EULAに同意する必要があります。\nHMCL は無料のオープンソースソフトウェアであり、第三者への販売を許可したことはありません。\n本ソフトウェアの入手に費用を支払った場合は、関連プラットフォームへ返金申請と通報を行い、詐欺にご注意ください。 launcher.background=背景画像 launcher.background.classic=クラシック launcher.background.choose=背景画像ファイルを選択してください diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 3c5e63b9de..c9f6f5bfdb 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -784,7 +784,7 @@ launcher=Лаунчер launcher.agreement=Пользовательское соглашение launcher.agreement.accept=Принять launcher.agreement.decline=Отклонить -launcher.agreement.hint=Нужно принять пользовательское соглашение, чтобы использовать это программное обеспечение. +launcher.agreement.hint=Нужно принять пользовательское соглашение, чтобы использовать это программное обеспечение.\nHMCL — бесплатное ПО с открытым исходным кодом, никогда не разрешалось третьим лицам на продажу.\nЕсли вы заплатили за получение этого ПО, рекомендуем обратиться за возвратом средств и пожаловаться на платформу, чтобы избежать мошенничества. launcher.background=Фоновое изображение launcher.background.choose=Выберите фоновое изображение launcher.background.classic=Классическое diff --git a/HMCL/src/main/resources/assets/lang/I18N_uk.properties b/HMCL/src/main/resources/assets/lang/I18N_uk.properties index c1da6e8423..3619c83303 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_uk.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_uk.properties @@ -732,7 +732,7 @@ launcher=Лаунчер launcher.agreement=ToS та EULA launcher.agreement.accept=Прийняти launcher.agreement.decline=Відхилити -launcher.agreement.hint=Ви повинні погодитися з EULA, щоб використовувати це програмне забезпечення. +launcher.agreement.hint=Ви повинні погодитися з EULA, щоб використовувати це програмне забезпечення.\nHMCL — безкоштовне програмне забезпечення з відкритим кодом, ніколи не дозволялося третім особам на продаж.\nЯкщо ви заплатили за отримання цього ПЗ, радимо подати заявку на повернення коштів та поскаржитися на платформу, щоб уникнути шахрайства. launcher.background=Фонове зображення launcher.background.choose=Вибрати фонове зображення launcher.background.classic=Класичний diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 90f2157ece..f16fc09188 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -657,7 +657,7 @@ launcher=啟動器 launcher.agreement=使用者協議與免責宣告 launcher.agreement.accept=同意 launcher.agreement.decline=拒絕 -launcher.agreement.hint=同意本軟體的使用者協議與免責宣告以使用本軟體。 +launcher.agreement.hint=同意本軟體的使用者協議與免責宣告以使用本軟體。\nHMCL 是免費開源軟體,從未授權任何第三方進行銷售。\n如您為取得本軟體支付了費用,建議向相關平台申請退款並檢舉,以防受騙。 launcher.april_fools.switch_lzh=HMCL 啟動器現已支援文言文,我們誠邀你參與體驗。是否要將介面語言切換至中文 (文言)?\n在切換語言後,你可以在「置設 → 貫用 → 文」中將語言切換回中文 (繁體)。 launcher.april_fools.switch_lzh.confirm=確認切換語言?\n點擊「確定」後 HMCL 將自動重新啟動並將介面語言切換至中文 (文言);點擊「取消」將繼續使用中文 (繁體) 進入 HMCL 主頁。 launcher.background=背景圖片 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 1180eddfa1..b55bb73d66 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -662,7 +662,7 @@ launcher=启动器 launcher.agreement=用户协议与免责声明 launcher.agreement.accept=同意 launcher.agreement.decline=拒绝 -launcher.agreement.hint=同意本软件的用户协议与免责声明以使用本软件。 +launcher.agreement.hint=同意本软件的用户协议与免责声明以使用本软件。\nHMCL 是免费开源软件,从未授权任何第三方进行销售。\n如您为获取本软件支付了费用,建议向相关平台申请退款并举报,谨防受骗。 launcher.april_fools.switch_lzh=HMCL 启动器现已支持文言文,我们诚邀你参与体验。是否要将界面语言切换至中文 (文言)?\n在切换语言后,你可以在“置設 → 貫用 → 文”中将语言切换回中文 (简体)。 launcher.april_fools.switch_lzh.confirm=确认切换语言?\n点击“确定”后 HMCL 将自动重启并将界面语言切换至中文 (文言);点击“取消”将继续使用中文 (简体) 进入 HMCL 主页。 launcher.background=背景图片 From b87a6f333e37c896cb984e37c03346645ef05b2e Mon Sep 17 00:00:00 2001 From: ShulkerSakura <2531493755@qq.com> Date: Tue, 5 May 2026 22:41:51 +0800 Subject: [PATCH 16/16] Check Code --- HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java | 2 -- 1 file changed, 2 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 70508123c2..d60d7f4d07 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXDialogLayout; import com.jfoenix.validation.base.ValidatorBase; import javafx.animation.KeyFrame; import javafx.animation.KeyValue; @@ -33,7 +32,6 @@ import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.ButtonBase; -import javafx.scene.control.Label; import javafx.scene.layout.Region; import javafx.scene.paint.Color; import javafx.stage.Screen;