diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/AssetsMojangLoader.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/AssetsMojangLoader.java index ad24a5015..126788fd4 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/AssetsMojangLoader.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/AssetsMojangLoader.java @@ -98,7 +98,7 @@ public class AssetsMojangLoader extends IAssetsHandler { @Override public Task getDownloadTask(IDownloadProvider sourceType) { - return new AssetsTask(sourceType.getAssetsDownloadURL()); + return new AssetsTask(sourceType.getAssetsDownloadURL(), sourceType.getRetryAssetsDownloadURL()); } @Override diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/IAssetsHandler.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/IAssetsHandler.java index 7302fba16..96b772a56 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/IAssetsHandler.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/IAssetsHandler.java @@ -34,6 +34,8 @@ import org.jackhuang.hellominecraft.util.code.DigestUtils; import org.jackhuang.hellominecraft.util.system.IOUtils; import org.jackhuang.hellominecraft.util.NetUtils; import org.jackhuang.hellominecraft.util.OverridableSwingWorker; +import org.jackhuang.hellominecraft.util.StrUtils; +import org.jackhuang.hellominecraft.util.func.Function; import org.jackhuang.hellominecraft.util.tasks.TaskInfo; /** @@ -89,30 +91,37 @@ public abstract class IAssetsHandler { protected class AssetsTask extends TaskInfo { - ArrayList al; - String u; + ArrayList tasks; + String baseUrl; + String retryBaseUrl; - public AssetsTask(String url) { + public AssetsTask(String url, String retryUrl) { super(C.i18n("assets.download")); - this.u = url; + this.baseUrl = url; + this.retryBaseUrl = retryUrl; } @Override public void executeTask() { if (assetsDownloadURLs == null || assetsLocalNames == null || contents == null) throw new IllegalStateException(C.i18n("assets.not_refreshed")); + + tasks = new ArrayList<>(); int max = assetsDownloadURLs.size(); - al = new ArrayList<>(); int hasDownloaded = 0; for (int i = 0; i < max; i++) { String mark = assetsDownloadURLs.get(i); - String url = u + mark; + String downloadUrl = baseUrl + mark; + String downloadRetryUrl = StrUtils.isNotBlank(retryBaseUrl) ? retryBaseUrl + mark : ""; File location = assetsLocalNames.get(i); + if (!location.getParentFile().exists() && !location.getParentFile().mkdirs()) HMCLog.warn("Failed to make directories: " + location.getParent()); + if (location.isDirectory()) continue; - boolean need = true; + + boolean needDownload = true; try { if (location.exists()) { FileInputStream fis = new FileInputStream(location); @@ -121,23 +130,39 @@ public abstract class IAssetsHandler { if (contents.get(i).geteTag().equals(sha)) { ++hasDownloaded; HMCLog.log("File " + assetsLocalNames.get(i) + " has been downloaded successfully, skipped downloading."); - if (ppl != null) + if (ppl != null) { ppl.setProgress(this, hasDownloaded, max); + } continue; } } } catch (IOException e) { HMCLog.warn("Failed to get hash: " + location, e); - need = !location.exists(); + needDownload = !location.exists(); } - if (need) - al.add(new FileDownloadTask(url, location).setTag(mark)); + + if (needDownload) { + FileDownloadTask fileDownloadTask = new FileDownloadTask(downloadUrl, location); + fileDownloadTask.setTag(mark); + + // retry + if (StrUtils.isNotBlank(downloadRetryUrl)) { + fileDownloadTask.setFailedCallbackReturnsNewURL(new Function() { + @Override + public String apply(Integer t) { + return downloadRetryUrl; + } + }); + } + + tasks.add(fileDownloadTask); + } } } @Override public Collection getAfterTasks() { - return al; + return tasks; } } } diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/MinecraftAssetService.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/MinecraftAssetService.java index 626dbe7cf..6070e8117 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/MinecraftAssetService.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/asset/MinecraftAssetService.java @@ -56,7 +56,8 @@ public class MinecraftAssetService extends IMinecraftAssetService { public Task downloadAssets(final MinecraftVersion mv) { if (mv == null) return null; - return IAssetsHandler.ASSETS_HANDLER.getList(mv, service.asset()).after(IAssetsHandler.ASSETS_HANDLER.getDownloadTask(service.getDownloadType().getProvider())); + return IAssetsHandler.ASSETS_HANDLER.getList(mv, service.asset()) + .after(IAssetsHandler.ASSETS_HANDLER.getDownloadTask(service.getDownloadType().getProvider())); } @Override diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DownloadLibraryJob.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DownloadLibraryJob.java index 7c5e28592..a3735004d 100644 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DownloadLibraryJob.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DownloadLibraryJob.java @@ -29,10 +29,12 @@ public class DownloadLibraryJob { public IMinecraftLibrary lib; public String url; + public String retryUrl; public File path; - public DownloadLibraryJob(IMinecraftLibrary n, String u, File p) { + public DownloadLibraryJob(IMinecraftLibrary n, String u, String retry, File p) { url = u; + retryUrl = retry; lib = n; path = IOUtils.tryGetCanonicalFile(p); } diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DownloadType.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DownloadType.java index 1a7644ef7..14e1711e6 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DownloadType.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DownloadType.java @@ -29,7 +29,8 @@ public enum DownloadType { Mojang("download.mojang", new MojangDownloadProvider()), BMCL("download.BMCL", new BMCLAPIDownloadProvider()), //RapidData("download.rapid_data", new RapidDataDownloadProvider()), - Curse("Curse CDN", new CurseDownloadProvider()); + Curse("Curse CDN", new CurseDownloadProvider()), + Dynamic(DynamicDownloadProvider.getInstance().getName(), DynamicDownloadProvider.getInstance()); private final String name; private final IDownloadProvider provider; @@ -47,7 +48,7 @@ public enum DownloadType { return C.i18n(name); } - private static DownloadType suggestedDownloadType = Mojang; + private static DownloadType suggestedDownloadType = Dynamic; public static DownloadType getSuggestedDownloadType() { return suggestedDownloadType; diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DynamicDownloadProvider.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DynamicDownloadProvider.java new file mode 100644 index 000000000..29523ab00 --- /dev/null +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/DynamicDownloadProvider.java @@ -0,0 +1,149 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2013 huangyuhui + * + * 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 {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hellominecraft.launcher.core.download; + +import com.google.gson.reflect.TypeToken; +import java.io.IOException; +import java.util.Map; +import org.jackhuang.hellominecraft.util.C; +import org.jackhuang.hellominecraft.util.NetUtils; +import org.jackhuang.hellominecraft.util.StrUtils; + +/** + * + * @author evilwk + */ +public class DynamicDownloadProvider extends MojangDownloadProvider { + + private static final String PROVIDER_ADDR = "http://localhost/provider.php"; + + private volatile static DynamicDownloadProvider instance; + + private String librariesAddr = null; + private String assetsAddr = null; + private String name = "MCHost"; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String getLibrariesAddr() { + return librariesAddr; + } + + public void setLibrariesAddr(String librariesAddr) { + this.librariesAddr = librariesAddr; + } + + public String getAssetsAddr() { + return assetsAddr; + } + + public void setAssetsAddr(String assetsAddr) { + this.assetsAddr = assetsAddr; + } + + + private DynamicDownloadProvider() { + + } + + public static DynamicDownloadProvider getInstance() { + if (instance == null) { + synchronized (DynamicDownloadProvider.class) { + if (instance == null) { + instance = new DynamicDownloadProvider(); + } + } + } + return instance; + } + + @Override + public String getRetryAssetsDownloadURL() { + return super.getAssetsDownloadURL(); + } + + @Override + public String getRetryLibraryDownloadURL() { + return super.getLibraryDownloadURL(); + } + + @Override + public String getAssetsDownloadURL() { + if (StrUtils.isNotBlank(assetsAddr)) { + return assetsAddr; + } + return super.getAssetsDownloadURL(); + } + + @Override + public String getLibraryDownloadURL() { + if (StrUtils.isNotBlank(librariesAddr)) { + return librariesAddr; + } + return super.getLibraryDownloadURL(); + } + + @Override + public String getParsedDownloadURL(String str) { + if (StrUtils.isNotBlank(librariesAddr)) { + str = str.replace("https://libraries.minecraft.net", librariesAddr); + } + return super.getParsedDownloadURL(str); + } + + public void init() { + new Thread() { + @Override + public void run() { + try { + String providerInfo = NetUtils.get(PROVIDER_ADDR); + Map addrInfo = null; + addrInfo = C.GSON.fromJson(providerInfo, new TypeToken>(){}.getType()); + if (addrInfo != null) { + if (addrInfo.containsKey("libraries")) { + String librariesAddr = addrInfo.get("libraries"); + if (StrUtils.isNotBlank(librariesAddr)) { + DynamicDownloadProvider.this.setLibrariesAddr(librariesAddr); + } + } + if (addrInfo.containsKey("assets")) { + String assetsAddr = addrInfo.get("assets"); + if (StrUtils.isNotBlank(assetsAddr)) { + DynamicDownloadProvider.this.setAssetsAddr(assetsAddr); + } + } + if (addrInfo.containsKey("name")) { + String name = addrInfo.get("name"); + if (StrUtils.isNotBlank(name)) { + DynamicDownloadProvider.this.setName(name); + } + } + } + } catch (IOException ex) { + + } + } + }.start(); + } +} diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/IDownloadProvider.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/IDownloadProvider.java index b6142969d..2d01c09b9 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/IDownloadProvider.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/IDownloadProvider.java @@ -38,7 +38,7 @@ public abstract class IDownloadProvider { return null; } } - + public abstract InstallerVersionList getForgeInstaller(); public abstract InstallerVersionList getLiteLoaderInstaller(); @@ -46,6 +46,10 @@ public abstract class IDownloadProvider { public abstract InstallerVersionList getOptiFineInstaller(); public abstract String getLibraryDownloadURL(); + + public String getRetryLibraryDownloadURL() { + return ""; + } public abstract String getVersionsDownloadURL(); @@ -55,6 +59,10 @@ public abstract class IDownloadProvider { public abstract String getAssetsDownloadURL(); + public String getRetryAssetsDownloadURL() { + return ""; + } + /** * For example, minecraft.json/assetIndex/url or * minecraft.json/downloads/client/url diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MinecraftDownloadService.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MinecraftDownloadService.java index 478ce10f5..e8c5feb51 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MinecraftDownloadService.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MinecraftDownloadService.java @@ -31,6 +31,7 @@ import org.jackhuang.hellominecraft.launcher.core.GameException; import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService; import org.jackhuang.hellominecraft.launcher.core.version.GameDownloadInfo; import org.jackhuang.hellominecraft.launcher.core.version.IMinecraftLibrary; +import org.jackhuang.hellominecraft.launcher.core.version.LibraryDownloadInfo; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask; import org.jackhuang.hellominecraft.util.func.Function; @@ -53,14 +54,17 @@ public class MinecraftDownloadService extends IMinecraftDownloadService { ArrayList downloadLibraries = new ArrayList<>(); if (mv == null) return downloadLibraries; + MinecraftVersion v = mv.resolve(service.version()); - for (IMinecraftLibrary l : v.getLibraries()) - if (l != null && l.allow() && l.getDownloadInfo() != null) { - File ff = l.getFilePath(service.baseDirectory()); + for (IMinecraftLibrary libraryInfo : v.getLibraries()) + if (libraryInfo != null && libraryInfo.allow() && libraryInfo.getDownloadInfo() != null) { + File ff = libraryInfo.getFilePath(service.baseDirectory()); if (!ff.exists()) { - String libURL = l.getDownloadInfo().getUrl(service.getDownloadType()); - if (libURL != null) - downloadLibraries.add(new DownloadLibraryJob(l, libURL, ff)); + LibraryDownloadInfo downloadInfo = libraryInfo.getDownloadInfo(); + String downloadUrl = downloadInfo.getUrl(service.getDownloadType()); + String retryDownloadUrl = downloadInfo.getRetryUrl(service.getDownloadType()); + if (downloadUrl != null) + downloadLibraries.add(new DownloadLibraryJob(libraryInfo, downloadUrl, retryDownloadUrl, ff)); } } return downloadLibraries; @@ -114,10 +118,13 @@ public class MinecraftDownloadService extends IMinecraftDownloadService { } @Override - public String apply(Integer t) { - return DownloadType.values()[t / 2].getProvider().getVersionsDownloadURL() + suffix; + public String apply(Integer repeat) { + int index = repeat / 2; + if (index > DownloadType.values().length) { + index = 0; + } + return DownloadType.values()[index].getProvider().getVersionsDownloadURL() + suffix; } - } @Override diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MojangDownloadProvider.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MojangDownloadProvider.java index 6882922dd..aa015fe75 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MojangDownloadProvider.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MojangDownloadProvider.java @@ -41,27 +41,32 @@ public class MojangDownloadProvider extends IDownloadProvider { public InstallerVersionList getOptiFineInstaller() { return org.jackhuang.hellominecraft.launcher.core.install.optifine.vanilla.OptiFineVersionList.getInstance(); } - + + // jars @Override public String getLibraryDownloadURL() { return "https://libraries.minecraft.net"; } + // jars @Override public String getVersionsDownloadURL() { return "http://s3.amazonaws.com/Minecraft.Download/versions/"; } - + + // resource @Override public String getIndexesDownloadURL() { return "http://s3.amazonaws.com/Minecraft.Download/indexes/"; } - + + // game versions json @Override public String getVersionsListDownloadURL() { return "https://launchermeta.mojang.com/mc/game/version_manifest.json"; } - + + // resource @Override public String getAssetsDownloadURL() { return "https://resources.download.minecraft.net/"; diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/launch/LibraryDownloadTask.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/launch/LibraryDownloadTask.java index 3cd1cfbb9..c088f74ed 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/launch/LibraryDownloadTask.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/launch/LibraryDownloadTask.java @@ -21,6 +21,8 @@ import java.io.File; import java.net.URL; import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.launcher.core.download.DownloadLibraryJob; +import org.jackhuang.hellominecraft.util.StrUtils; +import org.jackhuang.hellominecraft.util.func.Function; import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask; /** @@ -49,12 +51,20 @@ public class LibraryDownloadTask extends FileDownloadTask { if (s.length == 3 && s[2].length() > 3) job.url = "http://dl.liteloader.com/versions/com/mumfrey/liteloader/" + s[2].substring(0, s[2].length() - 3) + "/liteloader-" + s[2] + ".jar"; } - download(new URL(job.url), job.path); + download(new URL(job.url), job.retryUrl, job.path); } - void download(URL url, File filePath) throws Throwable { + void download(URL url, String retryUrl, File filePath) throws Throwable { this.url = url; this.filePath = filePath; + if (StrUtils.isNotBlank(retryUrl)) { + this.failedCallbackReturnsNewURL = new Function() { + @Override + public String apply(Integer t) { + return retryUrl; + } + }; + } super.executeTask(); } diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/LibraryDownloadInfo.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/LibraryDownloadInfo.java index f2cb07a3e..7ae1f8960 100644 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/LibraryDownloadInfo.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/LibraryDownloadInfo.java @@ -19,6 +19,7 @@ package org.jackhuang.hellominecraft.launcher.core.version; import com.google.gson.annotations.SerializedName; import org.jackhuang.hellominecraft.launcher.core.download.DownloadType; +import org.jackhuang.hellominecraft.launcher.core.download.IDownloadProvider; import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.util.system.IOUtils; @@ -35,14 +36,36 @@ public class LibraryDownloadInfo extends GameDownloadInfo { @Override public String getUrl(DownloadType dt, boolean allowSelf) { - String myURL = (forgeURL == null ? dt.getProvider().getLibraryDownloadURL() : forgeURL); - if (StrUtils.isNotBlank(url) && allowSelf) - myURL = url; - if (!myURL.endsWith(".jar")) + IDownloadProvider provider = dt.getProvider(); + String downloadUrl = (forgeURL == null ? provider.getLibraryDownloadURL() : forgeURL); + if (StrUtils.isNotBlank(url) && allowSelf) { + downloadUrl = provider.getParsedDownloadURL(url); + } + return getUrlWithBaseUrl(downloadUrl); + } + + public String getUrlWithBaseUrl(String baseUrl) { + if (!baseUrl.endsWith(".jar")) { if (path == null) return null; else - myURL = IOUtils.addURLSeparator(myURL) + path.replace('\\', '/'); - return myURL; - } + baseUrl = IOUtils.addURLSeparator(baseUrl) + path.replace('\\', '/'); + } + return baseUrl; + } + + public String getRetryUrl(DownloadType dt) { + IDownloadProvider provider = dt.getProvider(); + String retryBaseUrl = provider.getRetryLibraryDownloadURL(); + if (StrUtils.isBlank(retryBaseUrl)) { + return null; + } + + String downloadUrl = (forgeURL == null ? retryBaseUrl : forgeURL); + if (StrUtils.isNotBlank(url) && provider.isAllowedToUseSelfURL()) { + downloadUrl = url; + } + + return getUrlWithBaseUrl(downloadUrl); + } } diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftLibrary.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftLibrary.java index 5c6baede3..b4266a53c 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftLibrary.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftLibrary.java @@ -48,29 +48,25 @@ public class MinecraftLibrary extends IMinecraftLibrary { public MinecraftLibrary(ArrayList rules, String url, Natives natives, String name, Extract extract, LibraryDownloadInfo downloads) { super(name); - this.rules = rules == null ? null : (ArrayList) rules.clone(); + this.rules = (rules == null) ? null : (ArrayList) rules.clone(); this.url = url; - this.natives = natives == null ? null : (Natives) natives.clone(); - this.extract = extract == null ? null : (Extract) extract.clone(); + this.natives = (natives == null) ? null : (Natives) natives.clone(); + this.extract = (extract == null) ? null : (Extract) extract.clone(); } - /** - * is the library allowed to load. - * - * @return - */ @Override public boolean allow() { if (rules != null) { boolean flag = false; - for (Rules r : rules) + for (Rules r : rules) { if ("disallow".equals(r.action())) return false; else if ("allow".equals(r.action())) flag = true; + } return flag; - } else - return true; + } + return true; } private String formatArch(String nati) { @@ -95,19 +91,24 @@ public class MinecraftLibrary extends IMinecraftLibrary { public String formatName() { String[] s = name.split(":"); - if (s.length < 3) + if (s.length < 3) { return null; + } + StringBuilder sb = new StringBuilder(s[0].replace('.', '/')).append('/').append(s[1]).append('/').append(s[2]).append('/').append(s[1]).append('-').append(s[2]); - if (natives != null) + if (natives != null) { sb.append('-').append(getNative()); + } + return sb.append(".jar").toString(); } @Override public File getFilePath(File gameDir) { LibraryDownloadInfo info = getDownloadInfo(); - if (info == null) + if (info == null) { return null; + } return new File(gameDir, "libraries/" + info.path); } @@ -117,25 +118,34 @@ public class MinecraftLibrary extends IMinecraftLibrary { } public LibraryDownloadInfo getDownloadInfo() { - if (downloads == null) + if (downloads == null) { downloads = new LibrariesDownloadInfo(); - LibraryDownloadInfo info; + } + + LibraryDownloadInfo info = null; if (natives != null) { - if (downloads.classifiers == null) + if (downloads.classifiers == null) { downloads.classifiers = new HashMap<>(); - if (!downloads.classifiers.containsKey(getNative())) - downloads.classifiers.put(getNative(), info = new LibraryDownloadInfo()); - else - info = downloads.classifiers.get(getNative()); - } else if (downloads.artifact == null) + } else { + if (!downloads.classifiers.containsKey(getNative())) { + downloads.classifiers.put(getNative(), info = new LibraryDownloadInfo()); + } else { + info = downloads.classifiers.get(getNative()); + } + } + } else if (downloads.artifact == null) { downloads.artifact = info = new LibraryDownloadInfo(); - else + } else { info = downloads.artifact; + } + if (StrUtils.isBlank(info.path)) { info.path = formatName(); - if (info.path == null) + if (info.path == null) { return null; + } } + info.forgeURL = this.url; return info; } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java index a4e8d2689..fbe1709cd 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java @@ -59,144 +59,147 @@ import org.jackhuang.hellominecraft.util.VersionNumber; */ public final class Main implements Runnable { - private static final X509TrustManager XTM = new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) { - } + private static final X509TrustManager XTM = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) { - } + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - }; - private static final HostnameVerifier HNV = (hostname, session) -> true; + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + }; + private static final HostnameVerifier HNV = (hostname, session) -> true; - static { - SSLContext sslContext = null; + static { + SSLContext sslContext = null; - try { - sslContext = SSLContext.getInstance("TLS"); - X509TrustManager[] xtmArray = new X509TrustManager[] { XTM }; - sslContext.init(null, xtmArray, new java.security.SecureRandom()); - } catch (GeneralSecurityException gse) { - } - if (sslContext != null) - HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + try { + sslContext = SSLContext.getInstance("TLS"); + X509TrustManager[] xtmArray = new X509TrustManager[]{XTM}; + sslContext.init(null, xtmArray, new java.security.SecureRandom()); + } catch (GeneralSecurityException gse) { + } + if (sslContext != null) { + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + } - HttpsURLConnection.setDefaultHostnameVerifier(HNV); - } + HttpsURLConnection.setDefaultHostnameVerifier(HNV); + } - public static final String LAUNCHER_NAME = "Hello Minecraft! Launcher"; - public static final String LAUNCHER_VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@"; - public static final int MINIMUM_LAUNCHER_VERSION = 16; + public static final String LAUNCHER_NAME = "Hello Minecraft! Launcher"; + public static final String LAUNCHER_VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@"; + public static final int MINIMUM_LAUNCHER_VERSION = 16; - public static VersionNumber getVersionNumber() { - return VersionNumber.check(LAUNCHER_VERSION); - } + public static VersionNumber getVersionNumber() { + return VersionNumber.check(LAUNCHER_VERSION); + } - /** - * Make the main window title. - * - * @return the MainWindow title. - */ - public static String makeTitle() { - return LAUNCHER_NAME + ' ' + LAUNCHER_VERSION; - } + /** + * Make the main window title. + * + * @return the MainWindow title. + */ + public static String makeTitle() { + return LAUNCHER_NAME + ' ' + LAUNCHER_VERSION; + } - public static String shortTitle() { - return "HMCL" + ' ' + LAUNCHER_VERSION; - } + public static String shortTitle() { + return "HMCL" + ' ' + LAUNCHER_VERSION; + } - public static final Main INSTANCE = new Main(); - private static HelloMinecraftLookAndFeel LOOK_AND_FEEL; + public static final Main INSTANCE = new Main(); + private static HelloMinecraftLookAndFeel LOOK_AND_FEEL; - private static final Logger LOGGER = Logger.getLogger(Main.class.getName()); + private static final Logger LOGGER = Logger.getLogger(Main.class.getName()); - @SuppressWarnings({ "CallToPrintStackTrace", "UseSpecificCatch" }) - public static void main(String[] args) throws IOException { - { - PluginManager.getPlugin(DefaultPlugin.class); - if (IUpgrader.NOW_UPGRADER.parseArguments(getVersionNumber(), args)) - return; + @SuppressWarnings({"CallToPrintStackTrace", "UseSpecificCatch"}) + public static void main(String[] args) throws IOException { + PluginManager.getPlugin(DefaultPlugin.class); + if (IUpgrader.NOW_UPGRADER.parseArguments(getVersionNumber(), args)) { + return; + } - System.setProperty("awt.useSystemAAFontSettings", "on"); - System.setProperty("swing.aatext", "true"); - System.setProperty("sun.java2d.noddraw", "true"); - System.setProperty("sun.java2d.dpiaware", "false"); - Thread.setDefaultUncaughtExceptionHandler(new CrashReporter(true)); + System.setProperty("awt.useSystemAAFontSettings", "on"); + System.setProperty("swing.aatext", "true"); + System.setProperty("sun.java2d.noddraw", "true"); + System.setProperty("sun.java2d.dpiaware", "false"); + Thread.setDefaultUncaughtExceptionHandler(new CrashReporter(true)); - try { - File file = new File("hmcl.log"); - if (!file.exists() && !file.createNewFile()) - HMCLog.warn("Failed to create log file " + file); - Configuration.DEFAULT.appenders.add(new ConsoleAppender("File", new DefaultLayout(), true, new FileOutputStream(file), true)); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Failed to add log appender File because an error occurred while creating or opening hmcl.log", ex); - } + try { + File file = new File("hmcl.log"); + if (!file.exists() && !file.createNewFile()) { + HMCLog.warn("Failed to create log file " + file); + } + Configuration.DEFAULT.appenders.add(new ConsoleAppender("File", new DefaultLayout(), true, new FileOutputStream(file), true)); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Failed to add log appender File because an error occurred while creating or opening hmcl.log", ex); + } - HMCLog.log("*** " + Main.makeTitle() + " ***"); + HMCLog.log("*** " + Main.makeTitle() + " ***"); - String s = Settings.getInstance().getLocalization(); - for (SupportedLocales sl : SupportedLocales.values()) - if (sl.name().equals(s)) { - SupportedLocales.NOW_LOCALE = sl; - Locale.setDefault(sl.self); - } + String s = Settings.getInstance().getLocalization(); + for (SupportedLocales sl : SupportedLocales.values()) { + if (sl.name().equals(s)) { + SupportedLocales.NOW_LOCALE = sl; + Locale.setDefault(sl.self); + } + } - LogWindow.INSTANCE.clean(); - LogWindow.INSTANCE.setTerminateGame(GameLauncher.PROCESS_MANAGER::stopAllProcesses); + LogWindow.INSTANCE.clean(); + LogWindow.INSTANCE.setTerminateGame(GameLauncher.PROCESS_MANAGER::stopAllProcesses); - try { - LOOK_AND_FEEL = new HelloMinecraftLookAndFeel(Settings.getInstance().getTheme().settings); - UIManager.setLookAndFeel(LOOK_AND_FEEL); - } catch (ParseException | UnsupportedLookAndFeelException ex) { - HMCLog.warn("Failed to set look and feel...", ex); - } + try { + LOOK_AND_FEEL = new HelloMinecraftLookAndFeel(Settings.getInstance().getTheme().settings); + UIManager.setLookAndFeel(LOOK_AND_FEEL); + } catch (ParseException | UnsupportedLookAndFeelException ex) { + HMCLog.warn("Failed to set look and feel...", ex); + } - Settings.UPDATE_CHECKER.outdated.register(IUpgrader.NOW_UPGRADER); - Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute(); + Settings.UPDATE_CHECKER.outdated.register(IUpgrader.NOW_UPGRADER); + Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute(); - if (StrUtils.isNotBlank(Settings.getInstance().getProxyHost()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPort()) && MathUtils.canParseInt(Settings.getInstance().getProxyPort())) { - HMCLog.log("Initializing customized proxy"); - System.setProperty("http.proxyHost", Settings.getInstance().getProxyHost()); - System.setProperty("http.proxyPort", Settings.getInstance().getProxyPort()); - if (StrUtils.isNotBlank(Settings.getInstance().getProxyUserName()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPassword())) - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(Settings.getInstance().getProxyUserName(), Settings.getInstance().getProxyPassword().toCharArray()); - } - }); - } + if (StrUtils.isNotBlank(Settings.getInstance().getProxyHost()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPort()) && MathUtils.canParseInt(Settings.getInstance().getProxyPort())) { + HMCLog.log("Initializing customized proxy"); + System.setProperty("http.proxyHost", Settings.getInstance().getProxyHost()); + System.setProperty("http.proxyPort", Settings.getInstance().getProxyPort()); + if (StrUtils.isNotBlank(Settings.getInstance().getProxyUserName()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPassword())) { + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(Settings.getInstance().getProxyUserName(), Settings.getInstance().getProxyPassword().toCharArray()); + } + }); + } + } - try { - PluginManager.plugin().showUI(); - } catch (Throwable t) { - new CrashReporter(false).uncaughtException(Thread.currentThread(), t); - System.exit(1); - } - } - } + try { + PluginManager.plugin().showUI(); + } catch (Throwable t) { + new CrashReporter(false).uncaughtException(Thread.currentThread(), t); + System.exit(1); + } + } - @Override - public void run() { - GameLauncher.PROCESS_MANAGER.stopAllProcesses(); - } + @Override + public void run() { + GameLauncher.PROCESS_MANAGER.stopAllProcesses(); + } - public static void invokeUpdate() { - MainFrame.INSTANCE.invokeUpdate(); - } + public static void invokeUpdate() { + MainFrame.INSTANCE.invokeUpdate(); + } - public static ImageIcon getIcon(String path) { - try { - return new ImageIcon(Main.class.getResource("/org/jackhuang/hellominecraft/launcher/" + path)); - } catch (Exception e) { - HMCLog.err("Failed to load icon", e); - return null; - } - } + public static ImageIcon getIcon(String path) { + try { + return new ImageIcon(Main.class.getResource("/org/jackhuang/hellominecraft/launcher/" + path)); + } catch (Exception e) { + HMCLog.err("Failed to load icon", e); + return null; + } + } } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Config.java index 1657642f9..88d94c892 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Config.java @@ -193,7 +193,8 @@ public final class Config implements Cloneable { public Config() { clientToken = UUID.randomUUID().toString(); - logintype = downloadtype = 0; + logintype = 0; + downloadtype = DownloadType.Dynamic.ordinal(); enableShadow = false; enableAnimation = true; theme = 4; @@ -203,7 +204,7 @@ public final class Config implements Cloneable { public DownloadType getDownloadSource() { if (downloadtype >= DownloadType.values().length || downloadtype < 0) { - downloadtype = 0; + downloadtype = DownloadType.Dynamic.ordinal(); Settings.save(); } return DownloadType.values()[downloadtype]; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Settings.java index 2dcdbaccf..e05c5adf3 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Settings.java @@ -22,6 +22,8 @@ import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.util.logging.HMCLog; import org.jackhuang.hellominecraft.launcher.Main; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainFrame.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainFrame.java index aae86082a..641f4eb59 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainFrame.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainFrame.java @@ -48,6 +48,7 @@ import org.jackhuang.hellominecraft.util.logging.HMCLog; import org.jackhuang.hellominecraft.launcher.Main; import org.jackhuang.hellominecraft.launcher.setting.Settings; import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator; +import org.jackhuang.hellominecraft.launcher.core.download.DynamicDownloadProvider; import org.jackhuang.hellominecraft.util.ui.GraphicsUtils; import org.jackhuang.hellominecraft.lookandfeel.Theme; import org.jackhuang.hellominecraft.util.MessageBox; @@ -85,23 +86,27 @@ public final class MainFrame extends DraggableFrame { setUndecorated(!Settings.getInstance().isDecorated()); defaultTitle = isUndecorated() ? Main.makeTitle() : ""; enableShadow = Settings.getInstance().isEnableShadow() && isUndecorated(); - if (enableShadow) - setContentSize(834, 542); - else + if (enableShadow) { + setContentSize(834, 542); + } else { setContentSize(802, 511); + } + setDefaultCloseOperation(EXIT_ON_CLOSE); setTitle(Main.makeTitle()); initComponents(); loadBackground(); + + DynamicDownloadProvider.getInstance().init(); setLocationRelativeTo(null); - if (MainFrame.this.isUndecorated()) + if (MainFrame.this.isUndecorated()) { setResizable(false); + } this.addWindowListener(new WindowListener() { @Override - public void windowOpened(WindowEvent e) { - } + public void windowOpened(WindowEvent e) { } @Override public void windowClosing(WindowEvent e) { @@ -109,16 +114,13 @@ public final class MainFrame extends DraggableFrame { } @Override - public void windowClosed(WindowEvent e) { - } + public void windowClosed(WindowEvent e) { } @Override - public void windowIconified(WindowEvent e) { - } + public void windowIconified(WindowEvent e) { } @Override - public void windowDeiconified(WindowEvent e) { - } + public void windowDeiconified(WindowEvent e) { } @Override public void windowActivated(WindowEvent e) { @@ -131,11 +133,10 @@ public final class MainFrame extends DraggableFrame { } @Override - public void windowDeactivated(WindowEvent e) { - } + public void windowDeactivated(WindowEvent e) { } }); - if (enableShadow) + if (enableShadow) { try { setBackground(new Color(0, 0, 0, 0)); getRootPane().setBorder(border = new DropShadowBorder(borderColor, 4)); @@ -144,6 +145,8 @@ public final class MainFrame extends DraggableFrame { Settings.getInstance().setEnableShadow(false); setSize(802, 511); } + } + ((JPanel) getContentPane()).setOpaque(true); Settings.getInstance().themeChangedEvent.register(this::reloadColor); diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/tasks/download/FileDownloadTask.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/tasks/download/FileDownloadTask.java index d4e97809f..c21c1c4a8 100755 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/tasks/download/FileDownloadTask.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/tasks/download/FileDownloadTask.java @@ -118,7 +118,7 @@ public class FileDownloadTask extends Task implements PreviousResult, Prev this.url = IOUtils.parseURL(p.getResult()); for (int repeat = 0; repeat < 6; repeat++) { - if (repeat > 0) + if (repeat > 0) { if (failedCallbackReturnsNewURL != null) { URL tmp = IOUtils.parseURL(failedCallbackReturnsNewURL.apply(repeat)); if (tmp != null) { @@ -126,6 +126,8 @@ public class FileDownloadTask extends Task implements PreviousResult, Prev HMCLog.warn("Switch to: " + url); } } + } + HMCLog.log("Downloading: " + url + ", to: " + filePath); if (!shouldContinue) break; @@ -260,4 +262,8 @@ public class FileDownloadTask extends Task implements PreviousResult, Prev al.add(pr); return this; } + + public void setFailedCallbackReturnsNewURL() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } }