diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index aa18ee3f7..46b7e5f2c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -123,7 +123,13 @@ public final class Config implements Cloneable, Observable { private ObjectProperty localization = new SimpleObjectProperty<>(Locales.DEFAULT); @SerializedName("downloadType") - private StringProperty downloadType = new SimpleStringProperty("bmclapi"); + private StringProperty downloadType = new SimpleStringProperty("mcbbs"); + + @SerializedName("autoChooseDownloadType") + private BooleanProperty autoChooseDownloadType = new SimpleBooleanProperty(true); + + @SerializedName("versionListSource") + private StringProperty versionListSource = new SimpleStringProperty("balanced"); @SerializedName("configurations") private ObservableMap configurations = FXCollections.observableMap(new TreeMap<>()); @@ -395,6 +401,30 @@ public final class Config implements Cloneable, Observable { return downloadType; } + public boolean isAutoChooseDownloadType() { + return autoChooseDownloadType.get(); + } + + public BooleanProperty autoChooseDownloadTypeProperty() { + return autoChooseDownloadType; + } + + public void setAutoChooseDownloadType(boolean autoChooseDownloadType) { + this.autoChooseDownloadType.set(autoChooseDownloadType); + } + + public String getVersionListSource() { + return versionListSource.get(); + } + + public void setVersionListSource(String versionListSource) { + this.versionListSource.set(versionListSource); + } + + public StringProperty versionListSourceProperty() { + return versionListSource; + } + public ObservableMap getConfigurations() { return configurations; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java index 3b16ebf89..a1c1cebfc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java @@ -17,14 +17,10 @@ */ package org.jackhuang.hmcl.setting; -import org.jackhuang.hmcl.download.AdaptedDownloadProvider; -import org.jackhuang.hmcl.download.BMCLAPIDownloadProvider; -import org.jackhuang.hmcl.download.DownloadProvider; -import org.jackhuang.hmcl.download.MojangDownloadProvider; +import org.jackhuang.hmcl.download.*; import org.jackhuang.hmcl.ui.FXUtils; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -35,31 +31,66 @@ import static org.jackhuang.hmcl.util.Pair.pair; public final class DownloadProviders { private DownloadProviders() {} - private static final AdaptedDownloadProvider DOWNLOAD_PROVIDER = new AdaptedDownloadProvider(); + private static DownloadProvider currentDownloadProvider; public static final Map providersById; + public static final Map rawProviders; + private static final AdaptedDownloadProvider fileDownloadProvider = new AdaptedDownloadProvider(); - public static final String DEFAULT_PROVIDER_ID = "mcbbs"; + private static final MojangDownloadProvider MOJANG; + private static final BMCLAPIDownloadProvider BMCLAPI; + private static final BMCLAPIDownloadProvider MCBBS; + + public static final String DEFAULT_PROVIDER_ID = "balanced"; + public static final String DEFAULT_RAW_PROVIDER_ID = "mcbbs"; static { String bmclapiRoot = "https://bmclapi2.bangbang93.com"; String bmclapiRootOverride = System.getProperty("hmcl.bmclapi.override"); if (bmclapiRootOverride != null) bmclapiRoot = bmclapiRootOverride; + MOJANG = new MojangDownloadProvider(); + BMCLAPI = new BMCLAPIDownloadProvider(bmclapiRoot); + MCBBS = new BMCLAPIDownloadProvider("https://download.mcbbs.net"); + rawProviders = mapOf( + pair("mojang", MOJANG), + pair("bmclapi", BMCLAPI), + pair("mcbbs", MCBBS) + ); + + AdaptedDownloadProvider fileProvider = new AdaptedDownloadProvider(); + fileProvider.setDownloadProviderCandidates(Arrays.asList(MCBBS, BMCLAPI, MOJANG)); +// BalancedDownloadProvider balanced = new BalancedDownloadProvider(); + providersById = mapOf( - pair("mojang", new MojangDownloadProvider()), - pair("bmclapi", new BMCLAPIDownloadProvider(bmclapiRoot)), - pair("mcbbs", new BMCLAPIDownloadProvider("https://download.mcbbs.net"))); + pair("official", new AutoDownloadProvider(MOJANG, fileProvider)), + pair("balanced", new AutoDownloadProvider(MCBBS, fileProvider)), + pair("mirror", new AutoDownloadProvider(MCBBS, fileProvider))); } static void init() { - FXUtils.onChangeAndOperate(config().downloadTypeProperty(), downloadType -> { - DownloadProvider primary = Optional.ofNullable(providersById.get(config().getDownloadType())) + FXUtils.onChangeAndOperate(config().versionListSourceProperty(), versionListSource -> { + if (!providersById.containsKey(versionListSource)) { + config().setVersionListSource(DEFAULT_PROVIDER_ID); + return; + } + + currentDownloadProvider = Optional.ofNullable(providersById.get(versionListSource)) .orElse(providersById.get(DEFAULT_PROVIDER_ID)); - DOWNLOAD_PROVIDER.setDownloadProviderCandidates( + }); + + FXUtils.onChangeAndOperate(config().downloadTypeProperty(), downloadType -> { + if (!rawProviders.containsKey(downloadType)) { + config().setDownloadType(DEFAULT_RAW_PROVIDER_ID); + return; + } + + DownloadProvider primary = Optional.ofNullable(rawProviders.get(downloadType)) + .orElse(rawProviders.get(DEFAULT_RAW_PROVIDER_ID)); + fileDownloadProvider.setDownloadProviderCandidates( Stream.concat( Stream.of(primary), - providersById.values().stream().filter(x -> x != primary) + rawProviders.values().stream().filter(x -> x != primary) ).collect(Collectors.toList()) ); }); @@ -73,23 +104,15 @@ public final class DownloadProviders { return DEFAULT_PROVIDER_ID; } - public static AdaptedDownloadProvider getDownloadProviderByPrimaryId(String primaryId) { - AdaptedDownloadProvider adaptedDownloadProvider = new AdaptedDownloadProvider(); - DownloadProvider primary = Optional.ofNullable(providersById.get(primaryId)) + public static DownloadProvider getDownloadProviderByPrimaryId(String primaryId) { + return Optional.ofNullable(providersById.get(primaryId)) .orElse(providersById.get(DEFAULT_PROVIDER_ID)); - adaptedDownloadProvider.setDownloadProviderCandidates( - Stream.concat( - Stream.of(primary), - providersById.values().stream().filter(x -> x != primary) - ).collect(Collectors.toList()) - ); - return adaptedDownloadProvider; } /** * Get current primary preferred download provider */ - public static AdaptedDownloadProvider getDownloadProvider() { - return DOWNLOAD_PROVIDER; + public static DownloadProvider getDownloadProvider() { + return config().isAutoChooseDownloadType() ? currentDownloadProvider : fileDownloadProvider; } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java index 13b6e03f5..7680d4853 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java @@ -54,25 +54,53 @@ public class DownloadSettingsPage extends StackPane { ComponentList downloadSource = new ComponentList(); { + VBox pane = new VBox(8); + + VBox chooseWrapper = new VBox(); + chooseWrapper.setPadding(new Insets(8, 0, 8, 0)); + JFXCheckBox chkAutoChooseDownloadSource = new JFXCheckBox(i18n("settings.launcher.download_source.auto")); + chkAutoChooseDownloadSource.selectedProperty().bindBidirectional(config().autoChooseDownloadTypeProperty()); + chooseWrapper.getChildren().setAll(chkAutoChooseDownloadSource); + + BorderPane versionListSourcePane = new BorderPane(); + versionListSourcePane.setPadding(new Insets(0, 0, 8, 30)); + versionListSourcePane.disableProperty().bind(chkAutoChooseDownloadSource.selectedProperty().not()); + { + Label label = new Label(i18n("settings.launcher.version_list_source")); + BorderPane.setAlignment(label, Pos.CENTER_LEFT); + versionListSourcePane.setLeft(label); + + JFXComboBox cboVersionListSource = new JFXComboBox<>(); + cboVersionListSource.setConverter(stringConverter(key -> i18n("download.provider." + key))); + versionListSourcePane.setRight(cboVersionListSource); + FXUtils.setLimitWidth(cboVersionListSource, 420); + + cboVersionListSource.getItems().setAll(DownloadProviders.providersById.keySet()); + selectedItemPropertyFor(cboVersionListSource).bindBidirectional(config().versionListSourceProperty()); + } + BorderPane downloadSourcePane = new BorderPane(); + downloadSourcePane.setPadding(new Insets(0, 0, 8, 30)); + downloadSourcePane.disableProperty().bind(chkAutoChooseDownloadSource.selectedProperty()); { Label label = new Label(i18n("settings.launcher.download_source")); BorderPane.setAlignment(label, Pos.CENTER_LEFT); downloadSourcePane.setLeft(label); - } - { JFXComboBox cboDownloadSource = new JFXComboBox<>(); cboDownloadSource.setConverter(stringConverter(key -> i18n("download.provider." + key))); downloadSourcePane.setRight(cboDownloadSource); + FXUtils.setLimitWidth(cboDownloadSource, 420); - cboDownloadSource.getItems().setAll(DownloadProviders.providersById.keySet()); + cboDownloadSource.getItems().setAll(DownloadProviders.rawProviders.keySet()); selectedItemPropertyFor(cboDownloadSource).bindBidirectional(config().downloadTypeProperty()); } - downloadSource.getContent().add(downloadSourcePane); + + pane.getChildren().setAll(chooseWrapper, versionListSourcePane, downloadSourcePane); + downloadSource.getContent().add(pane); } - content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.download_source")), downloadSource); + content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.version_list_source")), downloadSource); } { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 26b35d465..6604a13c3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -189,6 +189,9 @@ download.failed.refresh=Unable to download version list. Click here to retry. download.provider.mcbbs=MCBBS (https://www.mcbbs.net/) download.provider.bmclapi=BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) download.provider.mojang=Mojang (OptiFine download service is provided by BMCLAPI) +download.provider.official=Try to load from official source +download.provider.balanced=Load from fastest source +download.provider.mirror=Try to load from mirror source download.javafx=Downloading the JavaFX runtime components extension.bat=Windows Bat file @@ -501,6 +504,7 @@ settings.launcher.appearance=Appearance settings.launcher.common_path.tooltip=This app will cache all downloads here. settings.launcher.debug=Debug settings.launcher.download_source=Download Source +settings.launcher.download_source.auto=Auto choose download source settings.launcher.enable_game_list=Show version list in main page settings.launcher.font=Font settings.launcher.language=Language @@ -520,6 +524,7 @@ settings.launcher.proxy.port=Port settings.launcher.proxy.socks=Socks settings.launcher.proxy.username=Account settings.launcher.theme=Theme +settings.launcher.version_list_source=Version List Source settings.memory=Game Memory settings.memory.allocate.auto=Minimum %1$.1f GB / Actual %2$.1f GB 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 6038ec4c1..e928ceb32 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -190,6 +190,9 @@ download.failed.refresh=加载版本列表失败,点击此处重试。 download.provider.mcbbs=我的世界中文论坛 (MCBBS, https://www.mcbbs.net/) download.provider.bmclapi=BMCLAPI(bangbang93,https://bmclapi2.bangbang93.com/) download.provider.mojang=官方(OptiFine 自动安装使用 BMCLAPI 下载源) +download.provider.official=尽量使用官方源(最新,但可能加载慢) +download.provider.balanced=选择加载速度快的下载源(平衡,但可能不是最新) +download.provider.mirror=尽量使用镜像源(加载快,但可能不是最新) download.javafx=正在下载 JavaFX 运行时组件 extension.bat=Windows 脚本 @@ -506,6 +509,7 @@ settings.launcher.appearance=外观 settings.launcher.common_path.tooltip=启动器将所有游戏资源及依赖库文件放于此集中管理,如果游戏文件夹内有现成的将不会使用公共库文件 settings.launcher.debug=调试 settings.launcher.download_source=下载源 +settings.launcher.download_source.auto=自动选择下载源 settings.launcher.enable_game_list=在主页内显示版本列表 settings.launcher.font=字体 settings.launcher.language=语言 @@ -525,6 +529,7 @@ settings.launcher.proxy.port=端口 settings.launcher.proxy.socks=Socks settings.launcher.proxy.username=账户 settings.launcher.theme=主题 +settings.launcher.version_list_source=版本列表源 settings.memory=游戏内存 settings.memory.allocate.auto=最低分配 %1$.1f GB / 实际分配 %2$.1f GB diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AutoDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AutoDownloadProvider.java new file mode 100644 index 000000000..bedc1a71e --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/AutoDownloadProvider.java @@ -0,0 +1,59 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui 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 . + */ +package org.jackhuang.hmcl.download; + +/** + * Official Download Provider fetches version list from Mojang and + * download files from mcbbs. + * + * @author huangyuhui + */ +public class AutoDownloadProvider implements DownloadProvider { + private final DownloadProvider versionListProvider; + private final DownloadProvider fileProvider; + + public AutoDownloadProvider(DownloadProvider versionListProvider, DownloadProvider fileProvider) { + this.versionListProvider = versionListProvider; + this.fileProvider = fileProvider; + } + + @Override + public String getVersionListURL() { + return versionListProvider.getVersionListURL(); + } + + @Override + public String getAssetBaseURL() { + return fileProvider.getAssetBaseURL(); + } + + @Override + public String injectURL(String baseURL) { + return fileProvider.injectURL(baseURL); + } + + @Override + public VersionList getVersionListById(String id) { + return versionListProvider.getVersionListById(id); + } + + @Override + public int getConcurrency() { + return fileProvider.getConcurrency(); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BalancedDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BalancedDownloadProvider.java new file mode 100644 index 000000000..0a289917e --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BalancedDownloadProvider.java @@ -0,0 +1,52 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui 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 . + */ +package org.jackhuang.hmcl.download; + +/** + * Official Download Provider fetches version list from Mojang and + * download files from mcbbs. + * + * @author huangyuhui + */ +public class BalancedDownloadProvider implements DownloadProvider { + + @Override + public String getVersionListURL() { + return null; + } + + @Override + public String getAssetBaseURL() { + return null; + } + + @Override + public String injectURL(String baseURL) { + return null; + } + + @Override + public VersionList getVersionListById(String id) { + return null; + } + + @Override + public int getConcurrency() { + return 0; + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MultipleSourceVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MultipleSourceVersionList.java new file mode 100644 index 000000000..5d294f4e2 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MultipleSourceVersionList.java @@ -0,0 +1,21 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui 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 . + */ +package org.jackhuang.hmcl.download; + +public class MultipleSourceVersionList { +}