Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5be81d6
Prompt user to switch working directory if unexpected content found
deepsleep-v3 Jan 18, 2026
92ea64e
Refactor path construction in ROOT_FOLDER check
deepsleep-v3 Jan 18, 2026
00bf5a2
Handle user response in working directory switch alert
deepsleep-v3 Jan 18, 2026
a4e66d7
fix(ui): 修复Alert在非JavaFX线程中使用的线程安全问题
deepsleep-v3 Jan 19, 2026
37a03fc
fix(JavaDoc): 修复了一些文档中的语法错误和文件格式应当保持大写
deepsleep-v3 Jan 19, 2026
bcd4a87
Moved "Switch Working Directory".
deepsleep-v3 Jan 19, 2026
e238c11
fix(bug):填补了未填充的大括号
deepsleep-v3 Jan 19, 2026
f0329a3
fix:格式
deepsleep-v3 Jan 19, 2026
5becbaf
修复了额外导入的同包下内容
deepsleep-v3 Jan 19, 2026
612aa8f
fix:修复了本人发现的问题及PR#5260所提到的一些批判
deepsleep-v3 Jan 19, 2026
1d52a58
add+fix: 修正了格式,并添加亚洲语言(zh-Hant、zh-CN、ja-JP)的翻译。
deepsleep-v3 Jan 19, 2026
95d2876
UPDATE
CiiLu Jan 19, 2026
cd090e7
Update HMCL/src/main/resources/assets/lang/I18N.properties
deepsleep-v3 Jan 20, 2026
5d2ff48
Update HMCL/src/main/resources/assets/lang/I18N.properties
deepsleep-v3 Jan 20, 2026
9c5df2f
Update HMCL/src/main/resources/assets/lang/I18N.properties
deepsleep-v3 Jan 20, 2026
1619480
Update HMCL/src/main/resources/assets/lang/I18N_zh.properties
deepsleep-v3 Jan 20, 2026
84b1969
Update HMCL/src/main/resources/assets/lang/I18N_zh.properties
deepsleep-v3 Jan 20, 2026
e35dc82
Update HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties
deepsleep-v3 Jan 20, 2026
31cc0c4
Update HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties
deepsleep-v3 Jan 20, 2026
9c5440d
Merge pull request #1 from CiiLu/deepsleep-v3/main
deepsleep-v3 Jan 20, 2026
c6e33a9
fallback ja_JP
deepsleep-v3 Jan 20, 2026
6bab585
Merge branch 'main' of https://github.com/deepsleep-v3/HMCL
deepsleep-v3 Jan 20, 2026
294299d
Merge branch 'HMCL-dev:main' into main
deepsleep-v3 Jan 20, 2026
d69676b
fixed format
deepsleep-v3 Jan 20, 2026
06c0cc1
Merge branch 'main' of https://github.com/deepsleep-v3/HMCL
deepsleep-v3 Jan 20, 2026
9fea525
一些语法错误(Part Ⅰ)
deepsleep-v3 Jan 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,27 @@
import org.jackhuang.hmcl.auth.AuthInfo;
import org.jackhuang.hmcl.launch.DefaultLauncher;
import org.jackhuang.hmcl.launch.ProcessListener;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
import org.jackhuang.hmcl.util.i18n.LocaleUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.platform.ManagedProcess;
import org.jackhuang.hmcl.util.versioning.GameVersionNumber;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;

import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;

/**
Expand Down Expand Up @@ -62,8 +72,16 @@ protected Map<String, String> getConfigurations() {
private void generateOptionsTxt() {
if (config().isDisableAutoGameOptions())
return;

Path runDir = repository.getRunDirectory(version.getId());
HMCLGameRepository repository = (HMCLGameRepository) this.repository;
if (repository.getGameDirectoryType(version.getId()) == GameDirectoryType.ROOT_FOLDER) {
Path versionRoot = repository.getVersionRoot(version.getId());
String[] subdirs = {"resourcepacks", "saves", "mods", "shaderpacks", "crash-report"};

if (Arrays.stream(subdirs).anyMatch(dir -> Files.exists(versionRoot.resolve(dir)))) {
runDir = switchWorkingDirectory(repository, version);
}
}
Path optionsFile = runDir.resolve("options.txt");
Path configFolder = runDir.resolve("config");

Expand All @@ -88,7 +106,7 @@ private void generateOptionsTxt() {
* 1.11 ~ 1.12 : zh_cn works fine, zh_CN will display Chinese but the language setting will incorrectly show English as selected
* 1.13+ : zh_cn works fine, zh_CN will automatically switch to English
*/
GameVersionNumber gameVersion = GameVersionNumber.asGameVersion(repository.getGameVersion(version));
GameVersionNumber gameVersion = GameVersionNumber.asGameVersion(this.repository.getGameVersion(version));
if (gameVersion.compareTo("1.1") < 0)
return;

Expand All @@ -107,6 +125,29 @@ private void generateOptionsTxt() {
}
}

private Path switchWorkingDirectory(HMCLGameRepository repository, Version version) {
CompletableFuture<Path> future = new CompletableFuture<>();

var dialog = new MessageDialogPane.Builder(
i18n("launcher.info.switch_working_directory.content", File.separatorChar, version.getId()),
i18n("launcher.info.switch_working_directory.title"), MessageDialogPane.MessageType.QUESTION)
.ok(() -> {
repository.getVersionSetting(version.getId()).setGameDirType(GameDirectoryType.VERSION_FOLDER);
future.complete(repository.getVersionRoot(version.getId()));
}).addCancel(() -> {
future.complete(repository.getBaseDirectory());
}).addCancel(i18n("Dialog.this_launch_only.button"), () -> {
future.complete(repository.getVersionRoot(version.getId()));
}).build();
FXUtils.runInFX(() -> Controllers.dialog(dialog));

try {
return future.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private static String normalizedLanguageTag(Locale locale, GameVersionNumber gameVersion) {
String region = locale.getCountry();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ private void loadLocalVersionSetting(String id) {
VersionSetting versionSetting = JsonUtils.fromJsonFile(file, VersionSetting.class);
initLocalVersionSetting(id, versionSetting);
} catch (Exception ex) {
// If [JsonParseException], [IOException] or [NullPointerException] happens, the json file is malformed and needed to be recreated.
// If [JsonParseException], [IOException] or [NullPointerException] happens, the JSON file is malformed and needed to be recreated.
initLocalVersionSetting(id, new VersionSetting());
}
}
Expand Down Expand Up @@ -231,7 +231,7 @@ private VersionSetting initLocalVersionSetting(String id, VersionSetting vs) {
* Get the version setting for version id.
*
* @param id version id
* @return corresponding version setting, null if the version has no its own version setting.
* @return corresponding version setting, null if the version does not have its own version setting.
*/
@Nullable
public VersionSetting getLocalVersionSetting(String id) {
Expand Down
6 changes: 6 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N.properties
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,8 @@ download.speed.byte_per_second=%d B/s
download.speed.kibibyte_per_second=%.1f KiB/s
download.speed.megabyte_per_second=%.1f MiB/s

Dialog.this_launch_only.button=This launch only

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 terminating that process.\n\
Expand Down Expand Up @@ -829,6 +831,7 @@ 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.


launcher=Launcher
launcher.agreement=ToS and EULA
launcher.agreement.accept=Accept
Expand All @@ -852,6 +855,9 @@ launcher.crash=Hello Minecraft! Launcher has encountered a fatal error! Please c
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 <a href="https://bell-sw.com/pages/downloads/#downloads">here</a>.
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.
launcher.info.switch_working_directory.title=Instance files detected
# %1$s = java.io.File.separator, %2$s = version root (Don't ends with java.io.File.separator)
launcher.info.switch_working_directory.content=Existing game files were detected in ".minecraft%1$sversions%1$s%2$s", but the Working Directory is currently set to "Default".\n\nTo use these files, the setting in "Game Settings → Working Directory" should be "Isolated". Would you like to switch to Isolated mode?

libraries.download=Downloading Libraries

Expand Down
5 changes: 5 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N_zh.properties
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ download.speed.byte_per_second=%d B/s
download.speed.kibibyte_per_second=%.1f KiB/s
download.speed.megabyte_per_second=%.1f MiB/s

Dialog.this_launch_only.button=僅限本次啟動

exception.access_denied=無法存取檔案「%s」。因為 HMCL 沒有對該檔案的訪問權限,或者該檔案已被其他程式開啟。\n\
請你檢查目前作業系統帳戶是否能訪存取檔案,比如非管理員使用者可能不能訪問其他帳戶的個人目錄內的檔案。\n\
對於 Windows 使用者,你還可以嘗試透過資源監視器查看是否有程式占用了該檔案。如果是,你可以關閉占用此檔案的程式,或者重啟電腦再試。
Expand Down Expand Up @@ -651,6 +653,9 @@ launcher.crash=Hello Minecraft! Launcher 遇到了無法處理的錯誤。請複
launcher.crash.java_internal_error=Hello Minecraft! Launcher 由於目前 Java 損壞而無法繼續執行。請移除目前 Java,點擊 <a href="https://bell-sw.com/pages/downloads/#downloads">此處</a> 安裝合適的 Java 版本。
launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher 遇到了無法處理的錯誤。已偵測到你的啟動器不是最新版本,請更新後重試!
launcher.update_java=請更新你的 Java
launcher.info.switch_working_directory.title=偵測到實例檔案
# %1$s = java.io.File.separator, %2$s = version root (Don't ends with java.io.File.separator)
launcher.info.switch_working_directory.content=在「.minecraft%1$sversions%1$s%2$s」中偵測到既有遊戲檔案,但目前執行路徑設定為「預設」。\n\n要使用這些檔案,請在「(全域/實例特定) 遊戲設定 → 執行路徑」中選取「各實例獨立」。你是否要切換到「各實例獨立」模式?

libraries.download=下載依賴庫

Expand Down
5 changes: 5 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@ download.speed.byte_per_second=%d B/s
download.speed.kibibyte_per_second=%.1f KiB/s
download.speed.megabyte_per_second=%.1f MiB/s

Dialog.this_launch_only.button=仅本次启动

exception.access_denied=无法访问文件“%s”。HMCL 没有对该文件的访问权限,或者该文件已被其他程序打开。\n\
请你检查当前操作系统账户是否能访问该文件,比如非管理员用户可能无法访问其他账户的个人文件夹内的文件。\n\
对于 Windows 用户,你还可以尝试通过资源监视器查看是否有程序占用了该文件。如果是,请关闭占用该文件的程序,或者重启电脑再试。\n\
Expand Down Expand Up @@ -655,6 +657,9 @@ launcher.crash=Hello Minecraft! Launcher 遇到了无法处理的错误。请复
launcher.crash.java_internal_error=Hello Minecraft! Launcher 由于当前 Java 损坏而无法继续运行。请卸载当前 Java,点击 <a href="https://bell-sw.com/pages/downloads/#downloads">此处</a> 安装合适的 Java 版本。
launcher.crash.hmcl_out_dated=Hello Minecraft! Launcher 遇到了无法处理的错误。已检测到你的启动器不是最新版本,请更新后再试。
launcher.update_java=请更新你的 Java。\n你可以访问 https://docs.hmcl.net/help.html 页面寻求帮助。
launcher.info.switch_working_directory.title=检测到实例文件
# %1$s = java.io.File.separator, %2$s = version root (Don't ends with java.io.File.separator)
launcher.info.switch_working_directory.content=在“.minecraft%1$sversions%1$s%2$s”中检测到既有游戏文件,但目前“版本隔离”设置为“默认”。\n\n要使用这些文件,请在“(全局/实例特定) 游戏设置 → 版本隔离”中选择“各实例独立”。\n\n你是否要切换到“各实例独立”模式?

libraries.download=下载依赖库

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ public JavaRuntime getJava() {
}

/**
* Will shown in the left bottom corner of the main menu of Minecraft.
* null if use the id of launch version.
* Will be shown in the left bottom corner of the main menu of Minecraft.
* null if the id of launch version.
*/
public String getVersionName() {
return versionName;
}

/**
* Will shown in the left bottom corner of the main menu of Minecraft.
* Will be shown in the left bottom corner of the main menu of Minecraft.
* null if use Version.versionType.
*/
public String getVersionType() {
Expand Down Expand Up @@ -208,7 +208,7 @@ public int getProxyPort() {
}

/**
* The user name of the proxy, optional.
* The username of the proxy, optional.
*/
public String getProxyUser() {
return proxyUser;
Expand Down