Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
652491c
修复资源包管理界面边框样式问题
Calboot Dec 14, 2025
2bc3fa7
修复 #4680
Calboot Dec 14, 2025
c5406e3
update
Calboot Dec 14, 2025
facdd47
修复光影包界面下载标题错误
Calboot Dec 14, 2025
d24b7b2
资源包启用/禁用功能
Calboot Dec 16, 2025
a2b5e8b
同步模组管理界面 Part1
Calboot Dec 16, 2025
2ca2f3e
为不兼容资源包添加警告
Calboot Dec 16, 2025
ce9377b
update
Calboot Dec 17, 2025
bd96337
启用/禁用资源包时添加警告
Calboot Dec 17, 2025
bc229e3
资源包详细信息界面
Calboot Dec 17, 2025
777aea3
修复esc键失效
Calboot Dec 17, 2025
e7c4f2e
Update i18n
Calboot Dec 17, 2025
07a9cc0
Update i18n
Calboot Dec 17, 2025
9aca021
完善资源包版本解析
Calboot Dec 18, 2025
eacf26b
Merge remote-tracking branch 'origin/resourcepack-enhancement' into r…
Calboot Dec 18, 2025
8d44424
从模组管理界面同步
Calboot Dec 18, 2025
00b377a
update
Calboot Dec 18, 2025
7d2ea79
update i18n
Calboot Dec 19, 2025
8ba09cf
移除资源包删除按钮
Calboot Dec 20, 2025
ae789fb
Merge branch 'HMCL-dev:main' into resourcepack-enhancement
Calboot Dec 20, 2025
9f6f42b
添加cf/modrinth页面检测 & fix i18n
Calboot Dec 20, 2025
9172c53
Apply suggestions
Calboot Dec 20, 2025
7ab6e62
update i18n
Calboot Dec 20, 2025
c7010f9
Apply suggestions from code review
Calboot Dec 21, 2025
b0fca8d
Apply suggestions from code review
Calboot Dec 21, 2025
78b5ce7
资源包更新功能
Calboot Dec 21, 2025
6709fbe
update
Calboot Dec 21, 2025
07632bb
update
Calboot Dec 21, 2025
6a6a07d
update
Calboot Dec 21, 2025
827272e
update
Calboot Dec 21, 2025
07a7b34
sync with #5016
Calboot Dec 21, 2025
4b69a17
Merge branch 'HMCL-dev:main' into resourcepack-enhancement
Calboot Dec 22, 2025
60ea149
update
Calboot Dec 23, 2025
e944351
update
Calboot Dec 23, 2025
29c34b9
update
Calboot Dec 24, 2025
b42dac6
update
Calboot Dec 24, 2025
bdc6cdb
Merge remote-tracking branch 'upstream/main' into resourcepack-enhanc…
Calboot Dec 24, 2025
3204857
update
Calboot Dec 24, 2025
423a021
update
Calboot Dec 24, 2025
194ce5f
Apply suggestions
Calboot Dec 24, 2025
79c04a1
update
Calboot Dec 25, 2025
b87dd5a
update
Calboot Dec 25, 2025
ff7f597
update
Calboot Dec 25, 2025
a915024
update
Calboot Dec 25, 2025
e1d8f5f
using config
Calboot Dec 26, 2025
f108671
update
Calboot Dec 26, 2025
87bb56d
update
Calboot Dec 26, 2025
4951406
添加资源包、光影包等的推荐下载
Calboot Dec 26, 2025
59d0dec
update
Calboot Dec 26, 2025
186ae00
update
Calboot Dec 27, 2025
cf84e5f
update
Calboot Dec 27, 2025
97d7d0f
update
Calboot Dec 27, 2025
4bf35f2
update
Calboot Dec 27, 2025
4fdab0a
update
Calboot Dec 28, 2025
ca167cb
update
Calboot Dec 28, 2025
6ab182c
update
Calboot Dec 28, 2025
c3ae0c1
update
Calboot Dec 28, 2025
d9a9dbb
update
Calboot Dec 28, 2025
701b839
清理代码
Calboot Dec 28, 2025
73662a6
Apply suggestions
Calboot Jan 1, 2026
dab739d
Merge branch 'HMCL-dev:main' into resourcepack-enhancement
Calboot Jan 1, 2026
9ddc2ed
Merge branch 'main' into resourcepack-enhancement
Calboot Jan 2, 2026
c4b4d2f
update
Calboot Jan 2, 2026
6fd1a56
update
Calboot Jan 3, 2026
106b5bb
update
Calboot Jan 3, 2026
0c9559c
Merge branch 'main' into resourcepack-enhancement
Calboot Jan 4, 2026
add29f8
update
Calboot Jan 4, 2026
598fd23
Merge branch 'main' into resourcepack-enhancement
Calboot Jan 13, 2026
7765f0c
update
Calboot Jan 13, 2026
26282ef
update
Calboot Jan 18, 2026
def0840
Merge branch 'main' into resourcepack-enhancement
Calboot Jan 18, 2026
3ecedb0
完成合并
Calboot Jan 18, 2026
1329d63
跟紧主线
Calboot Jan 18, 2026
c0e8395
Merge branch 'main' into resourcepack-enhancement
Calboot Jan 19, 2026
542b2e8
update
Calboot Jan 23, 2026
75ce692
update
Calboot Jan 23, 2026
c727451
update
Calboot Jan 24, 2026
2bf8151
Update HMCL/src/main/resources/assets/lang/I18N_zh.properties
Calboot Jan 24, 2026
d6a8d14
Update HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties
Calboot Jan 24, 2026
89e81d1
Merge remote-tracking branch 'origin/resourcepack-enhancement' into r…
Calboot Jan 24, 2026
23c8c5e
update
Calboot Jan 24, 2026
fe05cca
update
Calboot Jan 28, 2026
0e96a9d
Apply AI suggestions
Calboot Jan 29, 2026
05e60d6
Merge branch 'main' into resourcepack-enhancement
Calboot Jan 30, 2026
6a7f453
Merge
Calboot Feb 1, 2026
72d9ca3
Delete HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Resourcepack…
Calboot Feb 1, 2026
5f864a9
Fix #5207
Calboot Feb 1, 2026
871bd87
Merge branch 'main' into resourcepack-enhancement
Calboot Feb 2, 2026
63f93d7
update
Calboot Feb 3, 2026
774c2b7
Merge
Calboot Feb 6, 2026
4f0fa24
update
Calboot Feb 6, 2026
1bee3f7
update
Calboot Feb 6, 2026
063ff8c
update
Calboot Feb 6, 2026
1ed3dbe
Merge
Calboot Feb 7, 2026
e9cc88e
Merge branch 'HMCL-dev:main' into resourcepack-enhancement
Calboot Feb 8, 2026
c60634e
update
Calboot Feb 8, 2026
e5a3870
update
Calboot Feb 8, 2026
b54ae5d
Apply suggestions
Calboot Feb 8, 2026
55f6974
Merge branch 'main' into resourcepack-enhancement
Calboot Feb 19, 2026
146c601
rename
Calboot Feb 19, 2026
2ef2c1a
update
Calboot Feb 19, 2026
25677c2
update
Calboot Feb 19, 2026
835f416
update
Calboot Feb 19, 2026
abd05e2
update
Calboot Feb 19, 2026
a081bd1
Merge
Calboot Feb 24, 2026
8bd8ae9
Merge
Calboot Feb 24, 2026
7ece553
update
Calboot Feb 24, 2026
2133e19
Apply suggestions
Calboot Feb 25, 2026
2b6837c
Merge branch 'main' into resourcepack-enhancement
Calboot Feb 25, 2026
d588e27
update
Calboot Feb 25, 2026
89707c5
update
Calboot Feb 25, 2026
22fa93c
update
Calboot Feb 26, 2026
771f1c6
Merge
Calboot Feb 26, 2026
8b43bbf
update
Calboot Feb 26, 2026
d2bebcd
update test
Calboot Feb 27, 2026
1467763
Merge branch 'main' into resourcepack-enhancement
Calboot Mar 7, 2026
6db8633
update
Calboot Mar 7, 2026
835ac14
strict check for 1.20.1-
Calboot Mar 9, 2026
115fa40
Replace var with explicit types in ResourcePackListPage
Glavo Mar 11, 2026
591280b
Reformat ResourcePackManager.getCompatibility method
Glavo Mar 11, 2026
bdae961
Reformat ResourcePackManager conditional returns
Glavo Mar 11, 2026
778fc45
Reformat ResourcePackManager version range methods
Glavo Mar 11, 2026
ee87e80
Apply suggestions
Calboot Mar 11, 2026
bddb7f5
update
Calboot Mar 11, 2026
efb94b0
update
Calboot Mar 12, 2026
12c1130
Fix supported_formats parsing; Use lenient gson
Calboot Mar 13, 2026
b72d835
Merge branch 'HMCL-dev:main' into resourcepack-enhancement
Calboot Mar 13, 2026
4b401b0
fix #5489
Calboot Mar 13, 2026
eaa1bae
Merge branch 'main' into resourcepack-enhancement
Calboot Mar 13, 2026
039671e
update
Calboot Mar 13, 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
Expand Up @@ -18,7 +18,6 @@
package org.jackhuang.hmcl.game;

import org.jackhuang.hmcl.download.DownloadProvider;
import org.jackhuang.hmcl.mod.LocalModFile;
import org.jackhuang.hmcl.mod.RemoteMod;
import org.jackhuang.hmcl.mod.RemoteModRepository;
import org.jackhuang.hmcl.ui.versions.ModTranslations;
Expand Down Expand Up @@ -110,8 +109,8 @@ public Stream<Category> getCategories() throws IOException {
}

@Override
public Optional<RemoteMod.Version> getRemoteVersionByLocalFile(LocalModFile localModFile, Path file) throws IOException {
return getBackedRemoteModRepository().getRemoteVersionByLocalFile(localModFile, file);
public Optional<RemoteMod.Version> getRemoteVersionByLocalFile(Path file) throws IOException {
return getBackedRemoteModRepository().getRemoteVersionByLocalFile(file);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;

public class DownloadPage extends DecoratorAnimatedPage implements DecoratorPage {
public static final org.jackhuang.hmcl.ui.versions.DownloadPage.DownloadCallback FOR_MOD =
(profile, version, mod, file) -> download(profile, version, file, "mods");
public static final org.jackhuang.hmcl.ui.versions.DownloadPage.DownloadCallback FOR_RESOURCE_PACK =
(profile, version, mod, file) -> download(profile, version, file, "resourcepacks");
public static final org.jackhuang.hmcl.ui.versions.DownloadPage.DownloadCallback FOR_SHADER =
(profile, version, mod, file) -> download(profile, version, file, "shaderpacks");

private final ReadOnlyObjectWrapper<DecoratorPage.State> state = new ReadOnlyObjectWrapper<>(DecoratorPage.State.fromTitle(i18n("download"), -1));
private final TabHeader tab;
private final TabHeader.Tab<VersionsPage> newGameTab = new TabHeader.Tab<>("newGameTab");
Expand Down Expand Up @@ -94,9 +101,9 @@ public DownloadPage(String uploadVersion) {
page.getActions().add(installLocalModpackButton);
return page;
}));
modTab.setNodeSupplier(loadVersionFor(() -> HMCLLocalizedDownloadListPage.ofMod((profile, version, mod, file) -> download(profile, version, file, "mods"), true)));
resourcePackTab.setNodeSupplier(loadVersionFor(() -> HMCLLocalizedDownloadListPage.ofResourcePack((profile, version, mod, file) -> download(profile, version, file, "resourcepacks"), true)));
shaderTab.setNodeSupplier(loadVersionFor(() -> HMCLLocalizedDownloadListPage.ofShaderPack((profile, version, mod, file) -> download(profile, version, file, "shaderpacks"), true)));
modTab.setNodeSupplier(loadVersionFor(() -> HMCLLocalizedDownloadListPage.ofMod(FOR_MOD, true)));
resourcePackTab.setNodeSupplier(loadVersionFor(() -> HMCLLocalizedDownloadListPage.ofResourcePack(FOR_RESOURCE_PACK, true)));
shaderTab.setNodeSupplier(loadVersionFor(() -> HMCLLocalizedDownloadListPage.ofShaderPack(FOR_SHADER, true)));
worldTab.setNodeSupplier(loadVersionFor(() -> new DownloadListPage(CurseForgeRemoteModRepository.WORLDS)));
tab = new TabHeader(transitionPane, newGameTab, modpackTab, modTab, resourcePackTab, shaderTab, worldTab);

Expand Down Expand Up @@ -195,8 +202,9 @@ public void showModpackDownloads() {
tab.select(modpackTab, false);
}

public void showResourcepackDownloads() {
public DownloadListPage showResourcePackDownloads() {
tab.select(resourcePackTab, false);
return resourcePackTab.getNode();
}

public DownloadListPage showModDownloads() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
package org.jackhuang.hmcl.ui.versions;

import org.jackhuang.hmcl.mod.LocalModFile;
import org.jackhuang.hmcl.mod.LocalAddonFile;
import org.jackhuang.hmcl.mod.RemoteMod;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task;
Expand All @@ -29,31 +29,31 @@

import static org.jackhuang.hmcl.util.logging.Logger.LOG;

public class ModCheckUpdatesTask extends Task<List<LocalModFile.ModUpdate>> {
private final List<Task<LocalModFile.ModUpdate>> dependents;
public class AddonCheckUpdatesTask<T extends LocalAddonFile> extends Task<List<LocalAddonFile.AddonUpdate>> {
private final List<Task<LocalAddonFile.AddonUpdate>> dependents;

public ModCheckUpdatesTask(String gameVersion, Collection<LocalModFile> mods) {
dependents = mods.stream().map(mod ->
public AddonCheckUpdatesTask(String gameVersion, Collection<T> addons) {
dependents = addons.stream().map(addon ->
Task.supplyAsync(Schedulers.io(), () -> {
LocalModFile.ModUpdate candidate = null;
LocalAddonFile.AddonUpdate candidate = null;
for (RemoteMod.Type type : RemoteMod.Type.values()) {
LocalModFile.ModUpdate update = null;
LocalAddonFile.AddonUpdate update = null;
try {
update = mod.checkUpdates(gameVersion, type.getRemoteModRepository());
update = addon.checkUpdates(gameVersion, type);
} catch (IOException e) {
LOG.warning(String.format("Cannot check update for mod %s.", mod.getFileName()), e);
LOG.warning(String.format("Cannot check update for addon %s.", addon.getFileName()), e);
}
if (update == null) {
continue;
}

if (candidate == null || candidate.getCandidate().getDatePublished().isBefore(update.getCandidate().getDatePublished())) {
if (candidate == null || candidate.targetVersion().getDatePublished().isBefore(update.targetVersion().getDatePublished())) {
candidate = update;
}
}

return candidate;
}).setName(mod.getFileName()).setSignificance(TaskSignificance.MAJOR).withCounter("update.checking")
}).setName(addon.getFileName()).setSignificance(TaskSignificance.MAJOR).withCounter("update.checking")
).toList();

setStage("update.checking");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import org.jackhuang.hmcl.mod.LocalModFile;
import org.jackhuang.hmcl.mod.ModManager;
import org.jackhuang.hmcl.mod.LocalAddonFile;
import org.jackhuang.hmcl.mod.LocalAddonManager;
import org.jackhuang.hmcl.mod.RemoteMod;
import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.task.Schedulers;
Expand All @@ -41,10 +41,11 @@
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
import org.jackhuang.hmcl.ui.construct.PageCloseEvent;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.util.Pair;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.TaskCancellationAction;
import org.jackhuang.hmcl.util.io.CSVTable;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
Expand All @@ -56,50 +57,49 @@
import java.util.stream.Collectors;

import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
import static org.jackhuang.hmcl.util.Pair.pair;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;

public class ModUpdatesPage extends BorderPane implements DecoratorPage {
public class AddonUpdatesPage<F extends LocalAddonFile> extends BorderPane implements DecoratorPage {
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(DecoratorPage.State.fromTitle(i18n("mods.check_updates")));

private final ModManager modManager;
private final ObservableList<ModUpdateObject> objects;
private final LocalAddonManager<F> localAddonManager;
private final ObservableList<AddonUpdateObject> objects;

@SuppressWarnings("unchecked")
public ModUpdatesPage(ModManager modManager, List<LocalModFile.ModUpdate> updates) {
this.modManager = modManager;
public AddonUpdatesPage(LocalAddonManager<F> localAddonManager, List<LocalAddonFile.AddonUpdate> updates) {
this.localAddonManager = localAddonManager;

getStyleClass().add("gray-background");

TableColumn<ModUpdateObject, Boolean> enabledColumn = new TableColumn<>();
TableColumn<AddonUpdateObject, Boolean> enabledColumn = new TableColumn<>();
var allEnabledBox = new JFXCheckBox();
enabledColumn.setStyle("-fx-alignment: CENTER;");
enabledColumn.setGraphic(allEnabledBox);
enabledColumn.setCellFactory(JFXCheckBoxTableCell.forTableColumn(enabledColumn));
setupCellValueFactory(enabledColumn, ModUpdateObject::enabledProperty);
setupCellValueFactory(enabledColumn, AddonUpdateObject::enabledProperty);
enabledColumn.setEditable(true);
enabledColumn.setMaxWidth(40);
enabledColumn.setMinWidth(40);

TableColumn<ModUpdateObject, String> fileNameColumn = new TableColumn<>(i18n("mods.check_updates.file"));
TableColumn<AddonUpdateObject, String> fileNameColumn = new TableColumn<>(i18n("mods.check_updates.file"));
fileNameColumn.setPrefWidth(200);
setupCellValueFactory(fileNameColumn, ModUpdateObject::fileNameProperty);
setupCellValueFactory(fileNameColumn, AddonUpdateObject::fileNameProperty);

TableColumn<ModUpdateObject, String> currentVersionColumn = new TableColumn<>(i18n("mods.check_updates.current_version"));
TableColumn<AddonUpdateObject, String> currentVersionColumn = new TableColumn<>(i18n("mods.check_updates.current_version"));
currentVersionColumn.setPrefWidth(200);
setupCellValueFactory(currentVersionColumn, ModUpdateObject::currentVersionProperty);
setupCellValueFactory(currentVersionColumn, AddonUpdateObject::currentVersionProperty);

TableColumn<ModUpdateObject, String> targetVersionColumn = new TableColumn<>(i18n("mods.check_updates.target_version"));
TableColumn<AddonUpdateObject, String> targetVersionColumn = new TableColumn<>(i18n("mods.check_updates.target_version"));
targetVersionColumn.setPrefWidth(200);
setupCellValueFactory(targetVersionColumn, ModUpdateObject::targetVersionProperty);
setupCellValueFactory(targetVersionColumn, AddonUpdateObject::targetVersionProperty);

TableColumn<ModUpdateObject, String> sourceColumn = new TableColumn<>(i18n("mods.check_updates.source"));
setupCellValueFactory(sourceColumn, ModUpdateObject::sourceProperty);
TableColumn<AddonUpdateObject, String> sourceColumn = new TableColumn<>(i18n("mods.check_updates.source"));
setupCellValueFactory(sourceColumn, AddonUpdateObject::sourceProperty);

objects = FXCollections.observableList(updates.stream().map(ModUpdateObject::new).collect(Collectors.toList()));
objects = FXCollections.observableList(updates.stream().map(AddonUpdateObject::new).collect(Collectors.toList()));
FXUtils.bindAllEnabled(allEnabledBox.selectedProperty(), objects.stream().map(o -> o.enabled).toArray(BooleanProperty[]::new));

TableView<ModUpdateObject> table = new TableView<>(objects);
TableView<AddonUpdateObject> table = new TableView<>(objects);
table.setEditable(true);
table.getColumns().setAll(enabledColumn, fileNameColumn, currentVersionColumn, targetVersionColumn, sourceColumn);
setMargin(table, new Insets(10, 10, 5, 10));
Expand All @@ -114,7 +114,7 @@ public ModUpdatesPage(ModManager modManager, List<LocalModFile.ModUpdate> update
exportListButton.setOnAction(e -> exportList());

JFXButton nextButton = FXUtils.newRaisedButton(i18n("mods.check_updates.confirm"));
nextButton.setOnAction(e -> updateMods());
nextButton.setOnAction(e -> updateFiles());

JFXButton cancelButton = FXUtils.newRaisedButton(i18n("button.cancel"));
cancelButton.setOnAction(e -> fireEvent(new PageCloseEvent()));
Expand All @@ -125,23 +125,24 @@ public ModUpdatesPage(ModManager modManager, List<LocalModFile.ModUpdate> update
setBottom(actions);
}

private <T> void setupCellValueFactory(TableColumn<ModUpdateObject, T> column, Function<ModUpdateObject, ObservableValue<T>> mapper) {
private <T> void setupCellValueFactory(TableColumn<AddonUpdateObject, T> column, Function<AddonUpdateObject, ObservableValue<T>> mapper) {
column.setCellValueFactory(param -> mapper.apply(param.getValue()));
}

private void updateMods() {
ModUpdateTask task = new ModUpdateTask(
modManager,
private void updateFiles() {
AddonUpdateTask task = new AddonUpdateTask(
localAddonManager.getDirectory(),
objects.stream()
.filter(o -> o.enabled.get())
.map(object -> pair(object.data.getLocalMod(), object.data.getCandidate()))
.collect(Collectors.toList()));
.filter(AddonUpdateObject::isEnabled)
.map(AddonUpdateObject::getData)
.toList()
);
Controllers.taskDialog(
task.whenComplete(Schedulers.javafx(), exception -> {
fireEvent(new PageCloseEvent());
if (!task.getFailedMods().isEmpty()) {
if (!task.getFailedAddons().isEmpty()) {
Controllers.dialog(i18n("mods.check_updates.failed_download") + "\n" +
task.getFailedMods().stream().map(LocalModFile::getFileName).collect(Collectors.joining("\n")),
task.getFailedAddons().stream().map(LocalAddonFile::getFileName).collect(Collectors.joining("\n")),
i18n("install.failed"),
MessageDialogPane.MessageType.ERROR);
}
Expand Down Expand Up @@ -189,22 +190,22 @@ public ReadOnlyObjectWrapper<State> stateProperty() {
return state;
}

private static final class ModUpdateObject {
final LocalModFile.ModUpdate data;
private static final class AddonUpdateObject {
final LocalAddonFile.AddonUpdate data;
final BooleanProperty enabled = new SimpleBooleanProperty();
final StringProperty fileName = new SimpleStringProperty();
final StringProperty currentVersion = new SimpleStringProperty();
final StringProperty targetVersion = new SimpleStringProperty();
final StringProperty source = new SimpleStringProperty();

public ModUpdateObject(LocalModFile.ModUpdate data) {
public AddonUpdateObject(LocalAddonFile.AddonUpdate data) {
this.data = data;

enabled.set(!data.getLocalMod().getModManager().isDisabled(data.getLocalMod().getFile()));
fileName.set(data.getLocalMod().getFileName());
currentVersion.set(data.getCurrentVersion().getVersion());
targetVersion.set(data.getCandidate().getVersion());
switch (data.getCurrentVersion().getSelf().getType()) {
enabled.set(!data.localAddonFile().isDisabled());
fileName.set(data.localAddonFile().getFileName());
currentVersion.set(data.currentVersion().getVersion());
targetVersion.set(data.targetVersion().getVersion());
switch (data.currentVersion().getSelf().getType()) {
case CURSEFORGE:
source.set(i18n("mods.curseforge"));
break;
Expand All @@ -213,6 +214,10 @@ public ModUpdateObject(LocalModFile.ModUpdate data) {
}
}

public LocalAddonFile.AddonUpdate getData() {
return data;
}

public boolean isEnabled() {
return enabled.get();
}
Expand Down Expand Up @@ -274,30 +279,32 @@ public void setSource(String source) {
}
}

public static class ModUpdateTask extends Task<Void> {
public static class AddonUpdateTask extends Task<Void> {
private final Collection<Task<?>> dependents;
private final List<LocalModFile> failedMods = new ArrayList<>();
private final List<LocalAddonFile> failedAddons = new ArrayList<>();

ModUpdateTask(ModManager modManager, List<Pair<LocalModFile, RemoteMod.Version>> mods) {
AddonUpdateTask(Path addonDirectory, List<LocalAddonFile.AddonUpdate> addons) {
setStage("mods.check_updates.confirm");
getProperties().put("total", mods.size());
getProperties().put("total", addons.size());

this.dependents = new ArrayList<>();
for (Pair<LocalModFile, RemoteMod.Version> mod : mods) {
LocalModFile local = mod.getKey();
RemoteMod.Version remote = mod.getValue();
boolean isDisabled = local.getModManager().isDisabled(local.getFile());
for (LocalAddonFile.AddonUpdate addon : addons) {
LocalAddonFile local = addon.localAddonFile();
RemoteMod.Version remote = addon.targetVersion();
boolean isDisabled = local.isDisabled();
String originalFileName = local.getFile().getFileName().toString();

dependents.add(Task
.runAsync(Schedulers.javafx(), () -> local.setOld(true))
.thenComposeAsync(() -> {
String fileName = remote.getFile().getFilename();
String fileName = addon.useRemoteFileName() ? remote.getFile().getFilename() : originalFileName;
if (isDisabled)
fileName += ModManager.DISABLED_EXTENSION;
fileName = StringUtils.addSuffix(fileName, LocalAddonManager.DISABLED_EXTENSION);

var task = new FileDownloadTask(
remote.getFile().getUrl(),
modManager.getModsDirectory().resolve(fileName));
addonDirectory.resolve(fileName)
);

task.setName(remote.getName());
return task;
Expand All @@ -307,16 +314,22 @@ public static class ModUpdateTask extends Task<Void> {
// restore state if failed
local.setOld(false);
if (isDisabled)
local.disable();
failedMods.add(local);
local.markDisabled();
failedAddons.add(local);
} else if (!local.keepOldFiles()) {
try {
local.delete();
} catch (IOException e) {
// ignore
}
}
})
.withCounter("mods.check_updates.confirm"));
}
}

public List<LocalModFile> getFailedMods() {
return failedMods;
public List<LocalAddonFile> getFailedAddons() {
return failedAddons;
}

@Override
Expand Down
Loading
Loading