mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-09 11:55:52 -04:00
添加可以在线控制的下载源
This commit is contained in:
parent
9ae010a391
commit
94b6cda86e
@ -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
|
||||
|
@ -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<Task> al;
|
||||
String u;
|
||||
ArrayList<Task> 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<Integer, String>() {
|
||||
@Override
|
||||
public String apply(Integer t) {
|
||||
return downloadRetryUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
tasks.add(fileDownloadTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Task> getAfterTasks() {
|
||||
return al;
|
||||
return tasks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* 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 <evilwk@gmail.com>
|
||||
*/
|
||||
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<String, String> addrInfo = null;
|
||||
addrInfo = C.GSON.fromJson(providerInfo, new TypeToken<Map<String, String>>(){}.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();
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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<DownloadLibraryJob> 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
|
||||
|
@ -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/";
|
||||
|
@ -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<Integer, String>() {
|
||||
@Override
|
||||
public String apply(Integer t) {
|
||||
return retryUrl;
|
||||
}
|
||||
};
|
||||
}
|
||||
super.executeTask();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -48,29 +48,25 @@ public class MinecraftLibrary extends IMinecraftLibrary {
|
||||
|
||||
public MinecraftLibrary(ArrayList<Rules> rules, String url, Natives natives, String name, Extract extract, LibraryDownloadInfo downloads) {
|
||||
super(name);
|
||||
this.rules = rules == null ? null : (ArrayList<Rules>) rules.clone();
|
||||
this.rules = (rules == null) ? null : (ArrayList<Rules>) 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -118,7 +118,7 @@ public class FileDownloadTask extends Task implements PreviousResult<File>, 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<File>, 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<File>, Prev
|
||||
al.add(pr);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setFailedCallbackReturnsNewURL() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user