mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-18 00:10:33 -04:00
add: retry other download source in auto installation
This commit is contained in:
parent
b3bf9d5c94
commit
e68a3c7cd4
@ -79,6 +79,7 @@ public class BMCLAPIDownloadProvider implements DownloadProvider {
|
|||||||
@Override
|
@Override
|
||||||
public String injectURL(String baseURL) {
|
public String injectURL(String baseURL) {
|
||||||
return baseURL
|
return baseURL
|
||||||
|
.replace("https://bmclapi2.bangbang93.com", apiRoot)
|
||||||
.replace("https://launchermeta.mojang.com", apiRoot)
|
.replace("https://launchermeta.mojang.com", apiRoot)
|
||||||
.replace("https://launcher.mojang.com", apiRoot)
|
.replace("https://launcher.mojang.com", apiRoot)
|
||||||
.replace("https://libraries.minecraft.net", apiRoot + "/libraries")
|
.replace("https://libraries.minecraft.net", apiRoot + "/libraries")
|
||||||
|
@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.download;
|
package org.jackhuang.hmcl.download;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The service provider that provides Minecraft online file downloads.
|
* The service provider that provides Minecraft online file downloads.
|
||||||
*
|
*
|
||||||
@ -42,12 +39,6 @@ public interface DownloadProvider {
|
|||||||
*/
|
*/
|
||||||
String injectURL(String baseURL);
|
String injectURL(String baseURL);
|
||||||
|
|
||||||
default Stream<String> injectURLs(String[] baseURLs) {
|
|
||||||
Stream<String> urls = Arrays.stream(baseURLs);
|
|
||||||
Stream<String> jsonURLs = Arrays.stream(baseURLs).map(this::injectURL);
|
|
||||||
return Stream.concat(jsonURLs, urls);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the specific version list that this download provider provides. i.e. "forge", "liteloader", "game", "optifine"
|
* the specific version list that this download provider provides. i.e. "forge", "liteloader", "game", "optifine"
|
||||||
*
|
*
|
||||||
|
@ -31,6 +31,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
|
|||||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>Note</b>: Fabric should be installed first.
|
* <b>Note</b>: Fabric should be installed first.
|
||||||
@ -50,7 +51,9 @@ public final class FabricInstallTask extends Task<Version> {
|
|||||||
this.version = version;
|
this.version = version;
|
||||||
this.remote = remoteVersion;
|
this.remote = remoteVersion;
|
||||||
|
|
||||||
launchMetaTask = new GetTask(NetworkUtils.toURL(dependencyManager.getPrimaryDownloadProvider().injectURL(getLaunchMetaUrl(remote.getGameVersion(), remote.getSelfVersion()))))
|
launchMetaTask = new GetTask(dependencyManager.getPreferredDownloadProviders().stream()
|
||||||
|
.map(downloadProvider -> downloadProvider.injectURL(getLaunchMetaUrl(remote.getGameVersion(), remote.getSelfVersion())))
|
||||||
|
.map(NetworkUtils::toURL).collect(Collectors.toList()))
|
||||||
.setCacheRepository(dependencyManager.getCacheRepository());
|
.setCacheRepository(dependencyManager.getCacheRepository());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +30,7 @@ import org.jackhuang.hmcl.util.io.NetworkUtils;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
@ -92,9 +88,9 @@ public final class ForgeBMCLVersionList extends VersionList<ForgeRemoteVersion>
|
|||||||
+ (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : "");
|
+ (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : "");
|
||||||
String fileName1 = "forge-" + classifier + "-" + file.getCategory() + "." + file.getFormat();
|
String fileName1 = "forge-" + classifier + "-" + file.getCategory() + "." + file.getFormat();
|
||||||
String fileName2 = "forge-" + classifier + "-" + gameVersion + "-" + file.getCategory() + "." + file.getFormat();
|
String fileName2 = "forge-" + classifier + "-" + gameVersion + "-" + file.getCategory() + "." + file.getFormat();
|
||||||
urls.add(apiRoot + "/maven/net/minecraftforge/forge/" + classifier + "-" + gameVersion + "/" + fileName2);
|
urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "-" + gameVersion + "/" + fileName2);
|
||||||
urls.add(apiRoot + "/maven/net/minecraftforge/forge/" + classifier + "/" + fileName1);
|
urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "/" + fileName1);
|
||||||
urls.add(NetworkUtils.withQuery(apiRoot + "/forge/download", mapOf(
|
urls.add(NetworkUtils.withQuery("https://bmclapi2.bangbang93.com/forge/download", mapOf(
|
||||||
pair("mcversion", version.getGameVersion()),
|
pair("mcversion", version.getGameVersion()),
|
||||||
pair("version", version.getVersion()),
|
pair("version", version.getVersion()),
|
||||||
pair("branch", version.getBranch()),
|
pair("branch", version.getBranch()),
|
||||||
|
@ -68,9 +68,9 @@ public final class ForgeInstallTask extends Task<Version> {
|
|||||||
installer = Files.createTempFile("forge-installer", ".jar");
|
installer = Files.createTempFile("forge-installer", ".jar");
|
||||||
|
|
||||||
dependent = new FileDownloadTask(
|
dependent = new FileDownloadTask(
|
||||||
Arrays.stream(remote.getUrl())
|
dependencyManager.getPreferredDownloadProviders().stream()
|
||||||
.map(NetworkUtils::toURL)
|
.flatMap(downloadProvider -> Arrays.stream(remote.getUrl()).map(downloadProvider::injectURL))
|
||||||
.collect(Collectors.toList()),
|
.map(NetworkUtils::toURL).collect(Collectors.toList()),
|
||||||
installer.toFile(), null)
|
installer.toFile(), null)
|
||||||
.setCacheRepository(dependencyManager.getCacheRepository())
|
.setCacheRepository(dependencyManager.getCacheRepository())
|
||||||
.setCaching(true);
|
.setCaching(true);
|
||||||
|
@ -29,6 +29,7 @@ import java.io.File;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Task to download Minecraft jar
|
* Task to download Minecraft jar
|
||||||
@ -58,7 +59,9 @@ public final class GameDownloadTask extends Task<Void> {
|
|||||||
File jar = dependencyManager.getGameRepository().getVersionJar(version);
|
File jar = dependencyManager.getGameRepository().getVersionJar(version);
|
||||||
|
|
||||||
FileDownloadTask task = new FileDownloadTask(
|
FileDownloadTask task = new FileDownloadTask(
|
||||||
NetworkUtils.toURL(dependencyManager.getPrimaryDownloadProvider().injectURL(version.getDownloadInfo().getUrl())),
|
dependencyManager.getPreferredDownloadProviders().stream()
|
||||||
|
.map(downloadProvider -> downloadProvider.injectURL(version.getDownloadInfo().getUrl()))
|
||||||
|
.map(NetworkUtils::toURL).collect(Collectors.toList()),
|
||||||
jar,
|
jar,
|
||||||
IntegrityCheck.of(CacheRepository.SHA1, version.getDownloadInfo().getSha1()))
|
IntegrityCheck.of(CacheRepository.SHA1, version.getDownloadInfo().getSha1()))
|
||||||
.setCaching(true)
|
.setCaching(true)
|
||||||
|
@ -25,13 +25,12 @@ import org.jackhuang.hmcl.task.Task;
|
|||||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
@ -69,8 +68,9 @@ public final class VersionJsonDownloadTask extends Task<String> {
|
|||||||
RemoteVersion remoteVersion = gameVersionList.getVersion(gameVersion, gameVersion)
|
RemoteVersion remoteVersion = gameVersionList.getVersion(gameVersion, gameVersion)
|
||||||
.orElseThrow(() -> new IOException("Cannot find specific version " + gameVersion + " in remote repository"));
|
.orElseThrow(() -> new IOException("Cannot find specific version " + gameVersion + " in remote repository"));
|
||||||
dependencies.add(new GetTask(
|
dependencies.add(new GetTask(
|
||||||
dependencyManager.getPrimaryDownloadProvider().injectURLs(remoteVersion.getUrl())
|
dependencyManager.getPreferredDownloadProviders().stream()
|
||||||
.map(NetworkUtils::toURL).collect(Collectors.toList()),
|
.flatMap(downloadProvider -> Arrays.stream(remoteVersion.getUrl()).map(downloadProvider::injectURL))
|
||||||
UTF_8).storeTo(this::setResult));
|
.map(NetworkUtils::toURL).collect(Collectors.toList())
|
||||||
|
).storeTo(this::setResult));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ public final class LiteLoaderBMCLVersionList extends VersionList<LiteLoaderRemot
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
String version = v.getVersion();
|
String version = v.getVersion();
|
||||||
String url = downloadProvider.getApiRoot() + "/liteloader/download?version=" + version;
|
String url = "https://bmclapi2.bangbang93.com/liteloader/download?version=" + version;
|
||||||
if (snapshot) {
|
if (snapshot) {
|
||||||
try {
|
try {
|
||||||
version = version.replace("SNAPSHOT", getLatestSnapshotVersion(repository.getUrl() + "com/mumfrey/liteloader/" + v.getVersion() + "/"));
|
version = version.replace("SNAPSHOT", getLatestSnapshotVersion(repository.getUrl() + "com/mumfrey/liteloader/" + v.getVersion() + "/"));
|
||||||
@ -101,7 +101,7 @@ public final class LiteLoaderBMCLVersionList extends VersionList<LiteLoaderRemot
|
|||||||
}
|
}
|
||||||
|
|
||||||
versions.put(key, new LiteLoaderRemoteVersion(gameVersion,
|
versions.put(key, new LiteLoaderRemoteVersion(gameVersion,
|
||||||
version, downloadProvider.injectURL(url),
|
version, url,
|
||||||
v.getTweakClass(), v.getLibraries()
|
v.getTweakClass(), v.getLibraries()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
|
|||||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -71,7 +67,7 @@ public final class OptiFineBMCLVersionList extends VersionList<OptiFineRemoteVer
|
|||||||
}.getType());
|
}.getType());
|
||||||
for (OptiFineVersion element : root) {
|
for (OptiFineVersion element : root) {
|
||||||
String version = element.getType() + "_" + element.getPatch();
|
String version = element.getType() + "_" + element.getPatch();
|
||||||
String mirror = apiRoot + "/optifine/" + element.getGameVersion() + "/" + element.getType() + "/" + element.getPatch();
|
String mirror = "https://bmclapi2.bangbang93.com/optifine/" + element.getGameVersion() + "/" + element.getType() + "/" + element.getPatch();
|
||||||
if (!duplicates.add(mirror))
|
if (!duplicates.add(mirror))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -96,7 +96,9 @@ public final class OptiFineInstallTask extends Task<Version> {
|
|||||||
|
|
||||||
if (installer == null) {
|
if (installer == null) {
|
||||||
dependents.add(new FileDownloadTask(
|
dependents.add(new FileDownloadTask(
|
||||||
Arrays.stream(remote.getUrl()).map(NetworkUtils::toURL).collect(Collectors.toList()),
|
dependencyManager.getPreferredDownloadProviders().stream()
|
||||||
|
.flatMap(downloadProvider -> Arrays.stream(remote.getUrl()).map(downloadProvider::injectURL))
|
||||||
|
.map(NetworkUtils::toURL).collect(Collectors.toList()),
|
||||||
dest.toFile(), null)
|
dest.toFile(), null)
|
||||||
.setCacheRepository(dependencyManager.getCacheRepository())
|
.setCacheRepository(dependencyManager.getCacheRepository())
|
||||||
.setCaching(true));
|
.setCaching(true));
|
||||||
|
@ -207,7 +207,6 @@ public class FileDownloadTask extends Task<Void> {
|
|||||||
checkETag = true;
|
checkETag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.LOG.log(Level.FINER, "Downloading " + urls.get(0) + " to " + file);
|
|
||||||
Exception exception = null;
|
Exception exception = null;
|
||||||
URL failedURL = null;
|
URL failedURL = null;
|
||||||
|
|
||||||
@ -217,6 +216,7 @@ public class FileDownloadTask extends Task<Void> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logging.LOG.log(Level.FINER, "Downloading " + url + " to " + file);
|
||||||
Path temp = null;
|
Path temp = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -53,22 +53,21 @@ public final class GetTask extends Task<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GetTask(URL url, Charset charset) {
|
public GetTask(URL url, Charset charset) {
|
||||||
this(url, charset, 5);
|
this(url, charset, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GetTask(URL url, Charset charset, int retry) {
|
public GetTask(URL url, Charset charset, int retry) {
|
||||||
this.urls = Collections.singletonList(url);
|
this(Collections.singletonList(url), charset, retry);
|
||||||
this.charset = charset;
|
|
||||||
this.retry = retry;
|
|
||||||
|
|
||||||
setName(url.toString());
|
|
||||||
setExecutor(Schedulers.io());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GetTask(List<URL> urls, Charset charset) {
|
public GetTask(List<URL> url) {
|
||||||
|
this(url, UTF_8, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GetTask(List<URL> urls, Charset charset, int retry) {
|
||||||
this.urls = new ArrayList<>(urls);
|
this.urls = new ArrayList<>(urls);
|
||||||
this.charset = charset;
|
this.charset = charset;
|
||||||
this.retry = urls.size();
|
this.retry = retry;
|
||||||
|
|
||||||
setName(urls.get(0).toString());
|
setName(urls.get(0).toString());
|
||||||
setExecutor(Schedulers.io());
|
setExecutor(Schedulers.io());
|
||||||
@ -84,8 +83,12 @@ public final class GetTask extends Task<String> {
|
|||||||
Exception exception = null;
|
Exception exception = null;
|
||||||
URL failedURL = null;
|
URL failedURL = null;
|
||||||
boolean checkETag = true;
|
boolean checkETag = true;
|
||||||
for (int time = 0; time < retry; ++time) {
|
for (int time = 0; time < retry * urls.size(); ++time) {
|
||||||
URL url = urls.get(time % urls.size());
|
URL url = urls.get(time / retry);
|
||||||
|
if (isCancelled()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
updateProgress(0);
|
updateProgress(0);
|
||||||
HttpURLConnection conn = NetworkUtils.createConnection(url);
|
HttpURLConnection conn = NetworkUtils.createConnection(url);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user