Skip to content

重构启动器配置模型#6122

Open
Glavo wants to merge 519 commits into
HMCL-dev:mainfrom
Glavo:instance-setting2
Open

重构启动器配置模型#6122
Glavo wants to merge 519 commits into
HMCL-dev:mainfrom
Glavo:instance-setting2

Conversation

@Glavo

@Glavo Glavo commented May 18, 2026

Copy link
Copy Markdown
Member

No description provided.

@3gf8jv4dv

This comment was marked as resolved.

@3gf8jv4dv

This comment was marked as resolved.

@Glavo Glavo force-pushed the instance-setting2 branch from fb4dc52 to 17fbe26 Compare May 18, 2026 12:40
@Glavo Glavo linked an issue May 22, 2026 that may be closed by this pull request
Glavo added 26 commits May 27, 2026 20:36
Comment thread HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N.properties
Comment thread HMCL/src/main/resources/assets/lang/I18N.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N.properties Outdated
@Glavo

Glavo commented Jun 13, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the configuration and settings management of HMCL by replacing the legacy Config and ConfigHolder classes with a modular settings architecture. Configuration domains such as launcher settings, user settings, game directories, presets, accounts, and authlib-injector servers are now persisted in separate, detached JSON files managed by SettingsManager. Additionally, the PR introduces robust migration utilities for legacy configuration formats. The code review identified three critical issues: a compilation error in LineComponent due to calling protected Region methods on container, a potential null pointer or logic bug in HMCLGameRepository when retrieving parent game settings, and a potential unhandled UnsupportedOperationException in Launcher when retrieving file owners on unsupported filesystems.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +129 to +130
double horizontalInsets = container.snappedLeftInset() + container.snappedRightInset();
double verticalInsets = container.snappedTopInset() + container.snappedBottomInset();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

LineComponent 中,container 是一个 HBox 实例。由于 LineComponent 位于 org.jackhuang.hmcl.ui.construct 包中,而 Region.snappedLeftInset() 等方法在 javafx.scene.layout.Region 中是 protected 的,且 LineComponent 并不是 HBox 的子类,因此在非同包下无法通过 container 引用直接调用这些 protected 方法。这会导致编译错误(例如:snappedLeftInset() has protected access in Region)。

建议使用公开的 container.getInsets().getLeft() 等方法来代替,以避免编译失败。

Suggested change
double horizontalInsets = container.snappedLeftInset() + container.snappedRightInset();
double verticalInsets = container.snappedTopInset() + container.snappedBottomInset();
double horizontalInsets = container.getInsets().getLeft() + container.getInsets().getRight();
double verticalInsets = container.getInsets().getTop() + container.getInsets().getBottom();

Comment on lines +282 to +283
GameSettings.Preset profilePreset = SettingsManager.getGameSettings(profile.getLegacyGameSettings());
if (profilePreset != null && profilePreset.defaultIsolationTypeProperty().getValue() == DefaultIsolationType.ALWAYS) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

此处使用 SettingsManager.getGameSettings(profile.getLegacyGameSettings()) 来获取配置预设。如果当前游戏文件夹(Profile)没有关联特定的旧版游戏设置(即 profile.getLegacyGameSettings() 返回 null),则 profilePreset 将为 null。这会导致即使全局默认预设启用了“始终隔离(ALWAYS)”,也无法为该实例应用隔离设置。

建议使用已有的 getParentGameSettings(null) 方法,它会在 profile.getLegacyGameSettings()null 时自动回退到默认预设,从而保证逻辑的正确性。

Suggested change
GameSettings.Preset profilePreset = SettingsManager.getGameSettings(profile.getLegacyGameSettings());
if (profilePreset != null && profilePreset.defaultIsolationTypeProperty().getValue() == DefaultIsolationType.ALWAYS) {
GameSettings.Preset profilePreset = getParentGameSettings(null);
if (profilePreset.defaultIsolationTypeProperty().getValue() == DefaultIsolationType.ALWAYS) {

Comment on lines 294 to 299
try {
owner = Files.getOwner(ConfigHolder.configLocation()).getName();
owner = Files.getOwner(configDirectory).getName();
} catch (IOException ioe) {
LOG.warning("Failed to get file owner", ioe);
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Files.getOwner(configDirectory) 在某些不支持文件所有者属性的文件系统(如 FAT32、某些网盘同步目录或特定的内存文件系统)上运行时,会抛出 UnsupportedOperationException。由于当前只捕获了 IOException,这可能会导致程序在这些环境下意外崩溃。

建议同时捕获 UnsupportedOperationException,以提高程序的健壮性。

Suggested change
try {
owner = Files.getOwner(ConfigHolder.configLocation()).getName();
owner = Files.getOwner(configDirectory).getName();
} catch (IOException ioe) {
LOG.warning("Failed to get file owner", ioe);
return;
}
try {
owner = Files.getOwner(configDirectory).getName();
} catch (IOException | UnsupportedOperationException ioe) {
LOG.warning("Failed to get file owner", ioe);
return;
}

settings.game.dimension=游戏窗口分辨率
settings.game.exploration=浏览
settings.game.fullscreen=全屏
settings.game.inherit_global=当前继承游戏设置预设。点击后改为实例特定设置。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
settings.game.inherit_global=当前继承游戏设置预设。点击后改为实例特定设置
settings.game.inherit_global=当前继承游戏设置预设。点击后使用实例特定设置

settings.game.working_directory.hint=在「執行路徑」選項中選取「各實例獨立」使目前實例獨立存放設定、世界、模組等資料。使用模組時建議開啟此選項以避免不同實例模組衝突。修改此選項後需自行移動世界等檔案。

settings.icon=遊戲圖示
settings.game_directories.read_only=遊戲資料夾檔案是由更高版本的 HMCL 儲存的,目前版本的 HMCL 無法新增遊戲資料夾。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
settings.game_directories.read_only=遊戲資料夾檔案是由更高版本的 HMCL 儲存的,目前版本的 HMCL 無法新增遊戲資料夾
settings.game_directories.read_only=遊戲目錄設定檔是由更高版本的 HMCL 儲存的,目前版本的 HMCL 無法新增遊戲目錄

\ · Enter any GC arguments in "JVM Arguments", and the G1 argument of the default arguments will be disabled.\n\
\ · Enable "Do not add default JVM arguments" to launch the game without adding default arguments.
settings.advanced.jvm_memory.deprecated=Deprecated JVM Memory Options
settings.advanced.jvm_memory.deprecated.subtitle=These options are kept only for compatibility with older versions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
settings.advanced.jvm_memory.deprecated.subtitle=These options are kept only for compatibility with older versions
settings.advanced.jvm_memory.deprecated.subtitle=These options are kept only for compatibility with older versions of HMCL

settings.game.copy_global.copy_all.confirm=Are you sure you want to overwrite the current instance settings? This action cannot be undone!
settings.game.current=Game
settings.game.default_isolation=Default Isolation Strategy
settings.game.default_isolation.subtitle=Automatically enable version isolation for eligible instances when installing a new instance.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
settings.game.default_isolation.subtitle=Automatically enable version isolation for eligible instances when installing a new instance.
settings.game.default_isolation.subtitle=Automatically enable instance isolation for eligible instances when installing a new instance.

settings.game.default_isolation=Default Isolation Strategy
settings.game.default_isolation.subtitle=Automatically enable version isolation for eligible instances when installing a new instance.
settings.game.default_isolation.always=Isolate All Instances
settings.game.default_isolation.always.desc=Automatically enable version isolation for all new installations

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
settings.game.default_isolation.always.desc=Automatically enable version isolation for all new installations
settings.game.default_isolation.always.desc=Automatically enable instance isolation for all new installations

settings.game.default_isolation.modded=Isolate Instances of Installable Mods
settings.game.default_isolation.modded.desc=Automatically enable instance isolation for installable module instances
settings.game.default_isolation.never=Do not isolate instances
settings.game.default_isolation.never.desc=Do not automatically enable version isolation for new installations

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
settings.game.default_isolation.never.desc=Do not automatically enable version isolation for new installations
settings.game.default_isolation.never.desc=Do not automatically enable instance isolation for new installations

settings.game.quick_play.subtitle=Enter a server or world directly after launching the game
settings.game.running_directory=Game Working Directory
settings.game.running_directory.subtitle=Leave empty to use the default game directory.
settings.game.running_directory.subtitle.instance=When version isolation is enabled, leave empty to use the instance directory; otherwise the global working directory is inherited.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
settings.game.running_directory.subtitle.instance=When version isolation is enabled, leave empty to use the instance directory; otherwise the global working directory is inherited.
settings.game.running_directory.subtitle.instance=When instance isolation is enabled, leave empty to use the instance directory; otherwise the global working directory is inherited.

settings.game.dimension=遊戲介面解析度大小
settings.game.exploration=瀏覽
settings.game.fullscreen=全螢幕
settings.game.inherit_global=目前繼承遊戲設定預設。點擊後改為實例特定設定。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
settings.game.inherit_global=目前繼承遊戲設定預設。點擊後改為實例特定設定
settings.game.inherit_global=目前繼承遊戲設定預設。點擊後使用實例特定設定

@3gf8jv4dv

Copy link
Copy Markdown
Contributor

英文里,这个实例隔离策略看不清选了什么。

Image

@3gf8jv4dv

Copy link
Copy Markdown
Contributor

预设名称似乎允许重复。要不在重命名的地方检查一下已有的预设名,免得混淆。

@3gf8jv4dv

Copy link
Copy Markdown
Contributor

自定义命令 > 包装命令,在英文下显示不全。

Image

Glavo added 8 commits June 15, 2026 14:49
- replace the credential envelope schema with protection-specific
  payload formats and remove the obsolete nonce field
- allow credentials to serialize as plain JSON payloads for
  development while keeping obfuscated payload support
- preserve unknown credential fields during deserialization and
  tighten tests to verify tokens stay out of protected output
- move payload writing behind `protectionMode` to keep credential
  serialization logic in one place
- update protected payload encoding to use shared JSON helpers and
  compressed stream handling for portable account data
- reduce duplication between account credential persistence and the
  protection envelope implementation
- move account identifier generation into `Account` for shared reuse
- update credential serialization to call the unified identifier API
- align account-related classes with repository nullability and
  documentation requirements
- adjust detached account storage tests to cover the refactored
  identifier flow
- replace ad hoc credential map redaction with a dedicated JSON adapter
  for `AccountCredentials`
- separate protected credential payload serialization from account
  diagnostics to reduce exposure of sensitive fields
- log stable account identifiers instead of full storage maps when
  account loading fails or encounters an unknown type
- merge account credentials by searching a list of credential stores
  in priority order instead of relying on a single source
- prefer the credential file paired with the active account metadata
  while still falling back to other available stores
- update account storage tests to cover ordered credential restore
  behavior across multiple stores
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 重构 VersionSetting

4 participants