Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
65c9e97
移除 GameComponentAnalyzer 中未使用的 Status 枚举
Glavo Aug 21, 2026
58675df
移除 GameComponentAnalyzer 中未使用的 Status 枚举
Glavo Aug 22, 2026
a33a587
简化 DefaultDependencyManager 中的字符串格式化为 formatted 方法
Glavo Aug 22, 2026
3ea1d9c
更新 installComponentAsync 方法中的参数名称,从 libraryVersion 更改为 componentVersion
Glavo Aug 22, 2026
81512f7
修复 DefaultDependencyManager 中的格式问题并调整 OptiFineInstallTask 构造函数的参数格式
Glavo Aug 22, 2026
78e76d6
更新 installComponentAsync 方法,移除 gameVersion 参数并添加 isModifiable 方法以增强可读…
Glavo Aug 22, 2026
e8e9ceb
移除 GameComponentAnalyzer 中未使用的 removingMatchedLibrary 方法以简化代码
Glavo Aug 22, 2026
b041e92
更新 installComponentAsync 方法,移除 gameVersion 参数并调整 OptiFineInstallTask …
Glavo Aug 23, 2026
bd6b6dc
更新 DefaultGameBuilder 中的字符串格式化方式,并移除 GameInstanceManifest 中未使用的 isRes…
Glavo Aug 23, 2026
8ca8dea
重构组件安装方法,移除 installComponentAsync,新增 installComponentRemoteAsync 以增强代…
Glavo Aug 24, 2026
106ccba
增强组件安装逻辑,添加对不可修改清单的检查,并简化 addPatch 方法以提高代码可读性
Glavo Aug 24, 2026
8b9f581
增强组件安装逻辑,添加对不可修改清单的检查,并简化 installComponentLocalAsync 方法以提高代码可读性
Glavo Aug 25, 2026
9479044
重构组件移除逻辑,替换 RemoveVersionAction 为 RemoveComponentAction,并简化相关方法以提高代码可读性
Glavo Aug 25, 2026
176b651
重构 updateInstanceAsync 方法,简化逻辑并提高可读性
Glavo Aug 25, 2026
8c6d26b
重构 installNewInstanceComponentAsync 方法,移除不必要的 instanceId 参数以提高代码可读性
Glavo Aug 25, 2026
9fab533
重构 GameInstanceManifest 的重建逻辑,简化 removeComponent 方法并添加 reconstructByP…
Glavo Aug 25, 2026
35115bd
优化 libraryTask 的创建逻辑,将 Task.supplyAsync 替换为 Task.completed 以提高性能
Glavo Aug 25, 2026
4938edd
重构 McbbsModpackLocalInstallTask,移除多余的空行以提高代码整洁性
Glavo Aug 25, 2026
a831c65
重构 RemoteVersion 类的 getInstallTask 方法,添加 modsDirectory 参数以支持自定义 mods 目录
Glavo Aug 25, 2026
b817862
重构多个安装任务的 getInstallTask 方法,统一参数命名为 baseManifest 以提高一致性
Glavo Aug 25, 2026
16b0782
重构 RemoteVersion 类为 ComponentRemoteVersion,更新相关引用以提高代码一致性
Glavo Aug 25, 2026
df16fa6
重构 VersionList 类为 ComponentVersionList,更新相关引用以提高代码一致性
Glavo Aug 25, 2026
e1a3b5b
更新 MultiMCModpackInstallTask 类的文档注释,改用简洁的注释格式以提高可读性
Glavo Aug 25, 2026
b5f451d
重构 AutoDownloadProvider 类,移除 MultipleSourceVersionList 类并将其功能整合到 Auto…
Glavo Aug 26, 2026
f87cd5c
更新 GameComponentAnalyzer 中的 hasModLauncher 方法为 hasForgeModLauncher,添加…
Glavo Aug 26, 2026
72abbf1
Remove redundant default isolation re-evaluation
Glavo Aug 26, 2026
2946ac8
Add validation for instance ID in DownloadPage to prevent null values
Glavo Aug 26, 2026
b59035d
Refactor GameInstance methods to use getLaunchManifest for consistency
Glavo Aug 26, 2026
2e174c1
Introduce HMCLDependencyManager and HMCLGameBuilder for enhanced depe…
Glavo Aug 26, 2026
7bb346b
Refactor HMCLGameBuilder to use HMCLDependencyManager and enforce non…
Glavo Aug 26, 2026
ef1d43c
Refactor DownloadPage to use HMCLDependencyManager and HMCLGameBuilde…
Glavo Aug 26, 2026
7e9a019
Enhance HMCLGameBuilder and DefaultGameBuilder with instance commitme…
Glavo Aug 26, 2026
4fca906
Decouple HMCLGameBuilder isolation from game repository
Glavo Aug 26, 2026
e827a14
Replace useInstanceRunDirectory with enableIsolation in game builder …
Glavo Aug 27, 2026
5202ac5
Add support for existing game instances in game builder creation
Glavo Aug 27, 2026
c89e0fc
Refactor game instance handling in installation tasks to support exis…
Glavo Aug 27, 2026
f5351d3
Add support for updating existing CurseForge modpack instances in ins…
Glavo Aug 28, 2026
1682288
Refactor installation tasks to use updateTarget for existing instance…
Glavo Aug 28, 2026
9f8bd59
Merge remote-tracking branch 'upstream/main' into patches
Glavo Aug 28, 2026
f8373f2
refactor: simplify GameComponentAnalyzer usage in installation tasks
Glavo Aug 28, 2026
f6ea241
refactor: update DefaultGameInstance type for updateTarget in Default…
Glavo Aug 28, 2026
842cfe5
Refactor GameBuilder to reserve repository drafts at construction
Glavo Aug 29, 2026
a011e91
Move game builder draft acquisition into dependency managers
Glavo Aug 29, 2026
1700515
refactor: simplify openGameBuilderDraft and improve async task compos…
Glavo Aug 29, 2026
7f69a52
refactor: streamline async component installation and remove unused a…
Glavo Aug 29, 2026
1d19b59
refactor: validate modifiable manifest and simplify manifest usage in…
Glavo Aug 29, 2026
a2c9096
refactor: update instance jar retrieval to simplify path handling in …
Glavo Aug 29, 2026
8cb84e8
refactor: remove unused getGameVersion method and related test for ga…
Glavo Aug 29, 2026
adf982f
refactor: remove unused instance jar retrieval methods and simplify g…
Glavo Aug 29, 2026
afdc877
refactor: simplify GameInstanceManifest handling and remove resolved …
Glavo Aug 29, 2026
4b9f884
refactor: streamline file reading and simplify manifest initializatio…
Glavo Aug 30, 2026
c204cde
refactor: simplify GameInstanceManifest resolution and update patch m…
Glavo Aug 30, 2026
465e299
refactor: enhance resolve method to handle null resolvedSoFar and rem…
Glavo Aug 30, 2026
ad91fe9
refactor: implement uniqueLibraries method to optimize library declar…
Glavo Aug 30, 2026
353168e
refactor: remove Resolved record from GameInstanceManifest and simpli…
Glavo Aug 30, 2026
be9e7fa
Merge remote-tracking branch 'upstream/main' into patches
Glavo Aug 30, 2026
a8426b8
Merge remote-tracking branch 'upstream/main' into patches
Glavo Aug 30, 2026
ad4261e
refactor: rename getLaunchManifest to getResolvedManifest and update …
Glavo Aug 30, 2026
a965a5f
refactor: update GameInstanceManifest builder to set root flag and re…
Glavo Aug 30, 2026
8c80274
Fix draft cleanup and component repair paths
Glavo Aug 31, 2026
44d4178
Merge remote-tracking branch 'upstream/main' into patches
Glavo Aug 31, 2026
1dc1fcd
refactor: replace Collections.singletonList with List.of for improved…
Glavo Sep 1, 2026
4dab809
Rebuild HMCL modpack components with a single game builder
Glavo Sep 1, 2026
e070f29
fix: improve error handling for game manifest loading
Glavo Sep 1, 2026
916a315
Merge remote-tracking branch 'upstream/main' into patches
Glavo Sep 1, 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2026 huangyuhui <huanghongxun2008@126.com> 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 <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;

import org.jackhuang.hmcl.download.DefaultCacheRepository;
import org.jackhuang.hmcl.download.DefaultDependencyManager;
import org.jackhuang.hmcl.download.DownloadProvider;
import org.jetbrains.annotations.NotNullByDefault;

/// Provides HMCL-specific game builders for an HMCL game repository.
@NotNullByDefault
public class HMCLDependencyManager extends DefaultDependencyManager {
/// Creates a dependency manager for a repository and download context.
///
/// @param repository the associated game repository
/// @param downloadProvider the remote download provider
/// @param cacheRepository the artifact cache
public HMCLDependencyManager(
HMCLGameRepository repository,
DownloadProvider downloadProvider,
DefaultCacheRepository cacheRepository) {
super(repository, downloadProvider, cacheRepository);
}

/// {@inheritDoc}
@Override
public HMCLGameRepository getGameRepository() {
return (HMCLGameRepository) super.getGameRepository();
}

/// {@inheritDoc}
@Override
public HMCLGameBuilder newGameBuilder(GameInstanceID instanceId) {
GameInstanceManifest initialManifest = new GameInstanceManifest(instanceId);
DefaultGameRepositoryDraft draft = openGameBuilderDraft(initialManifest, null);
return new HMCLGameBuilder(this, instanceId, null, draft, initialManifest);
}

/// {@inheritDoc}
@Override
public HMCLGameBuilder newGameBuilder(GameInstance instance) {
validateGameInstance(instance);
HMCLGameInstance updateTarget = (HMCLGameInstance) instance;

GameInstanceManifest initialManifest = new GameInstanceManifest(updateTarget.getId());
DefaultGameRepositoryDraft draft = openGameBuilderDraft(initialManifest, updateTarget);
return new HMCLGameBuilder(
this, updateTarget.getId(), updateTarget, draft, initialManifest);
}
}
53 changes: 53 additions & 0 deletions HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2026 huangyuhui <huanghongxun2008@126.com> 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 <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;

import org.jackhuang.hmcl.download.DefaultGameBuilder;
import org.jetbrains.annotations.NotNullByDefault;
import org.jetbrains.annotations.Nullable;

/// Builds game instances and applies HMCL-specific post-installation settings.
@NotNullByDefault
public class HMCLGameBuilder extends DefaultGameBuilder {
/// Creates a builder around an HMCL target already reserved by its dependency manager.
///
/// @param dependencyManager the dependency manager for the target repository
/// @param instanceId the id of the reserved instance
/// @param updateTarget the exact update target retained by the draft, or `null` for install
/// @param draft the open draft containing `initialManifest`
/// @param initialManifest the empty target manifest retained by `draft`
HMCLGameBuilder(
HMCLDependencyManager dependencyManager,
GameInstanceID instanceId,
@Nullable HMCLGameInstance updateTarget,
DefaultGameRepositoryDraft draft,
GameInstanceManifest initialManifest) {
super(dependencyManager, instanceId, updateTarget, draft, initialManifest);
}

/// {@inheritDoc}
///
/// When isolation was enabled, persists the corresponding HMCL instance setting so subsequent
/// launches use the instance root. A read-only instance retains its existing setting.
@Override
protected void onInstanceCommitted(DefaultGameInstance instance) {
if (isolationEnabled) {
((HMCLGameInstance) instance).enableIsolation();
}
}
}
39 changes: 17 additions & 22 deletions HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -189,28 +189,6 @@ public GameSettings.Effective getEffectiveSettings() {
return GameSettings.resolve(getRepository().getParentGameSettings(setting), setting);
}

/// Applies the selected parent preset's default isolation policy to this instance.
public void applyDefaultIsolationSetting() {
@Nullable GameSettings.Instance instanceSetting = getSettings();
GameSettings.Preset preset = getRepository().getParentGameSettings(instanceSetting);
DefaultIsolationType type = Lang.requireNonNullElse(
preset.defaultIsolationTypeProperty().getValue(), DefaultIsolationType.MODDED);
boolean isolated = switch (type) {
case NEVER -> false;
case ALWAYS -> true;
case MODDED -> getResolvedManifest().isModded();
};

if (isolated) {
@Nullable GameSettings.Instance setting =
instanceSetting != null ? instanceSetting : getSettingsOrCreate();
if (setting != null
&& setting.getOverrideProperties().add(GameSettings.PROPERTY_RUNNING_DIRECTORY)) {
saveSettings();
}
}
}

/// Creates empty instance-local game settings when none are loaded.
///
/// @return the settings, or `null` when settings are read-only or already present in a non-creatable state
Expand All @@ -233,6 +211,23 @@ public boolean isSettingsReadOnly() {
return gameSettingsReadOnly;
}

/// Enables instance-local running-directory selection for this instance.
///
/// A blank local running directory resolves to the instance root. This operation is idempotent
/// and schedules a settings save only when it adds the override. It leaves the instance
/// unchanged when its local settings cannot be written safely.
public void enableIsolation() {
if (isSettingsReadOnly()) {
return;
}

@Nullable GameSettings.Instance setting = getSettingsOrCreate();
if (setting != null
&& setting.getOverrideProperties().add(GameSettings.PROPERTY_RUNNING_DIRECTORY)) {
saveSettings();
}
}

/// Backs up and overwrites the settings file when this instance still owns its settings.
public void forceOverwriteSettings() {
ensureGameSettingsLoaded();
Expand Down
Loading