This commit is contained in:
huangyuhui 2017-02-01 12:21:19 +08:00
parent 130b950878
commit 9ab853d0ea
53 changed files with 592 additions and 1524 deletions

4
.gitignore vendored
View File

@ -26,6 +26,4 @@ HMCLServer/
HMCSM/build/
MetroLookAndFeel/build/
/HMCUtils/build/
/HMCLaF/build/
HMCL/version.properties
.idea/
/HMCLaF/build/

View File

@ -31,6 +31,6 @@
<license-header>
<name>GNU General Public License</name>
<template>license-header.txt</template>
<property name="organization">HMCLSoft</property>
<property name="organization">huangyuhui</property>
</license-header>
</gradle-project-properties>

View File

@ -1,10 +1,18 @@
language: java
sudo: false
jdk:
- oraclejdk8
branches:
only:
- master
before_deploy:
- git config --global user.email ${GITHUB_EMAIL}
- git config --global user.name ${GITHUB_NAME}
- git tag ${TRAVIS_BUILD_NUMBER}
- git push -q ${REPO} --tags
deploy:
provider: releases
api_key: ${DEPLOY_REPO}
api_key:
secure: lfFEwKtij/s9Ao/SKL7oVdsWcfASshZuwT27gllMrTx1ZQqLCG2I5mGJOp5ukx7lb3y4Tu316nFasLjy9NI3eLXSx9f0w4q+wMf0K5Yj9iOwu/TIn7JkLyHDMQ20qRwGxZplS2WUb669gIRg+l6jUHeTBW+dlTxr0mMa6WHIl8UDpHwfFrGC3i6dL4y6WlDwGl2rYktvOoA/iqvtglBcHuXaL2sDfhp5MXRcYULTIw+b9zmiQXP665DQN+Su5I3gwB4y5X8RH72GAacZn13fEIo5i8UUoHM7UQxM8y8DKSO3avyFCfpUle9+9sErQVW7b6JV1c+AoLWuAhNJLMlUTKarZE7UMqfjvoQHxX5hp2B2WHLEON/UJiGf25HJWx6VhJitE0/odujqnG/umesqki2jMTs6gPcxbc9iBjzUg+ZmFztdtC+Emnni7lpqVVl+Y5hsJRn3Z6rIiNgwmaE0r2OQgAm1vRYFc7jvOdRfyFG+uCRZF6nS56BzJ7dLc0WW8dTgSft6YFll4ZYL6hiI9qiIaBAK948y5HV+6VBWuO3xf/G2CUFbE1Y9qUCjToh3ahxNDzZvXB+rXqvlvNQOi5l8n594oQ61n45qIHSKlMBn9Bxhw29oWT5mo1aYIaNXbpzKam2w4mK0T3VrgTszu/3282wRbNr+VAwdGMfwW1s=
file:
- HMCL/build/libs/HMCL-${HMCL_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.jar
- HMCL/build/libs/HMCL-${HMCL_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.exe
@ -13,9 +21,8 @@ deploy:
- HMCSM/build/libs/HMCSM-${HMCSM_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}.exe
- HMCSM/build/libs/HMCSM-${HMCSM_VERSION_ROOT}.${TRAVIS_BUILD_NUMBER}-MacOSApp.zip
on:
repo: mclauncher/HMCL
branch: master
tags: true
repo: huanghongxun/HMCL
tags: false
skip_cleanup: true
install: echo "skip 'gradle assemble' step"
script: gradle build --continue
@ -24,4 +31,4 @@ before_cache:
cache:
directories:
- "$HOME/.gradle/caches/"
- "$HOME/.gradle/wrapper/"
- "$HOME/.gradle/wrapper/"

View File

@ -27,7 +27,6 @@ buildscript {
classpath 'net.sf.proguard:proguard-gradle:4.10'
classpath 'edu.sc.seis.gradle:launch4j:1.0.6'
classpath 'me.tatarka:gradle-retrolambda:3.1.0'
classpath 'com.google.code.gson:gson:2.2.4'
}
}
}
@ -39,7 +38,6 @@ plugins {
import java.util.jar.JarOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import com.google.gson.JsonParser
apply plugin: 'launch4j'
apply plugin: 'me.tatarka.retrolambda'
@ -48,46 +46,15 @@ if (!hasProperty('mainClass')) {
ext.mainClass = 'org.jackhuang.hellominecraft.launcher.Main'
}
def readBuildNumber() {
def versionPropsFile = file('version.properties')
def Properties versionProps = new Properties()
if (versionPropsFile.canRead()) {
versionProps.load(new FileInputStream(versionPropsFile))
def code = versionProps['VERSION_CODE'].toInteger()
return code.toString()
} else {
versionPropsFile.createNewFile()
String url = 'https://api.travis-ci.org/repos/mclauncher/HMCL/branches'
def json = new JsonParser().parse(url.toURL().text);
if (json.has('branches') && json.get('branches').isJsonArray()) {
def branches = json.getAsJsonArray('branches')
if (branches != null && branches.size() > 0) {
def info = branches.get(0).getAsJsonObject()
def code = info.get('number').getAsInt().toString()
versionProps['VERSION_CODE'] = code
versionProps.store(versionPropsFile.newWriter(), null)
return code
}
}
}
return '233'
}
task cleanVersionFile << {
file("version.properties").delete()
}
def buildnumber = System.getenv("TRAVIS_BUILD_NUMBER")
if (buildnumber == null)
buildnumber = System.getenv("BUILD_NUMBER")
if (buildnumber == null)
buildnumber = readBuildNumber()
def versionroot = System.getenv("HMCL_VERSION_ROOT")
buildnumber = "233"
def versionroot = System.getenv("VERSION_ROOT")
if (versionroot == null)
versionroot = "2.5.3"
versionroot = "2.4.1"
String mavenGroupId = 'HMCL'
String mavenVersion = versionroot + '.' + buildnumber
@ -173,20 +140,22 @@ jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes 'Created-By' : 'Copyright(c) 2013-2016 HMCLSoft.',
attributes 'Created-By' : 'Copyright(c) 2013-2016 huangyuhui.',
'Main-Class' : mainClass
}
}
launch4j {
supportUrl = 'http://www.hmclsoft.com'
launch4jCmd = 'D:\\Develop\\Java\\Launch4j\\launch4j.exe'
//launch4jCmd = '/home/huangyuhui/softwares/launch4j/launch4j'
supportUrl = 'http://www.mcbbs.net/thread-142335-1-1.html'
jreMinVersion = '1.6.0'
mainClassName = mainClass
icon = new File(project.buildDir, '../icon.ico').absolutePath
version = mavenVersion
downloadUrl = 'http://java.com/download'
copyright = "Copyright(c) 2013-2016 HMCLSoft."
copyright = "Copyright(c) 2013-2015 huangyuhui."
jar = new File(project.buildDir, 'libs/' + mavenGroupId + '-' + mavenVersion + '.jar').absolutePath
outfile = mavenGroupId + '-' + mavenVersion + '.exe'
@ -199,7 +168,6 @@ processResources {
}
}
build.dependsOn cleanVersionFile
build.dependsOn makeExecutable
build.dependsOn makePackGZ
build.dependsOn macAppCompressed

View File

@ -98,7 +98,7 @@ public class AssetsMojangLoader extends IAssetsHandler {
@Override
public Task getDownloadTask(IDownloadProvider sourceType) {
return new AssetsTask(sourceType.getAssetsDownloadURL(), sourceType.getRetryAssetsDownloadURL());
return new AssetsTask(sourceType.getAssetsDownloadURL());
}
@Override

View File

@ -34,8 +34,6 @@ 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;
/**
@ -91,37 +89,30 @@ public abstract class IAssetsHandler {
protected class AssetsTask extends TaskInfo {
ArrayList<Task> tasks;
String baseUrl;
String retryBaseUrl;
ArrayList<Task> al;
String u;
public AssetsTask(String url, String retryUrl) {
public AssetsTask(String url) {
super(C.i18n("assets.download"));
this.baseUrl = url;
this.retryBaseUrl = retryUrl;
this.u = url;
}
@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 downloadUrl = baseUrl + mark;
String downloadRetryUrl = StrUtils.isNotBlank(retryBaseUrl) ? retryBaseUrl + mark : "";
String url = u + 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 needDownload = true;
boolean need = true;
try {
if (location.exists()) {
FileInputStream fis = new FileInputStream(location);
@ -130,39 +121,23 @@ 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);
needDownload = !location.exists();
need = !location.exists();
}
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);
}
if (need)
al.add(new FileDownloadTask(url, location).setTag(mark));
}
}
@Override
public Collection<Task> getAfterTasks() {
return tasks;
return al;
}
}
}

View File

@ -56,8 +56,7 @@ 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

View File

@ -29,12 +29,10 @@ public class DownloadLibraryJob {
public IMinecraftLibrary lib;
public String url;
public String retryUrl;
public File path;
public DownloadLibraryJob(IMinecraftLibrary n, String u, String retry, File p) {
public DownloadLibraryJob(IMinecraftLibrary n, String u, File p) {
url = u;
retryUrl = retry;
lib = n;
path = IOUtils.tryGetCanonicalFile(p);
}

View File

@ -29,8 +29,7 @@ public enum DownloadType {
Mojang("download.mojang", new MojangDownloadProvider()),
BMCL("download.BMCL", new BMCLAPIDownloadProvider()),
//RapidData("download.rapid_data", new RapidDataDownloadProvider()),
Curse("Curse CDN", new CurseDownloadProvider()),
Dynamic("HMCLSoft", DynamicDownloadProvider.getInstance());
Curse("Curse CDN", new CurseDownloadProvider());
private final String name;
private final IDownloadProvider provider;
@ -48,7 +47,7 @@ public enum DownloadType {
return C.i18n(name);
}
private static DownloadType suggestedDownloadType = Dynamic;
private static DownloadType suggestedDownloadType = Mojang;
public static DownloadType getSuggestedDownloadType() {
return suggestedDownloadType;

View File

@ -1,161 +0,0 @@
/*
* 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://client.api.mcgogogo.com:81/provider.php";
private volatile static DynamicDownloadProvider instance;
private String versionManifestAddr = null;
private String launcherMetaAddr = null;
private String launcherAddr = null;
private String librariesAddr = null;
private String assetsAddr = null;
public void setVersionManifestAddr(String versionManifestAddr) {
this.versionManifestAddr = versionManifestAddr;
}
public void setLauncherMetaAddr(String launcherMetaAddr) {
this.launcherMetaAddr = launcherMetaAddr;
}
public void setLauncherAddr(String launcherAddr) {
this.launcherAddr = launcherAddr;
}
public void setLibrariesAddr(String librariesAddr) {
this.librariesAddr = librariesAddr;
}
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 getVersionsListDownloadURL() {
if (StrUtils.isNotBlank(versionManifestAddr)) {
return versionManifestAddr;
}
return super.getVersionsListDownloadURL();
}
@Override
public String getParsedDownloadURL(String str) {
if (str != null) {
if (StrUtils.isNotBlank(librariesAddr)) {
str = str.replace("https://libraries.minecraft.net", librariesAddr);
}
if (StrUtils.isNotBlank(launcherMetaAddr)) {
str = str.replace("https://launchermeta.mojang.com", launcherMetaAddr);
}
if (StrUtils.isNotBlank(launcherAddr)) {
str = str.replace("https://launcher.mojang.com", launcherAddr);
}
}
return super.getParsedDownloadURL(str);
}
public void init() {
new Thread() {
private String getValue(Map<String, String> addrInfo, String key) {
String value = null;
do {
if (!addrInfo.containsKey(key))
continue;
value = addrInfo.get(key);
} while(false);
return value;
}
@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) {
setLibrariesAddr(getValue(addrInfo, "libraries"));
setAssetsAddr(getValue(addrInfo, "assets"));
setLauncherMetaAddr(getValue(addrInfo, "launcherMeta"));
setLauncherAddr(getValue(addrInfo, "launcher"));
setVersionManifestAddr(getValue(addrInfo, "versionManifest"));
}
} catch (Throwable t) {
}
}
}.start();
}
}

View File

@ -38,7 +38,7 @@ public abstract class IDownloadProvider {
return null;
}
}
public abstract InstallerVersionList getForgeInstaller();
public abstract InstallerVersionList getLiteLoaderInstaller();
@ -46,10 +46,6 @@ public abstract class IDownloadProvider {
public abstract InstallerVersionList getOptiFineInstaller();
public abstract String getLibraryDownloadURL();
public String getRetryLibraryDownloadURL() {
return "";
}
public abstract String getVersionsDownloadURL();
@ -59,10 +55,6 @@ public abstract class IDownloadProvider {
public abstract String getAssetsDownloadURL();
public String getRetryAssetsDownloadURL() {
return "";
}
/**
* For example, minecraft.json/assetIndex/url or
* minecraft.json/downloads/client/url

View File

@ -31,7 +31,6 @@ 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;
@ -54,17 +53,14 @@ public class MinecraftDownloadService extends IMinecraftDownloadService {
ArrayList<DownloadLibraryJob> downloadLibraries = new ArrayList<>();
if (mv == null)
return downloadLibraries;
MinecraftVersion v = mv.resolve(service.version());
for (IMinecraftLibrary libraryInfo : v.getLibraries())
if (libraryInfo != null && libraryInfo.allow() && libraryInfo.getDownloadInfo() != null) {
File ff = libraryInfo.getFilePath(service.baseDirectory());
for (IMinecraftLibrary l : v.getLibraries())
if (l != null && l.allow() && l.getDownloadInfo() != null) {
File ff = l.getFilePath(service.baseDirectory());
if (!ff.exists()) {
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));
String libURL = l.getDownloadInfo().getUrl(service.getDownloadType());
if (libURL != null)
downloadLibraries.add(new DownloadLibraryJob(l, libURL, ff));
}
}
return downloadLibraries;
@ -118,13 +114,10 @@ public class MinecraftDownloadService extends IMinecraftDownloadService {
}
@Override
public String apply(Integer repeat) {
int index = repeat / 2;
if (index > DownloadType.values().length) {
index = 0;
}
return DownloadType.values()[index].getProvider().getVersionsDownloadURL() + suffix;
public String apply(Integer t) {
return DownloadType.values()[t / 2].getProvider().getVersionsDownloadURL() + suffix;
}
}
@Override

View File

@ -41,32 +41,27 @@ 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/";
@ -85,7 +80,7 @@ public class MojangDownloadProvider extends IDownloadProvider {
return str.replace("http://files.minecraftforge.net/maven", "http://ftb.cursecdn.com/FTB2/maven/");
else if (str.contains("typesafe") || str.contains("scala"))
if (SupportedLocales.NOW_LOCALE.self == Locale.CHINA)
return str.replace("http://files.minecraftforge.net/maven", "http://maven.aliyun.com/nexus/content/groups/public");
return str.replace("http://files.minecraftforge.net/maven", "http://maven.oschina.net/content/groups/public");
else
return str.replace("http://files.minecraftforge.net/maven", "http://repo1.maven.org/maven2");
else

View File

@ -30,110 +30,91 @@ import org.jackhuang.hellominecraft.util.tasks.Task;
*/
public abstract class InstallerVersionList {
/**
* Refresh installer versions list from the downloaded content.
*
* @param versions Minecraft versions you need to refresh
*
* @throws java.lang.Exception including network exceptions, IO exceptions.
*/
public abstract Task refresh(String[] versions);
/**
* Refresh installer versions list from the downloaded content.
*
* @param versions Minecraft versions you need to refresh
*
* @throws java.lang.Exception including network exceptions, IO exceptions.
*/
public abstract Task refresh(String[] versions);
/**
* Installer name.
*
* @return installer name.
*/
public abstract String getName();
/**
* Installer name.
*
* @return installer name.
*/
public abstract String getName();
/**
* Get installers you want.
*
* @param mcVersion the installers to this Minecraft version.
*
* @return cached result.
*/
protected abstract List<InstallerVersion> getVersionsImpl(String mcVersion);
/**
* Get installers you want.
*
* @param mcVersion the installers to this Minecraft version.
*
* @return cached result.
*/
protected abstract List<InstallerVersion> getVersionsImpl(String mcVersion);
/**
* Get installers you want, please cache this method's result to save time.
*
* @param mcVersion the installers to this Minecraft version.
*
* @return a copy of the cached data to prevent
* ConcurrentModificationException.
*/
public List<InstallerVersion> getVersions(String mcVersion) {
List<InstallerVersion> a = getVersionsImpl(mcVersion);
if (a == null) {
return null;
} else {
return new ArrayList<>(a);
}
}
/**
* Get installers you want, please cache this method's result to save time.
*
* @param mcVersion the installers to this Minecraft version.
*
* @return a copy of the cached data to prevent
* ConcurrentModificationException.
*/
public List<InstallerVersion> getVersions(String mcVersion) {
List<InstallerVersion> a = getVersionsImpl(mcVersion);
if (a == null)
return null;
else
return new ArrayList<>(a);
}
public static int compareVersion(String verOne, String verTwo) {
String[] verInfoOne = verOne.split("\\.");
String[] verInfoTwo = verTwo.split("\\.");
int idx = 0;
int minLength = Math.min(verInfoOne.length, verInfoTwo.length);
int diff = 0;
while (idx < minLength
&& (diff = verInfoOne[idx].length() - verInfoTwo[idx].length()) == 0
&& (diff = verInfoOne[idx].compareTo(verInfoTwo[idx])) == 0) {
++idx;
}
diff = (diff != 0) ? diff : verInfoOne.length - verInfoTwo.length;
return (diff == 0) ? 0 : (diff < 0 ? -1 : 1);
}
public static class InstallerVersion implements Comparable<InstallerVersion> {
public static class InstallerVersion implements Comparable<InstallerVersion> {
public String selfVersion, mcVersion;
public String installer, universal;
public String changelog;
public String selfVersion, mcVersion;
public String installer, universal;
public String changelog;
public InstallerVersion(String selfVersion, String mcVersion) {
this.selfVersion = selfVersion;
this.mcVersion = mcVersion;
}
public InstallerVersion(String selfVersion, String mcVersion) {
this.selfVersion = selfVersion;
this.mcVersion = mcVersion;
}
@Override
public int compareTo(InstallerVersion o) {
return selfVersion.compareTo(o.selfVersion);
}
@Override
public int compareTo(InstallerVersion o) {
return compareVersion(selfVersion, o.selfVersion);
}
@Override
public int hashCode() {
return selfVersion.hashCode();
}
@Override
public int hashCode() {
return selfVersion.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final InstallerVersion other = (InstallerVersion) obj;
return Objects.equals(this.selfVersion, other.selfVersion);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final InstallerVersion other = (InstallerVersion) obj;
return Objects.equals(this.selfVersion, other.selfVersion);
}
}
}
public static class InstallerVersionComparator implements Comparator<InstallerVersion>, Serializable {
public static class InstallerVersionComparator implements Comparator<InstallerVersion>, Serializable {
private static final long serialVersionUID = 3276198781795213723L;
private static final long serialVersionUID = 3276198781795213723L;
public static final InstallerVersionComparator INSTANCE = new InstallerVersionComparator();
public static final InstallerVersionComparator INSTANCE = new InstallerVersionComparator();
@Override
public int compare(InstallerVersion o1, InstallerVersion o2) {
return o2.compareTo(o1);
}
}
@Override
public int compare(InstallerVersion o1, InstallerVersion o2) {
return o2.compareTo(o1);
}
}
}

View File

@ -76,13 +76,10 @@ public class MinecraftForgeVersionList extends InstallerVersionList {
for (Map.Entry<String, int[]> arr : root.mcversion.entrySet()) {
String mcver = StrUtils.formatVersion(arr.getKey());
if (mcver == null) {
mcver = arr.getKey();
}
ArrayList<InstallerVersion> al = new ArrayList<>();
for (int num : arr.getValue()) {
MinecraftForgeVersion v = root.number.get(num);
InstallerVersion iv = new InstallerVersion(v.version, v.mcversion);
InstallerVersion iv = new InstallerVersion(v.version, StrUtils.formatVersion(v.mcversion));
for (String[] f : v.files) {
String ver = v.mcversion + "-" + v.version;
@ -111,7 +108,7 @@ public class MinecraftForgeVersionList extends InstallerVersionList {
versions.add(iv);
}
versionMap.put(mcver, al);
versionMap.put(StrUtils.formatVersion(mcver), al);
}
Collections.sort(versions, new InstallerVersionComparator());

View File

@ -21,8 +21,6 @@ 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;
/**
@ -51,20 +49,12 @@ 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.retryUrl, job.path);
download(new URL(job.url), job.path);
}
void download(URL url, String retryUrl, File filePath) throws Throwable {
void download(URL url, 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();
}

View File

@ -17,15 +17,13 @@
*/
package org.jackhuang.hellominecraft.launcher.core.mod;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@ -62,8 +60,6 @@ public class ModInfo implements Comparable<ModInfo> {
public String credits;
@SerializedName("authorList")
public String[] authorList;
@SerializedName("authors")
public String[] authors;
public boolean isActive() {
return !location.getName().endsWith(".disabled");
@ -91,8 +87,6 @@ public class ModInfo implements Comparable<ModInfo> {
public String getAuthor() {
if (authorList != null && authorList.length > 0)
return StrUtils.parseParams("", authorList, ", ");
else if (authors != null && authors.length > 0)
return StrUtils.parseParams("", authors, ", ");
else if (StrUtils.isNotBlank(author))
return author;
else
@ -129,30 +123,18 @@ public class ModInfo implements Comparable<ModInfo> {
return name.endsWith(".zip") || name.endsWith(".jar") || name.endsWith("litemod");
}
private static ModInfo getForgeModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException {
ModInfo i = new ModInfo();
i.location = f;
private static final Type TYPE = new TypeToken<List<ModInfo>>() {
}.getType();
InputStreamReader streamReader = new InputStreamReader(jar.getInputStream(entry), "UTF-8");
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(streamReader);
List<ModInfo> m = null;
if (element.isJsonArray()) {
m = C.GSON.fromJson(element, new TypeToken<List<ModInfo>>(){}.getType());
} else if (element.isJsonObject()) {
JsonObject modInfo = element.getAsJsonObject();
if (modInfo.has("modList") && modInfo.get("modList").isJsonArray()) {
m = C.GSON.fromJson(modInfo.get("modList"), new TypeToken<List<ModInfo>>(){}.getType());
}
}
if (m != null && m.size() > 0) {
i = m.get(0);
i.location = f;
}
return i;
private static ModInfo getForgeModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException {
ModInfo i = new ModInfo();
i.location = f;
List<ModInfo> m = C.GSON.fromJson(new InputStreamReader(jar.getInputStream(entry), "UTF-8"), TYPE);
if (m != null && m.size() > 0) {
i = m.get(0);
i.location = f;
}
return i;
}
private static ModInfo getLiteLoaderModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException {

View File

@ -19,7 +19,6 @@ 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;
@ -36,43 +35,14 @@ public class LibraryDownloadInfo extends GameDownloadInfo {
@Override
public String getUrl(DownloadType dt, boolean allowSelf) {
IDownloadProvider provider = dt.getProvider();
String downloadUrl = (forgeURL == null ? provider.getLibraryDownloadURL() : forgeURL);
if (StrUtils.isNotBlank(url) && allowSelf) {
downloadUrl = url;
} // forced replace: Let different download sources into force
return provider.getParsedDownloadURL(getUrlWithBaseUrl(downloadUrl));
}
public String getRetryUrl(DownloadType dt) {
IDownloadProvider provider = dt.getProvider();
String retryBaseUrl = provider.getRetryLibraryDownloadURL();
String downloadUrl = (forgeURL == null ? retryBaseUrl : forgeURL);
if (StrUtils.isNotBlank(url) && provider.isAllowedToUseSelfURL()) {
downloadUrl = url;
}
if (StrUtils.isBlank(downloadUrl)) {
return null;
}
downloadUrl = getUrlWithBaseUrl(downloadUrl);
if (downloadUrl.contains("minecraftforge")) { // fix forge url
downloadUrl = provider.getParsedDownloadURL(downloadUrl);
}
return downloadUrl;
}
private String getUrlWithBaseUrl(String baseUrl) {
if (!baseUrl.endsWith(".jar")) {
if (path == null) {
String myURL = (forgeURL == null ? dt.getProvider().getLibraryDownloadURL() : forgeURL);
if (StrUtils.isNotBlank(url) && allowSelf)
myURL = url;
if (!myURL.endsWith(".jar"))
if (path == null)
return null;
} else {
baseUrl = IOUtils.addURLSeparator(baseUrl) + path.replace('\\', '/');
}
}
return baseUrl;
}
else
myURL = IOUtils.addURLSeparator(myURL) + path.replace('\\', '/');
return myURL;
}
}

View File

@ -31,122 +31,112 @@ import org.jackhuang.hellominecraft.util.StrUtils;
*/
public class MinecraftLibrary extends IMinecraftLibrary {
@SerializedName("rules")
public ArrayList<Rules> rules;
@SerializedName("url")
public String url;
@SerializedName("natives")
public Natives natives;
@SerializedName("extract")
public Extract extract;
@SerializedName("downloads")
public LibrariesDownloadInfo downloads;
@SerializedName("rules")
public ArrayList<Rules> rules;
@SerializedName("url")
public String url;
@SerializedName("natives")
public Natives natives;
@SerializedName("extract")
public Extract extract;
@SerializedName("downloads")
public LibrariesDownloadInfo downloads;
public MinecraftLibrary(String name) {
super(name);
}
public MinecraftLibrary(String name) {
super(name);
}
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.url = url;
this.natives = (natives == null) ? null : (Natives) natives.clone();
this.extract = (extract == null) ? null : (Extract) extract.clone();
}
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.url = url;
this.natives = natives == null ? null : (Natives) natives.clone();
this.extract = extract == null ? null : (Extract) extract.clone();
}
@Override
public boolean allow() {
if (rules != null) {
boolean flag = false;
for (Rules r : rules) {
if ("disallow".equals(r.action())) {
return false;
} else if ("allow".equals(r.action())) {
flag = true;
}
}
return flag;
}
return true;
}
/**
* is the library allowed to load.
*
* @return
*/
@Override
public boolean allow() {
if (rules != null) {
boolean flag = false;
for (Rules r : rules)
if ("disallow".equals(r.action()))
return false;
else if ("allow".equals(r.action()))
flag = true;
return flag;
} else
return true;
}
private String formatArch(String nati) {
return nati == null ? "" : nati.replace("${arch}", Platform.getPlatform().getBit());
}
private String formatArch(String nati) {
return nati == null ? "" : nati.replace("${arch}", Platform.getPlatform().getBit());
}
private String getNative() {
switch (OS.os()) {
case WINDOWS:
return formatArch(natives.windows);
case OSX:
return formatArch(natives.osx);
default:
return formatArch(natives.linux);
}
}
private String getNative() {
switch (OS.os()) {
case WINDOWS:
return formatArch(natives.windows);
case OSX:
return formatArch(natives.osx);
default:
return formatArch(natives.linux);
}
}
@Override
public boolean isRequiredToUnzip() {
return natives != null && allow();
}
@Override
public boolean isRequiredToUnzip() {
return natives != null && allow();
}
public String formatName() {
String[] s = name.split(":");
if (s.length < 3) {
return null;
}
public String formatName() {
String[] s = name.split(":");
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)
sb.append('-').append(getNative());
return sb.append(".jar").toString();
}
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) {
sb.append('-').append(getNative());
}
@Override
public File getFilePath(File gameDir) {
LibraryDownloadInfo info = getDownloadInfo();
if (info == null)
return null;
return new File(gameDir, "libraries/" + info.path);
}
return sb.append(".jar").toString();
}
@Override
public Extract getDecompressExtractRules() {
return extract == null ? new Extract() : extract;
}
@Override
public File getFilePath(File gameDir) {
LibraryDownloadInfo info = getDownloadInfo();
if (info == null) {
return null;
}
return new File(gameDir, "libraries/" + info.path);
}
@Override
public Extract getDecompressExtractRules() {
return extract == null ? new Extract() : extract;
}
public LibraryDownloadInfo getDownloadInfo() {
if (downloads == null) {
downloads = new LibrariesDownloadInfo();
}
LibraryDownloadInfo info = null;
if (natives != 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) {
downloads.artifact = info = new LibraryDownloadInfo();
} else {
info = downloads.artifact;
}
if (StrUtils.isBlank(info.path)) {
info.path = formatName();
if (info.path == null) {
return null;
}
}
info.forgeURL = this.url;
return info;
}
public LibraryDownloadInfo getDownloadInfo() {
if (downloads == null)
downloads = new LibrariesDownloadInfo();
LibraryDownloadInfo info;
if (natives != 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)
downloads.artifact = info = new LibraryDownloadInfo();
else
info = downloads.artifact;
if (StrUtils.isBlank(info.path)) {
info.path = formatName();
if (info.path == null)
return null;
}
info.forgeURL = this.url;
return info;
}
}

Binary file not shown.

View File

@ -59,158 +59,144 @@ 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())
.regDone(() -> { Settings.UPDATE_CHECKER.checkOutdate(); })
.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() {
if (Settings.UPDATE_CHECKER.isForceUpdate())
return;
if (Settings.getInstance().ignoreUpdate(
Settings.UPDATE_CHECKER.getNewVersion() )) {
return;
}
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;
}
}
}

View File

@ -21,17 +21,13 @@ import org.jackhuang.hellominecraft.launcher.core.download.DownloadType;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator;
import org.jackhuang.hellominecraft.lookandfeel.Theme;
import org.jackhuang.hellominecraft.util.EventHandler;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.VersionNumber;
import org.jackhuang.hellominecraft.util.system.JdkVersion;
import org.jackhuang.hellominecraft.util.system.OS;
@ -69,52 +65,17 @@ public final class Config implements Cloneable {
private String localization;
@SerializedName("logintype")
private int logintype;
@SerializedName("downloadSourcetype")
@SerializedName("downloadtype")
private int downloadtype;
@SerializedName("configurations")
private TreeMap<String, Profile> configurations;
@SerializedName("auth")
@SuppressWarnings("FieldMayBeFinal")
private Map<String, Map> auth;
@SerializedName("ignoreUpdateVersion")
private String ignoreUpdateVersion;
@SerializedName("ignoreRecommend")
private Set<String> ignoreRecommend;
public Set<String> getIgnoreRecommend() {
if (ignoreRecommend == null) {
ignoreRecommend = new HashSet<>();
Settings.save();
}
return ignoreRecommend;
}
public List<JdkVersion> getJava() {
return java == null ? java = new ArrayList<>() : java;
}
public boolean ignoreUpdate(VersionNumber versionNumber) {
boolean ignore = false;
do
{
if (StrUtils.isBlank(ignoreUpdateVersion))
continue;
VersionNumber ignoreVersion = VersionNumber.check(ignoreUpdateVersion);
if (ignoreVersion == null)
continue;
if (versionNumber.compareTo(ignoreVersion) == 0)
ignore = true;
} while(false);
return ignore;
}
public void setIgnoreUpdate(VersionNumber versionNumber) {
ignoreUpdateVersion = versionNumber.toString();
Settings.save();
}
public transient final EventHandler<Theme> themeChangedEvent = new EventHandler<>(this);
public transient final EventHandler<DownloadType> downloadTypeChangedEvent = new EventHandler<>(this);
@ -232,8 +193,7 @@ public final class Config implements Cloneable {
public Config() {
clientToken = UUID.randomUUID().toString();
logintype = 0;
downloadtype = DownloadType.Dynamic.ordinal();
logintype = downloadtype = 0;
enableShadow = false;
enableAnimation = true;
theme = 4;
@ -243,7 +203,7 @@ public final class Config implements Cloneable {
public DownloadType getDownloadSource() {
if (downloadtype >= DownloadType.values().length || downloadtype < 0) {
downloadtype = DownloadType.Dynamic.ordinal();
downloadtype = 0;
Settings.save();
}
return DownloadType.values()[downloadtype];

View File

@ -22,8 +22,6 @@ 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;

View File

@ -17,13 +17,9 @@
*/
package org.jackhuang.hellominecraft.launcher.ui;
import java.util.Comparator;
import java.util.List;
import javax.swing.RowSorter;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.launcher.setting.Settings;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerType;
@ -40,45 +36,29 @@ import org.jackhuang.hellominecraft.util.ui.SwingUtils;
*/
public class InstallerPanel extends AnimatedPanel {
GameSettingsPanel gsp;
GameSettingsPanel gsp;
private static class VerComparator implements Comparator<String> {
/**
* Creates new form InstallerPanel
*
* @param gsp To get the minecraft version
* @param installerType load which installer
*/
public InstallerPanel(GameSettingsPanel gsp, InstallerType installerType) {
initComponents();
@Override
public int compare(String o1, String o2) {
return InstallerVersionList.compareVersion(o1, o2);
}
};
setOpaque(false);
this.gsp = gsp;
id = installerType;
list = Settings.getInstance().getDownloadSource().getProvider().getInstallerByType(id);
}
/**
* Creates new form InstallerPanel
*
* @param gsp To get the minecraft version
* @param installerType load which installer
*/
public InstallerPanel(GameSettingsPanel gsp, InstallerType installerType) {
initComponents();
//表格排序
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(lstInstallers.getModel());
VerComparator verComparator = new VerComparator();
for (int i = 0; i < lstInstallers.getColumnCount(); i++) {
sorter.setComparator(i, verComparator);
}
lstInstallers.setRowSorter(sorter);
setOpaque(false);
this.gsp = gsp;
id = installerType;
list = Settings.getInstance().getDownloadSource().getProvider().getInstallerByType(id);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
@ -129,64 +109,60 @@ public class InstallerPanel extends AnimatedPanel {
}// </editor-fold>//GEN-END:initComponents
private void btnInstallActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnInstallActionPerformed
downloadSelectedRow();
downloadSelectedRow();
}//GEN-LAST:event_btnInstallActionPerformed
private void btnRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshActionPerformed
refreshVersions();
refreshVersions();
}//GEN-LAST:event_btnRefreshActionPerformed
transient List<InstallerVersionList.InstallerVersion> versions;
transient InstallerVersionList list;
InstallerType id;
transient List<InstallerVersionList.InstallerVersion> versions;
transient InstallerVersionList list;
InstallerType id;
void refreshVersions() {
if (TaskWindow.execute(list.refresh(new String[]{gsp.getMinecraftVersionFormatted()}))) {
loadVersions();
}
}
void refreshVersions() {
if (TaskWindow.execute(list.refresh(new String[] { gsp.getMinecraftVersionFormatted() })))
loadVersions();
}
public synchronized InstallerVersionList.InstallerVersion getVersion(int idx) {
return versions.get(idx);
}
public synchronized InstallerVersionList.InstallerVersion getVersion(int idx) {
return versions.get(idx);
}
synchronized void downloadSelectedRow() {
int idx = lstInstallers.getSelectedRow();
if (versions == null || idx < 0 || idx >= versions.size()) {
MessageBox.Show(C.i18n("install.not_refreshed"));
return;
}
TaskWindow.execute(Settings.getLastProfile().service().install().download(Settings.getLastProfile().getSelectedVersion(), getVersion(idx), id),
new TaskRunnable(this::refreshVersions));
}
synchronized void downloadSelectedRow() {
int idx = lstInstallers.getSelectedRow();
if (versions == null || idx < 0 || idx >= versions.size()) {
MessageBox.Show(C.i18n("install.not_refreshed"));
return;
}
TaskWindow.execute(Settings.getLastProfile().service().install().download(Settings.getLastProfile().getSelectedVersion(), getVersion(idx), id),
new TaskRunnable(this::refreshVersions));
}
public void loadVersions() {
SwingUtilities.invokeLater(() -> {
synchronized (InstallerPanel.this) {
DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel();
String mcver = StrUtils.formatVersion(gsp.getMinecraftVersionFormatted());
versions = list.getVersions(mcver);
SwingUtils.clearDefaultTable(lstInstallers);
if (versions != null) {
for (InstallerVersionList.InstallerVersion v : versions) {
if (v != null) {
model.addRow(new Object[]{v.selfVersion == null ? "null" : v.selfVersion, v.mcVersion == null ? "null" : v.mcVersion});
}
}
}
}
});
}
public void loadVersions() {
SwingUtilities.invokeLater(() -> {
synchronized (InstallerPanel.this) {
DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel();
String mcver = StrUtils.formatVersion(gsp.getMinecraftVersionFormatted());
versions = list.getVersions(mcver);
SwingUtils.clearDefaultTable(lstInstallers);
if (versions != null)
for (InstallerVersionList.InstallerVersion v : versions)
if (v != null)
model.addRow(new Object[] { v.selfVersion == null ? "null" : v.selfVersion, v.mcVersion == null ? "null" : v.mcVersion });
}
});
}
boolean refreshed = false;
boolean refreshed = false;
@Override
public void onSelect() {
if (!refreshed) {
refreshVersions();
refreshed = true;
}
}
@Override
public void onSelect() {
if (!refreshed) {
refreshVersions();
refreshed = true;
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnInstall;

View File

@ -27,7 +27,7 @@
<Group type="102" alignment="0" attributes="0">
<Component id="btnCheckUpdate" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnHomepage" min="-2" max="-2" attributes="0"/>
<Component id="btnMCBBS" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="chkDecorated" min="-2" max="-2" attributes="0"/>
</Group>
@ -127,11 +127,11 @@
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnCheckUpdate" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="chkDecorated" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnHomepage" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnMCBBS" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblRestart" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="116" max="32767" attributes="0"/>
<EmptySpace pref="65" max="32767" attributes="0"/>
<Component id="lblModpack" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblAbout" min="-2" max="-2" attributes="0"/>
@ -157,9 +157,12 @@
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="launcher.about" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
<Color id="&#x9ed8;&#x8ba4;&#x5149;&#x6807;"/>
<Color id="&#x624b;&#x578b;&#x5149;&#x6807;"/>
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="lblAboutMouseClicked"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnSelBackgroundPath">
<Properties>
@ -345,15 +348,13 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnHomepage">
<Component class="javax.swing.JButton" name="btnMCBBS">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="launcher.homepage" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
<Property name="text" type="java.lang.String" value="MCBBS"/>
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnHomepageActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnMCBBSActionPerformed"/>
</Events>
</Component>
</SubComponents>

View File

@ -116,7 +116,7 @@ public class LauncherSettingsPanel extends AnimatedPanel {
cboLang = new javax.swing.JComboBox();
lblLang = new javax.swing.JLabel();
lblRestart = new javax.swing.JLabel();
btnHomepage = new javax.swing.JButton();
btnMCBBS = new javax.swing.JButton();
cboDownloadSource.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
@ -125,7 +125,12 @@ public class LauncherSettingsPanel extends AnimatedPanel {
});
lblAbout.setText(C.i18n("launcher.about")); // NOI18N
lblAbout.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
lblAbout.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
lblAbout.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
lblAboutMouseClicked(evt);
}
});
btnSelBackgroundPath.setText(C.i18n("ui.button.explore")); // NOI18N
btnSelBackgroundPath.addActionListener(new java.awt.event.ActionListener() {
@ -236,11 +241,11 @@ public class LauncherSettingsPanel extends AnimatedPanel {
lblRestart.setText(C.i18n("launcher.restart")); // NOI18N
btnHomepage.setText(C.i18n("launcher.homepage")); // NOI18N
btnHomepage.setToolTipText("");
btnHomepage.addActionListener(new java.awt.event.ActionListener() {
btnMCBBS.setText("MCBBS");
btnMCBBS.setToolTipText("");
btnMCBBS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnHomepageActionPerformed(evt);
btnMCBBSActionPerformed(evt);
}
});
@ -258,7 +263,7 @@ public class LauncherSettingsPanel extends AnimatedPanel {
.addGroup(layout.createSequentialGroup()
.addComponent(btnCheckUpdate)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnHomepage)
.addComponent(btnMCBBS)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkDecorated))
.addGroup(layout.createSequentialGroup()
@ -341,10 +346,10 @@ public class LauncherSettingsPanel extends AnimatedPanel {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCheckUpdate, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(chkDecorated)
.addComponent(btnHomepage))
.addComponent(btnMCBBS))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblRestart)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 116, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 65, Short.MAX_VALUE)
.addComponent(lblModpack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
@ -384,9 +389,8 @@ public class LauncherSettingsPanel extends AnimatedPanel {
}//GEN-LAST:event_txtBackgroundPathFocusLost
private void btnCheckUpdateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckUpdateActionPerformed
Settings.UPDATE_CHECKER.process(true)
.regDone(() -> { Settings.UPDATE_CHECKER.checkOutdate(); })
.execute();
Settings.UPDATE_CHECKER.process(true);
Settings.UPDATE_CHECKER.checkOutdate();
}//GEN-LAST:event_btnCheckUpdateActionPerformed
private void cboThemeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboThemeItemStateChanged
@ -394,7 +398,7 @@ public class LauncherSettingsPanel extends AnimatedPanel {
}//GEN-LAST:event_cboThemeItemStateChanged
private void lblModpackMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lblModpackMouseClicked
SwingUtils.openLink("http://client.api.mcgogogo.com:81/link.php?type=modpack");
SwingUtils.openLink("http://huangyuhui.duapp.com/link.php?type=modpack");
}//GEN-LAST:event_lblModpackMouseClicked
private void cboLangItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboLangItemStateChanged
@ -429,13 +433,17 @@ public class LauncherSettingsPanel extends AnimatedPanel {
Settings.getInstance().setProxyPassword(txtProxyPassword.getText());
}//GEN-LAST:event_txtProxyPasswordFocusLost
private void btnHomepageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnHomepageActionPerformed
private void lblAboutMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lblAboutMouseClicked
SwingUtils.openLink("http://huangyuhui.duapp.com/link.php?type=sponsor");
}//GEN-LAST:event_lblAboutMouseClicked
private void btnMCBBSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMCBBSActionPerformed
SwingUtils.openLink(C.URL_PUBLISH);
}//GEN-LAST:event_btnHomepageActionPerformed
}//GEN-LAST:event_btnMCBBSActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCheckUpdate;
private javax.swing.JButton btnHomepage;
private javax.swing.JButton btnMCBBS;
private javax.swing.JButton btnSelBackgroundPath;
private javax.swing.JComboBox cboDownloadSource;
private javax.swing.JComboBox cboLang;

View File

@ -48,7 +48,6 @@ 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;
@ -86,27 +85,23 @@ 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);
setDefaultCloseOperation(3);
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) {
@ -114,13 +109,16 @@ 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) {
@ -133,10 +131,11 @@ 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));
@ -145,8 +144,6 @@ public final class MainFrame extends DraggableFrame {
Settings.getInstance().setEnableShadow(false);
setSize(802, 511);
}
}
((JPanel) getContentPane()).setOpaque(true);
Settings.getInstance().themeChangedEvent.register(this::reloadColor);

View File

@ -277,16 +277,5 @@
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="contentPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
<AbsoluteConstraints x="220" y="40" width="540" height="320"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
<Property name="useNullLayout" type="boolean" value="true"/>
</Layout>
</Container>
</SubComponents>
</Form>

View File

@ -61,7 +61,7 @@ public class MainPagePanel extends AnimatedPanel {
void initGui() {
initComponents();
pnlButtons = new javax.swing.JPanel();
pnlButtons.setLayout(null);
@ -84,9 +84,6 @@ public class MainPagePanel extends AnimatedPanel {
pnlMore.setBounds(0, 0, pnlMore.getWidth(), DEFAULT_HEIGHT);
pnlMore.setBackground(GraphicsUtils.getWebColorWithAlpha("FFFFFF7F"));
pnlMore.setOpaque(true);
recommendPanel = new RecommendPanel();
contentPanel.add(recommendPanel);
Settings.getInstance().authChangedEvent.register(onAuthChanged);
Settings.profileLoadingEvent.register(onLoadingProfiles);
@ -125,7 +122,6 @@ public class MainPagePanel extends AnimatedPanel {
btnLogout = new javax.swing.JButton();
btnImportModpack = new javax.swing.JButton();
btnExportModpack = new javax.swing.JButton();
contentPanel = new javax.swing.JPanel();
setLayout(null);
@ -266,7 +262,7 @@ public class MainPagePanel extends AnimatedPanel {
.addComponent(lblVersion, javax.swing.GroupLayout.Alignment.TRAILING))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(cboProfiles, 0, 128, Short.MAX_VALUE)
.addComponent(cboVersions, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(pnlMoreLayout.createSequentialGroup()
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -310,10 +306,6 @@ public class MainPagePanel extends AnimatedPanel {
add(pnlMore);
pnlMore.setBounds(0, 0, 190, 480);
contentPanel.setLayout(null);
add(contentPanel);
contentPanel.setBounds(220, 40, 540, 320);
}// </editor-fold>//GEN-END:initComponents
private void txtPlayerNameFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPlayerNameFocusGained
@ -434,8 +426,6 @@ public class MainPagePanel extends AnimatedPanel {
super.onCreate();
Settings.onProfileLoading();
}
private RecommendPanel recommendPanel;
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnExportModpack;
@ -444,7 +434,6 @@ public class MainPagePanel extends AnimatedPanel {
private javax.swing.JComboBox cboLoginMode;
private javax.swing.JComboBox cboProfiles;
private javax.swing.JComboBox cboVersions;
private javax.swing.JPanel contentPanel;
private javax.swing.JLabel jLabel10;
private javax.swing.JLabel jLabel7;
private javax.swing.JLabel jLabel9;

View File

@ -1,338 +0,0 @@
/*
* Copyright (C) 2016 evilwk <evilwk@gmail.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.ui;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.awt.Cursor;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import org.jackhuang.hellominecraft.launcher.Main;
import org.jackhuang.hellominecraft.launcher.setting.Settings;
import org.jackhuang.hellominecraft.util.NetUtils;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.ui.SwingUtils;
/**
*
* @author evilwk <evilwk@gmail.com>
*/
public class RecommendPanel extends JPanel {
private static final int SWITCH_INTERVAL = 10;
private static final int SPACE = 10;
private static final int TOP_POSITION = 2;
private JButton closeButton;
private Image currImage;
private String imageKey = null;
private boolean ignoreSwitch = false;
private List<RecommendInfo> recommends;
public final ScheduledExecutorService scheduledexec = Executors.newScheduledThreadPool(1);
public RecommendPanel() {
initComponents();
recommends = new ArrayList<RecommendInfo>();
new LoadImages().execute();
setCursor(new Cursor(Cursor.HAND_CURSOR));
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
MouseClicked(e);
}
});
}
private void initComponents() {
this.setLayout(null);
closeButton = new JButton(Main.getIcon("re_close.png"));
closeButton.setRolloverIcon(Main.getIcon("re_close_enter.png"));
closeButton.setBorder(BorderFactory.createEmptyBorder());
closeButton.setContentAreaFilled(false);
closeButton.addActionListener((e) -> ignoreTheRecommend(imageKey));
closeButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
closeButton.setFocusable(false);
closeButton.setBounds(0, 0, 12, 12);
closeButton.setVisible(false);
this.add(closeButton);
}
private void ignoreTheRecommend(String url) {
synchronized(RecommendPanel.class) {
if (StrUtils.isNotBlank(url)) {
Settings.getInstance().getIgnoreRecommend().add(url);
Settings.save();
ignoreSwitch = true;
showNext();
}
}
}
private void MouseClicked(MouseEvent evt) {
if (imageKey == null) {
return;
}
RecommendInfo info = recommends.get(getCurrentImageIndex());
if (StrUtils.isNotBlank(info.link)) {
if (info.once) {
ignoreTheRecommend(info.url);
}
SwingUtils.openLink(info.link);
}
}
public void showImages() {
if (recommends.isEmpty()) {
return;
}
new Thread(new Runnable() {
@Override
public void run() {
for (RecommendInfo info : recommends) {
if (!ignoreShowUrl(info.url)) {
try {
File tempFile = File.createTempFile("hmcl", "png");
String tempPath = tempFile.getCanonicalPath();
if (NetUtils.download(info.url, tempPath)) {
info.image = ImageIO.read(tempFile);
}
} catch (Throwable t) { }
}
}
if (getImagesSize() == 0 || showIfOnly()) {
return;
}
scheduledexec.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
synchronized(RecommendPanel.class) {
if (ignoreSwitch) {
ignoreSwitch = false;
} else {
showNext();
}
}
}
});
}
}, 0, SWITCH_INTERVAL, TimeUnit.SECONDS);
}
}).start();
}
public int getImagesSize() {
int imageCount = 0;
for (RecommendInfo recommend : recommends) {
if (recommend.image != null) {
imageCount++;
}
}
return imageCount;
}
public boolean showIfOnly() {
if (getImagesSize() != 1) {
return false;
}
for (RecommendInfo recommend : recommends) {
if (recommend.image != null) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
RecommendPanel.this.setImage(recommend.url, recommend.image);
}
});
}
}
return true;
}
private void showNext() {
if (getCanShowImageCount() == 0) {
setVisible(false);
scheduledexec.shutdown();
} else {
int showIndex = getNextImageIndex();
RecommendInfo info = recommends.get(showIndex);
setImage(info.url, info.image);
}
}
private boolean ignoreShowUrl(String url) {
if (StrUtils.isBlank(url)) {
return true;
}
return Settings.getInstance().getIgnoreRecommend().contains(url);
}
public int getCanShowImageCount() {
int imageCount = 0;
for (RecommendInfo recommend : recommends) {
if (recommend.image != null && !ignoreShowUrl(recommend.url)) {
imageCount++;
}
}
return imageCount;
}
public int getNextImageIndex(int showIndex) {
if (showIndex >= recommends.size()) {
showIndex = 0;
}
RecommendInfo info = recommends.get(showIndex);
if (info.image == null || ignoreShowUrl(info.url)) {
showIndex = getNextImageIndex(++showIndex);
}
return showIndex;
}
public int getNextImageIndex() {
int showIndex = getCurrentImageIndex();
if (++showIndex >= recommends.size()) {
showIndex = 0;
}
showIndex = getNextImageIndex(showIndex);
return showIndex >= recommends.size() ? 0 : showIndex;
}
public int getCurrentImageIndex() {
int currIndex = 0;
for (int i = 0; i < recommends.size(); i++) {
RecommendInfo info = recommends.get(i);
if (StrUtils.isNotBlank(imageKey) && info.url.equals(imageKey)) {
currIndex = i;
break;
}
}
return currIndex;
}
public void setImage(String key, Image image) {
this.imageKey = key;
this.currImage = image;
int btnWidth = closeButton.getWidth();
setSize(image.getWidth(this) + SPACE + btnWidth, image.getHeight(this));
closeButton.setLocation(getWidth() - btnWidth, TOP_POSITION);
closeButton.setVisible(true);
SwingUtilities.updateComponentTreeUI(this.getRootPane());
}
@Override
public void paintComponent(Graphics g) {
if (currImage != null) {
g.drawImage(currImage, 0, 0, currImage.getWidth(this), currImage.getHeight(this), this);
}
super.paintComponent(g);
}
static class RecommendInfo {
String url;
String link;
boolean once;
Image image;
}
class LoadImages extends SwingWorker<List<Map<String, Object>>, Void> {
private static final String RECOMMEND_URL = "http://client.api.mcgogogo.com:81/recommend.php";
@Override
protected List<Map<String, Object>> doInBackground() throws Exception {
List<Map<String, Object>> infos = null;
do {
String content = NetUtils.get(RECOMMEND_URL);
if (content == null || content.equals("")) {
break;
}
Map<String, Object> data = new Gson().fromJson(content,
new TypeToken<Map<String, Object>>() {}.getType());
if (data == null) {
break;
}
infos = (List<Map<String, Object>>) data.get("data");
} while (false);
return infos;
}
@Override
protected void done() {
try {
List<Map<String, Object>> infos = this.get();
if (infos == null) {
return;
}
for (Map<String, Object> info : infos) {
RecommendInfo recommend = new RecommendInfo();
if (info.get("url") != null) {
recommend.url = (String) info.get("url");
} else {
recommend.url = "";
}
if (info.get("link") != null) {
recommend.link = (String) info.get("link");
} else {
recommend.link = "";
}
if (info.get("once") != null) {
recommend.once = (boolean) info.get("once");
} else {
recommend.once = false;
}
recommend.image = null;
recommends.add(recommend);
}
RecommendPanel.this.showImages();
} catch (InterruptedException | ExecutionException ex) {
}
}
}
}

View File

@ -138,9 +138,9 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
HashMap<String, String> map = new HashMap<>();
map.put("CrashReport", text);
try {
NetUtils.post(NetUtils.constantURL("http://client.api.mcgogogo.com:81/crash_report.php"), map);
} catch (Throwable error) {
LOGGER.log(Level.SEVERE, "Failed to post HMCL server.", error);
NetUtils.post(NetUtils.constantURL("http://huangyuhui.duapp.com/crash.php"), map);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Failed to post HMCL server.", ex);
}
});
t.setDaemon(true);

View File

@ -17,7 +17,6 @@
*/
package org.jackhuang.hellominecraft.launcher.util.upgrade;
import java.awt.Dimension;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@ -37,30 +36,20 @@ import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
import java.util.zip.GZIPInputStream;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.launcher.core.MCUtils;
import org.jackhuang.hellominecraft.launcher.setting.Settings;
import org.jackhuang.hellominecraft.util.tasks.Task;
import org.jackhuang.hellominecraft.util.tasks.TaskWindow;
import org.jackhuang.hellominecraft.util.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.util.ArrayUtils;
import org.jackhuang.hellominecraft.util.MessageBox;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.UpdateChecker;
import org.jackhuang.hellominecraft.util.Utils;
import org.jackhuang.hellominecraft.util.VersionNumber;
import org.jackhuang.hellominecraft.util.func.Consumer;
import org.jackhuang.hellominecraft.util.system.FileUtils;
import org.jackhuang.hellominecraft.util.system.IOUtils;
import org.jackhuang.hellominecraft.util.system.OS;
import org.jackhuang.hellominecraft.util.tasks.TaskList;
import org.jackhuang.hellominecraft.util.tasks.TaskWindow;
/**
*
@ -108,97 +97,43 @@ public class AppDataUpgrader extends IUpgrader {
}
return false;
}
public boolean askUpdateVersion(VersionNumber versionNumber) {
if (!Settings.UPDATE_CHECKER.isManualUpdate() &&
Settings.getInstance().ignoreUpdate(versionNumber))
return false;
String content = C.i18n("update.newest_version") +
versionNumber.firstVer + "." + versionNumber.secondVer + "." +
versionNumber.thirdVer + "\n" +
C.i18n("update.should_open_link");
JCheckBox checkbox = new JCheckBox(C.i18n("update.ignore"));
JPanel logPanel = new JPanel();
logPanel.setLayout(new BoxLayout(logPanel, BoxLayout.X_AXIS));
logPanel.setPreferredSize(new Dimension(300,150));
logPanel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 5));
JScrollPane scrollPane = new JScrollPane();
JTextPane textPane = new JTextPane();
textPane.setContentType("text/plain");
textPane.setEditable(false);
scrollPane.setViewportView(textPane);
logPanel.add(scrollPane);
int msgRet;
String updateLog = Settings.UPDATE_CHECKER.getUpdateLog();
if (StrUtils.isBlank(updateLog)) {
msgRet = MessageBox.Show(new Object[]{content, checkbox}, MessageBox.YES_NO_OPTION);
} else {
textPane.setText(updateLog);
msgRet = MessageBox.Show(new Object[]{content, logPanel, checkbox}, MessageBox.YES_NO_OPTION);
}
if (msgRet == MessageBox.NO_OPTION) {
if (checkbox.isSelected()) {
Settings.getInstance().setIgnoreUpdate(versionNumber);
}
return false;
}
return true;
}
@Override
public boolean call(Object sender, final VersionNumber number) {
((UpdateChecker) sender).requestDownloadLink().reg(new Consumer<Map<String, String>>() {
@Override
public void accept(Map<String, String> map) {
boolean isForceUpdate = Settings.UPDATE_CHECKER.isForceUpdate();
if (isForceUpdate || askUpdateVersion(number))
if (map != null && map.containsKey("pack"))
try {
String hash = null;
if (map.containsKey("packsha1")) {
hash = map.get("packsha1");
}
AppDataUpgraderTask upgraderTask = new AppDataUpgraderTask(map.get("pack"), number.version, hash);
if (isForceUpdate) {
TaskList tasks = new TaskList();
tasks.addTask(upgraderTask);
tasks.start();
} else {
if (TaskWindow.factory().append(upgraderTask).create()) {
new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderTask.getSelf(number.version).getAbsolutePath() }).directory(new File(".")).start();
System.exit(0);
}
}
} catch (IOException ex) {
HMCLog.err("Failed to create upgrader", ex);
}
else {
String url = C.URL_PUBLISH;
if (map != null)
if (map.containsKey(OS.os().checked_name))
url = map.get(OS.os().checked_name);
else if (map.containsKey(OS.UNKOWN.checked_name))
url = map.get(OS.UNKOWN.checked_name);
if (url == null)
url = C.URL_PUBLISH;
try {
java.awt.Desktop.getDesktop().browse(new URI(url));
} catch (URISyntaxException | IOException e) {
HMCLog.warn("Failed to browse uri: " + url, e);
Utils.setClipborad(url);
MessageBox.Show(C.i18n("update.no_browser"));
}
}
}
}).execute();
((UpdateChecker) sender).requestDownloadLink().reg(map -> {
if (MessageBox.Show(C.i18n("update.newest_version") + number.firstVer + "." + number.secondVer + "." + number.thirdVer + "\n"
+ C.i18n("update.should_open_link"),
MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
if (map != null && map.containsKey("pack"))
try {
String hash = null;
if (map.containsKey("packsha1"))
hash = map.get("packsha1");
if (TaskWindow.factory().append(new AppDataUpgraderTask(map.get("pack"), number.version, hash)).create()) {
new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderTask.getSelf(number.version).getAbsolutePath() }).directory(new File(".")).start();
System.exit(0);
}
} catch (IOException ex) {
HMCLog.err("Failed to create upgrader", ex);
}
else {
String url = C.URL_PUBLISH;
if (map != null)
if (map.containsKey(OS.os().checked_name))
url = map.get(OS.os().checked_name);
else if (map.containsKey(OS.UNKOWN.checked_name))
url = map.get(OS.UNKOWN.checked_name);
if (url == null)
url = C.URL_PUBLISH;
try {
java.awt.Desktop.getDesktop().browse(new URI(url));
} catch (URISyntaxException | IOException e) {
HMCLog.warn("Failed to browse uri: " + url, e);
Utils.setClipborad(url);
MessageBox.Show(C.i18n("update.no_browser"));
}
}
}).execute();
return true;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -29,10 +29,10 @@ public final class C {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final String URL_PUBLISH = "http://www.hmclsoft.com";
public static final String URL_GITHUB = "https://github.com/mclauncher/HMCL/issues";
//http://repo1.maven.org/maven2
public static final String URL_PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html";
public static final String URL_TIEBA = "http://tieba.baidu.com/f?kw=hellominecraftlauncher";
public static final String URL_GITHUB = "https://github.com/huanghongxun/HMCL/issues";
public static final String URL_MINECRAFTFORUM = "http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-tools/1265720-hello-minecraft-launcher-1-9-3-mc-1-7-4-auto";
public static final String FILE_MINECRAFT_VERSIONS = "versions";

View File

@ -26,27 +26,9 @@ import java.util.Map;
public interface IUpdateChecker {
/**
* Update response
*
*/
void checkOutdate();
/**
*
* @return Update log
*/
String getUpdateLog();
/**
*
* @return Server to assign a mandatory update
*/
boolean isForceUpdate();
/**
*
* @return User manual update
*/
boolean isManualUpdate();
/**
* Get the <b>cached</b> newest version number, use "process" method to

View File

@ -86,23 +86,23 @@ public class MessageBox {
/**
* Show MsgBox with title and options
*
* @param msg The Message
* @param title The title of MsgBox.
* @param optionType The type of MsgBox.
* @param Msg The Message
* @param Title The title of MsgBox.
* @param Option The type of MsgBox.
*
* @return user operation.
*/
public static int Show(Object msg, String title, int optionType) {
switch (optionType) {
public static int Show(String Msg, String Title, int Option) {
switch (Option) {
case YES_NO_OPTION:
case YES_NO_CANCEL_OPTION:
case OK_CANCEL_OPTION:
return SwingUtils.invokeAndWait(() -> JOptionPane.showConfirmDialog(null, msg, title, optionType - 10));
return SwingUtils.invokeAndWait(() -> JOptionPane.showConfirmDialog(null, Msg, Title, Option - 10));
default:
SwingUtils.invokeAndWait(() -> JOptionPane.showMessageDialog(null, msg, title, optionType));
SwingUtils.invokeAndWait(() -> JOptionPane.showMessageDialog(null, Msg, Title, Option));
}
return 0;
}
}
/**
* Show MsgBox with options
@ -112,8 +112,8 @@ public class MessageBox {
*
* @return User Operation
*/
public static int Show(Object msg, int optionType) {
return Show(msg, TITLE, optionType);
public static int Show(String Msg, int Option) {
return Show(Msg, TITLE, Option);
}
/**
@ -123,8 +123,8 @@ public class MessageBox {
*
* @return User Operation
*/
public static int Show(Object msg) {
return Show(msg, TITLE, INFORMATION_MESSAGE);
public static int Show(String Msg) {
return Show(Msg, TITLE, INFORMATION_MESSAGE);
}
public static int ShowLocalized(String msg) {

View File

@ -19,8 +19,6 @@ package org.jackhuang.hellominecraft.util;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -131,23 +129,6 @@ public final class NetUtils {
con.disconnect();
return result;
}
public static boolean download(String url, String saveFile) {
try {
int readCount = 0;
byte[] buffer = new byte[1204];
InputStream inputStream = new URL(url).openConnection().getInputStream();
FileOutputStream fs = new FileOutputStream(saveFile);
while ((readCount = inputStream.read(buffer)) != -1) {
fs.write(buffer, 0, readCount);
}
return true;
} catch (FileNotFoundException e) {
return false;
} catch (IOException e) {
return false;
}
}
private static final String DEFAULT_CHARSET = "UTF-8";

View File

@ -19,28 +19,16 @@ package org.jackhuang.hellominecraft.util;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import java.util.Map;
import org.jackhuang.hellominecraft.util.lang.SupportedLocales;
/**
*
* @author huangyuhui
*/
public final class UpdateChecker implements IUpdateChecker {
public static final String VERSION_URL = "http://client.api.mcgogogo.com:81/version.php?type=";
public static final String UPDATE_LINK_URL = "http://client.api.mcgogogo.com:81/update_link.php?type=";
public boolean OUT_DATED = false;
public String versionString;
public VersionNumber base;
private VersionNumber value;
private boolean isforceUpdate = false;
private boolean isManualUpdate = false;
private String updateLog = null;
public String versionString;
public String type;
private Map<String, String> download_link = null;
@ -49,39 +37,26 @@ public final class UpdateChecker implements IUpdateChecker {
this.type = type;
}
VersionNumber value;
@Override
public OverridableSwingWorker<VersionNumber> process(final boolean showMessage) {
return new OverridableSwingWorker() {
@Override
protected void work() throws Exception {
isManualUpdate = showMessage;
if (value == null) {
versionString = NetUtils.get(VERSION_URL + type +
"&ver=" + base.toString() +
"&lang=" + SupportedLocales.NOW_LOCALE.self);
Map<String, Object> versionInfo = C.GSON.fromJson(versionString, Map.class);
if (versionInfo.containsKey("version"))
value = VersionNumber.check((String) versionInfo.get("version"));
if (versionInfo.containsKey("force"))
isforceUpdate = (boolean) versionInfo.get("force");
if (versionInfo.containsKey("log"))
updateLog = (String) versionInfo.get("log");
versionString = NetUtils.get("http://huangyuhui.duapp.com/info.php?type=" + type);
value = VersionNumber.check(versionString);
}
if (value == null) {
HMCLog.warn("Failed to check update...");
if (showMessage) {
if (showMessage)
MessageBox.Show(C.i18n("update.failed"));
}
} else if (VersionNumber.isOlder(base, value)) {
} else if (VersionNumber.isOlder(base, value))
OUT_DATED = true;
}
if (OUT_DATED) {
if (OUT_DATED)
publish(value);
}
}
};
}
@ -91,21 +66,6 @@ public final class UpdateChecker implements IUpdateChecker {
return value;
}
@Override
public boolean isForceUpdate() {
return isforceUpdate;
}
@Override
public boolean isManualUpdate() {
return isManualUpdate;
}
@Override
public String getUpdateLog() {
return updateLog;
}
@Override
public synchronized OverridableSwingWorker<Map<String, String>> requestDownloadLink() {
return new OverridableSwingWorker() {
@ -113,7 +73,7 @@ public final class UpdateChecker implements IUpdateChecker {
protected void work() throws Exception {
if (download_link == null)
try {
download_link = C.GSON.fromJson(NetUtils.get(UPDATE_LINK_URL + type), Map.class);
download_link = C.GSON.fromJson(NetUtils.get("http://huangyuhui.duapp.com/update_link.php?type=" + type), Map.class);
} catch (Exception e) {
HMCLog.warn("Failed to get update link.", e);
}

View File

@ -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,8 +126,6 @@ public class FileDownloadTask extends Task implements PreviousResult<File>, Prev
HMCLog.warn("Switch to: " + url);
}
}
}
HMCLog.log("Downloading: " + url + ", to: " + filePath);
if (!shouldContinue)
break;
@ -262,8 +260,4 @@ 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.
}
}

View File

@ -36,7 +36,7 @@
<Group type="102" alignment="1" attributes="0">
<Component id="btnTieBa" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnHomepage" min="-2" max="-2" attributes="0"/>
<Component id="btnMCBBS" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnMCF" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@ -68,7 +68,7 @@
<Component id="btnClear" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnClose" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnCopy" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnHomepage" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnMCBBS" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnTieBa" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnMCF" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnTerminateGame" alignment="3" min="-2" max="-2" attributes="0"/>
@ -117,14 +117,12 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnHomepage">
<Component class="javax.swing.JButton" name="btnMCBBS">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="logwindow.homepage" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
<Property name="text" type="java.lang.String" value="MCBBS"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnHomepageActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnMCBBSActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnTieBa">

View File

@ -69,7 +69,7 @@ public class LogWindow extends javax.swing.JFrame {
btnClose = new javax.swing.JButton();
btnCopy = new javax.swing.JButton();
lblCrash = new javax.swing.JLabel();
btnHomepage = new javax.swing.JButton();
btnMCBBS = new javax.swing.JButton();
btnTieBa = new javax.swing.JButton();
btnMCF = new javax.swing.JButton();
btnTerminateGame = new javax.swing.JButton();
@ -108,10 +108,10 @@ public class LogWindow extends javax.swing.JFrame {
lblCrash.setText(C.i18n("ui.label.crashing")); // NOI18N
btnHomepage.setText(C.i18n("logwindow.homepage")); // NOI18N
btnHomepage.addActionListener(new java.awt.event.ActionListener() {
btnMCBBS.setText("MCBBS");
btnMCBBS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnHomepageActionPerformed(evt);
btnMCBBSActionPerformed(evt);
}
});
@ -156,7 +156,7 @@ public class LogWindow extends javax.swing.JFrame {
.addGroup(layout.createSequentialGroup()
.addComponent(btnTieBa)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnHomepage)
.addComponent(btnMCBBS)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnMCF)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -184,7 +184,7 @@ public class LogWindow extends javax.swing.JFrame {
.addComponent(btnClear)
.addComponent(btnClose)
.addComponent(btnCopy)
.addComponent(btnHomepage)
.addComponent(btnMCBBS)
.addComponent(btnTieBa)
.addComponent(btnMCF)
.addComponent(btnTerminateGame)
@ -209,9 +209,9 @@ public class LogWindow extends javax.swing.JFrame {
Utils.setClipborad(this.txtLog.getText());
}//GEN-LAST:event_btnCopyActionPerformed
private void btnHomepageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnHomepageActionPerformed
private void btnMCBBSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMCBBSActionPerformed
SwingUtils.openLink(C.URL_PUBLISH);
}//GEN-LAST:event_btnHomepageActionPerformed
}//GEN-LAST:event_btnMCBBSActionPerformed
private void btnTieBaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTieBaActionPerformed
SwingUtils.openLink(C.URL_TIEBA);
@ -284,7 +284,7 @@ public class LogWindow extends javax.swing.JFrame {
@Override
public void setVisible(boolean b) {
lblCrash.setVisible(false);
btnHomepage.setVisible(false);
btnMCBBS.setVisible(false);
btnTieBa.setVisible(false);
btnMCF.setVisible(false);
super.setVisible(b);
@ -293,13 +293,13 @@ public class LogWindow extends javax.swing.JFrame {
public void showAsCrashWindow(boolean out_date) {
if (out_date) {
lblCrash.setVisible(false);
btnHomepage.setVisible(false);
btnMCBBS.setVisible(false);
btnTieBa.setVisible(false);
btnMCF.setVisible(false);
lblCrash.setText(C.i18n("ui.label.crashing_out_dated"));
} else {
lblCrash.setVisible(true);
btnHomepage.setVisible(true);
btnMCBBS.setVisible(true);
btnTieBa.setVisible(true);
btnMCF.setVisible(true);
lblCrash.setText(C.i18n("ui.label.crashing"));
@ -313,7 +313,7 @@ public class LogWindow extends javax.swing.JFrame {
private javax.swing.JButton btnClose;
private javax.swing.JButton btnCopy;
private javax.swing.JButton btnGitHub;
private javax.swing.JButton btnHomepage;
private javax.swing.JButton btnMCBBS;
private javax.swing.JButton btnMCF;
private javax.swing.JButton btnTerminateGame;
private javax.swing.JButton btnTieBa;

View File

@ -35,6 +35,8 @@ public class LogWindowOutputStream extends OutputStream {
private final Level sas;
public LogWindowOutputStream(LogWindow logWindow, Level l) {
Objects.nonNull(logWindow);
Objects.nonNull(l);
txt = logWindow;
sas = l;
}

View File

@ -168,7 +168,6 @@ ui.message.launching=启动中
ui.message.making=生成中
ui.message.sure_remove=真的要删除配置%s吗
ui.message.update_java=请更新您的Java
ui.message.recommend_tip=点击打开链接
ui.label.settings=选项
ui.label.crashing=<html>Hello Minecraft!遇到了无法处理的错误请复制下列内容并通过mcbbs、贴吧、Github或Minecraft Forum反馈bug。</html>
@ -176,7 +175,7 @@ ui.label.crashing_out_dated=<html>Hello Minecraft! Launcher遇到了无法处理
ui.label.failed_set=设置失败:
download=下载
download.mojang=Mojang官方
download.mojang=官方
download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/)
download.rapid_data=RapidData (锐网云计算, https://www.rapiddata.org/)
download.not_200=下载失败,回复码
@ -299,9 +298,8 @@ mainwindow.enter_script_name=输入要生成脚本的文件名
mainwindow.make_launch_succeed=启动脚本已生成完毕:
mainwindow.no_version=未找到任何版本,是否进入游戏下载?
launcher.about=<html>默认背景图感谢gamerteam提供。<br/>关于作者:<br/>主页http://www.hmclsoft.com<br/>邮箱contact@hmclsoft.com<br/>欢迎提交Bug哦<br/>Copyright (c) 2013-2016 HMCLSoft.<br/>免责声明Minecraft软件版权归Mojang AB所有使用本软件产生的版权问题本软件制作方概不负责。<br/>本启动器在GPLv3协议下开源https://github.com/mclauncher/HMCL感谢issues和pull requests贡献者<br/>本软件使用了基于Apache License 2.0的Gson项目感谢贡献者。</html>
launcher.about=<html>默认背景图感谢gamerteam提供。<br><a href="http://huangyuhui.duapp.com/link.php?type=sponsor">如果您希望本软件继续发展,请赞助</a><br/>关于作者:<br/>百度IDhuanghongxun20<br/>mcbbshuanghongxun<br/>邮箱huanghongxun2008@126.com<br/>Minecraft Forum ID: klkl6523<br/>欢迎提交Bug哦<br/>Copyright (c) 2013-2016 huangyuhui.<br/>免责声明Minecraft软件版权归Mojang AB所有使用本软件产生的版权问题本软件制作方概不负责。<br/>本启动器在GPLv3协议下开源:https://github.com/huanghongxun/HMCL/ ,感谢issues和pull requests贡献者<br/>本软件使用了基于Apache License 2.0的Gson项目感谢贡献者。</html>
launcher.download_source=下载源
launcher.homepage=官网
launcher.background_location=背景地址
launcher.exit_failed=强制退出失败可能是Forge 1.7.10及更高版本导致的,无法解决。
launcher.versions_json_not_matched=版本%s格式不规范该版本文件夹下有json:%s是否更名这个文件来规范格式
@ -314,7 +312,7 @@ launcher.enable_shadow=启用窗口阴影
launcher.theme=主题
launcher.proxy=代理
launcher.decorated=启用窗口边框(Linux下可解决程序界面全灰问题)
launcher.modpack=<html><a href="http://client.api.mcgogogo.com:81/link.php?type=modpack">整合包作者帮助</a></html>
launcher.modpack=<html><a href="http://huangyuhui.duapp.com/link.php?type=modpack">整合包作者帮助</a></html>
launcher.enable_animation=启用动态效果
launcher.lang=语言
launcher.restart=本界面选项需要重启本启动器生效
@ -371,12 +369,10 @@ update.should_open_link=是否更新?
update.newest_version=最新版本为:
update.failed=检查更新失败
update.found=(发现更新!)
update.ignore=不再提醒此版本更新
logwindow.terminate_game=结束游戏进程
logwindow.tieba=贴吧
logwindow.title=日志
logwindow.homepage=官网
selector.choose=选择

View File

@ -168,7 +168,6 @@ ui.message.launching=\u542f\u52a8\u4e2d
ui.message.making=\u751f\u6210\u4e2d
ui.message.sure_remove=\u771f\u7684\u8981\u5220\u9664\u914d\u7f6e%s\u5417\uff1f
ui.message.update_java=\u8bf7\u66f4\u65b0\u60a8\u7684Java
ui.message.recommend_tip=\u70b9\u51fb\u6253\u5f00\u94fe\u63a5
ui.label.settings=\u9009\u9879
ui.label.crashing=<html>Hello Minecraft!\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u8bf7\u590d\u5236\u4e0b\u5217\u5185\u5bb9\u5e76\u901a\u8fc7mcbbs\u3001\u8d34\u5427\u3001Github\u6216Minecraft Forum\u53cd\u9988bug\u3002</html>
@ -176,7 +175,7 @@ ui.label.crashing_out_dated=<html>Hello Minecraft! Launcher\u9047\u5230\u4e86\u6
ui.label.failed_set=\u8bbe\u7f6e\u5931\u8d25\uff1a
download=\u4e0b\u8f7d
download.mojang=Mojang\u5b98\u65b9
download.mojang=\u5b98\u65b9
download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/)
download.rapid_data=RapidData (\u9510\u7f51\u4e91\u8ba1\u7b97, https://www.rapiddata.org/)
download.not_200=\u4e0b\u8f7d\u5931\u8d25\uff0c\u56de\u590d\u7801
@ -299,9 +298,8 @@ mainwindow.enter_script_name=\u8f93\u5165\u8981\u751f\u6210\u811a\u672c\u7684\u6
mainwindow.make_launch_succeed=\u542f\u52a8\u811a\u672c\u5df2\u751f\u6210\u5b8c\u6bd5:
mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u662f\u5426\u8fdb\u5165\u6e38\u620f\u4e0b\u8f7d\uff1f
launcher.about=<html>\u9ed8\u8ba4\u80cc\u666f\u56fe\u611f\u8c22gamerteam\u63d0\u4f9b\u3002<br/>\u5173\u4e8e\u4f5c\u8005\uff1a<br/>\u4e3b\u9875\uff1ahttp://www.hmclsoft.com<br/>\u90ae\u7bb1\uff1acontact@hmclsoft.com<br/>\u6b22\u8fce\u63d0\u4ea4Bug\u54e6<br/>Copyright (c) 2013-2016 HMCLSoft.<br/>\u514d\u8d23\u58f0\u660e\uff1aMinecraft\u8f6f\u4ef6\u7248\u6743\u5f52Mojang AB\u6240\u6709\uff0c\u4f7f\u7528\u672c\u8f6f\u4ef6\u4ea7\u751f\u7684\u7248\u6743\u95ee\u9898\u672c\u8f6f\u4ef6\u5236\u4f5c\u65b9\u6982\u4e0d\u8d1f\u8d23\u3002<br/>\u672c\u542f\u52a8\u5668\u5728GPLv3\u534f\u8bae\u4e0b\u5f00\u6e90\uff1ahttps://github.com/mclauncher/HMCL\uff0c\u611f\u8c22issues\u548cpull requests\u8d21\u732e\u8005<br/>\u672c\u8f6f\u4ef6\u4f7f\u7528\u4e86\u57fa\u4e8eApache License 2.0\u7684Gson\u9879\u76ee\uff0c\u611f\u8c22\u8d21\u732e\u8005\u3002</html>
launcher.about=<html>\u9ed8\u8ba4\u80cc\u666f\u56fe\u611f\u8c22gamerteam\u63d0\u4f9b\u3002<br><a href="http://huangyuhui.duapp.com/link.php?type=sponsor">\u5982\u679c\u60a8\u5e0c\u671b\u672c\u8f6f\u4ef6\u7ee7\u7eed\u53d1\u5c55\uff0c\u8bf7\u8d5e\u52a9</a><br/>\u5173\u4e8e\u4f5c\u8005\uff1a<br/>\u767e\u5ea6ID\uff1ahuanghongxun20<br/>mcbbs\uff1ahuanghongxun<br/>\u90ae\u7bb1\uff1ahuanghongxun2008@126.com<br/>Minecraft Forum ID: klkl6523<br/>\u6b22\u8fce\u63d0\u4ea4Bug\u54e6<br/>Copyright (c) 2013-2016 huangyuhui.<br/>\u514d\u8d23\u58f0\u660e\uff1aMinecraft\u8f6f\u4ef6\u7248\u6743\u5f52Mojang AB\u6240\u6709\uff0c\u4f7f\u7528\u672c\u8f6f\u4ef6\u4ea7\u751f\u7684\u7248\u6743\u95ee\u9898\u672c\u8f6f\u4ef6\u5236\u4f5c\u65b9\u6982\u4e0d\u8d1f\u8d23\u3002<br/>\u672c\u542f\u52a8\u5668\u5728GPLv3\u534f\u8bae\u4e0b\u5f00\u6e90:https://github.com/huanghongxun/HMCL/ ,\u611f\u8c22issues\u548cpull requests\u8d21\u732e\u8005<br/>\u672c\u8f6f\u4ef6\u4f7f\u7528\u4e86\u57fa\u4e8eApache License 2.0\u7684Gson\u9879\u76ee\uff0c\u611f\u8c22\u8d21\u732e\u8005\u3002</html>
launcher.download_source=\u4e0b\u8f7d\u6e90
launcher.homepage=\u5b98\u7f51
launcher.background_location=\u80cc\u666f\u5730\u5740
launcher.exit_failed=\u5f3a\u5236\u9000\u51fa\u5931\u8d25\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5bfc\u81f4\u7684\uff0c\u65e0\u6cd5\u89e3\u51b3\u3002
launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u89c4\u8303\uff01\u8be5\u7248\u672c\u6587\u4ef6\u5939\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u8fd9\u4e2a\u6587\u4ef6\u6765\u89c4\u8303\u683c\u5f0f\uff1f
@ -314,7 +312,7 @@ launcher.enable_shadow=\u542f\u7528\u7a97\u53e3\u9634\u5f71
launcher.theme=\u4e3b\u9898
launcher.proxy=\u4ee3\u7406
launcher.decorated=\u542f\u7528\u7a97\u53e3\u8fb9\u6846(Linux\u4e0b\u53ef\u89e3\u51b3\u7a0b\u5e8f\u754c\u9762\u5168\u7070\u95ee\u9898)
launcher.modpack=<html><a href="http://client.api.mcgogogo.com:81/link.php?type=modpack">\u6574\u5408\u5305\u4f5c\u8005\u5e2e\u52a9</a></html>
launcher.modpack=<html><a href="http://huangyuhui.duapp.com/link.php?type=modpack">\u6574\u5408\u5305\u4f5c\u8005\u5e2e\u52a9</a></html>
launcher.enable_animation=\u542f\u7528\u52a8\u6001\u6548\u679c
launcher.lang=\u8bed\u8a00
launcher.restart=\u672c\u754c\u9762\u9009\u9879\u9700\u8981\u91cd\u542f\u672c\u542f\u52a8\u5668\u751f\u6548
@ -371,12 +369,10 @@ update.should_open_link=\u662f\u5426\u66f4\u65b0\uff1f
update.newest_version=\u6700\u65b0\u7248\u672c\u4e3a\uff1a
update.failed=\u68c0\u67e5\u66f4\u65b0\u5931\u8d25
update.found=(\u53d1\u73b0\u66f4\u65b0!)
update.ignore=\u4e0d\u518d\u63d0\u9192\u6b64\u7248\u672c\u66f4\u65b0
logwindow.terminate_game=\u7ed3\u675f\u6e38\u620f\u8fdb\u7a0b
logwindow.tieba=\u8d34\u5427
logwindow.title=\u65e5\u5fd7
logwindow.homepage=\u5b98\u7f51
selector.choose=\u9009\u62e9

View File

@ -168,7 +168,6 @@ ui.message.launching=Launching...
ui.message.making=Generating...
ui.message.sure_remove=Sure to remove profile %s?
ui.message.update_java=Please upgrade your Java.
ui.message.recommend_tip=Click to open link
ui.label.settings=Settings
ui.label.crashing=<html>Hello Minecraft! Launcher has crashed!</html>
@ -299,9 +298,8 @@ mainwindow.enter_script_name=Enter the script name.
mainwindow.make_launch_succeed=Finished script creation.
mainwindow.no_version=No version found. Switch to Game Downloads Tab?
launcher.about=<html>About Author<br/>Homepage: http://www.hmclsoft.com<br/>Email: contact@hmclsoft.com<br/>Copyright (c) 2013 HMCLSoft.<br/>Opened source under GPL v3 license: http://github.com/mclauncher/HMCL<br/>This software used project Gson which is under Apache License 2.0, thanks contributors.</html>
launcher.about=<html>About Author<br/>Emailhuanghongxun2008@126.com<br/>Minecraft Forum ID: klkl6523<br/>Copyright (c) 2013 huangyuhui<br/>Opened source under GPL v3 license:http://github.com/huanghongxun/HMCL/<br/>This software used project Gson which is under Apache License 2.0, thanks contributors.</html>
launcher.download_source=Download Source
launcher.homepage=Homepage
launcher.background_location=Background Location
launcher.exit_failed=Failed to shutdown.
launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem?
@ -314,7 +312,7 @@ launcher.enable_shadow=Enable Window Shadow
launcher.theme=Theme
launcher.proxy=Proxy
launcher.decorated=Enable system window border(in order to fix the problem that the ui become all gray in Linux OS)
launcher.modpack=<html><a href="http://client.api.mcgogogo.com:81/link.php?type=modpack">Documentations for modpacks.</a></html>
launcher.modpack=<html><a href="http://blog.163.com/huanghongxun2008@126/blog/static/7738046920160323812771/">Documentations for modpacks.</a></html>
launcher.enable_animation=Enable Animation
launcher.lang=Language
launcher.restart=Options will be in operations only if restart this app.
@ -371,12 +369,10 @@ update.should_open_link=Are you willing to upgrade this app?
update.newest_version=Newest version:
update.failed=Failed to check for updates.
update.found=(Found Update!)
update.ignore=Do not remind this version update.
logwindow.terminate_game=Terminate Game
logwindow.tieba=Baidu Tieba
logwindow.title=Log
logwindow.homepage=Homepage
selector.choose=Choose

View File

@ -168,7 +168,6 @@ ui.message.launching=Launching...
ui.message.making=Generating...
ui.message.sure_remove=Sure to remove profile %s?
ui.message.update_java=Please upgrade your Java.
ui.message.recommend_tip=Click to open link
ui.label.settings=Settings
ui.label.crashing=<html>Hello Minecraft! Launcher has crashed!</html>
@ -299,9 +298,8 @@ mainwindow.enter_script_name=Enter the script name.
mainwindow.make_launch_succeed=Finished script creation.
mainwindow.no_version=No version found. Switch to Game Downloads Tab?
launcher.about=<html>About Author<br/>Homepage: http://www.hmclsoft.com<br/>Email: contact@hmclsoft.com<br/>Copyright (c) 2013 HMCLSoft.<br/>Opened source under GPL v3 license: http://github.com/mclauncher/HMCL<br/>This software used project Gson which is under Apache License 2.0, thanks contributors.</html>
launcher.about=<html>About Author<br/>Email\uff1ahuanghongxun2008@126.com<br/>Minecraft Forum ID: klkl6523<br/>Copyright (c) 2013 huangyuhui<br/>Opened source under GPL v3 license:http://github.com/huanghongxun/HMCL/<br/>This software used project Gson which is under Apache License 2.0, thanks contributors.</html>
launcher.download_source=Download Source
launcher.homepage=Homepage
launcher.background_location=Background Location
launcher.exit_failed=Failed to shutdown.
launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem?
@ -314,7 +312,7 @@ launcher.enable_shadow=Enable Window Shadow
launcher.theme=Theme
launcher.proxy=Proxy
launcher.decorated=Enable system window border(in order to fix the problem that the ui become all gray in Linux OS)
launcher.modpack=<html><a href="http://client.api.mcgogogo.com:81/link.php?type=modpack">Documentations for modpacks.</a></html>
launcher.modpack=<html><a href="http://blog.163.com/huanghongxun2008@126/blog/static/7738046920160323812771/">Documentations for modpacks.</a></html>
launcher.enable_animation=Enable Animation
launcher.lang=Language
launcher.restart=Options will be in operations only if restart this app.
@ -371,12 +369,10 @@ update.should_open_link=Are you willing to upgrade this app?
update.newest_version=Newest version:
update.failed=Failed to check for updates.
update.found=(Found Update!)
update.ignore=Do not remind this version update.
logwindow.terminate_game=Terminate Game
logwindow.tieba=Baidu Tieba
logwindow.title=Log
logwindow.homepage=Homepage
selector.choose=Choose

View File

@ -168,7 +168,6 @@ ui.message.launching=啟動中
ui.message.making=生成中
ui.message.sure_remove=真的要删除配置%s吗
ui.message.update_java=请更新您的Java
ui.message.recommend_tip=點擊打開連接
ui.label.settings=選項
ui.label.crashing=<html>Hello Minecraft! Launcher遇到了無法處理的錯誤請複制下列內容並通過mcbbs、貼吧或Minecraft Forum反饋bug。 </html>
@ -176,7 +175,7 @@ ui.label.crashing_out_dated=<html>Hello Minecraft! Launcher遇到了無法處理
ui.label.failed_set=設定失敗:
download=下載
download.mojang=Mojang官方
download.mojang=官方
download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/)
download.rapid_data=RapidData (銳網雲計算, https://www.rapiddata.org/)
download.not_200=下載失敗,回复码
@ -299,9 +298,8 @@ mainwindow.enter_script_name=輸入要生成腳本的資料名
mainwindow.make_launch_succeed=啟動腳本已生成完畢:
mainwindow.no_version=未找到任何版本,是否進入遊戲下載?
launcher.about=<html>默認背景圖感謝gamerteam提供。<br/>關於作者:<br/>主頁http://www.hmclsoft.com<br/>郵箱contact@hmclsoft.com<br/>歡迎提交Bug哦<br/>Copyright (c) 2013-2016 HMCLSoft.<br/>免責聲明Minecraft軟體版權歸Mojang AB所有遊戲由於誤操作本啟動器而丟失數據的概不負責。<br/>本啟動器在GPLv3協議下開源http://github.com/mclauncher/HMCL感谢issues和pull requests贡献者<br/>本軟體使用了基於Apache License 2.0的Gson項目感謝貢獻者。</html>
launcher.about=<html>默認背景圖感謝gamerteam提供。<br><a href="http://huangyuhui.duapp.com/link.php?type=sponsor">如果您希望本軟件繼續發展,請贊助</a><br>關於作者:<br>百度IDhuanghongxun20<br>mcbbshuanghongxun<br>郵箱huanghongxun2008@126.com<br>Minecraft Forum ID: klkl6523<br>歡迎提交Bug哦<br/>Copyright (c) 2013-2016 huangyuhui.<br>免責聲明Minecraft軟體版權歸Mojang AB所有遊戲由於誤操作本啟動器而丟失數據的概不負責。<br>本啟動器在GPLv3協議下開源:http://github.com/huanghongxun/HMCL/ ,感谢issues和pull requests贡献者<br>本軟體使用了基於Apache License 2.0的Gson項目感謝貢獻者。</html>
launcher.download_source=下載源
launcher.homepage=官網
launcher.background_location=背景地址
launcher.exit_failed=強制退出失敗可能是Forge 1.7.10及更高版本導致的,無法解決。
launcher.versions_json_not_matched=版本%s格式不規範該版本資料夾下有json:%s是否更名這個資料來規範格式
@ -314,7 +312,7 @@ launcher.enable_shadow=启用窗口阴影
launcher.theme=主题
launcher.proxy=代理
launcher.decorated=啟用窗口邊框(Linux下可解決程序界面全灰問題)
launcher.modpack=<html><a href="http://client.api.mcgogogo.com:81/link.php?type=modpack">整合包作者帮助</a></html>
launcher.modpack=<html><a href="http://huangyuhui.duapp.com/link.php?type=modpack">整合包作者帮助</a></html>
launcher.enable_animation=啟用動態效果
launcher.lang=語言
launcher.restart=本界面選項需要重啟本啟動器生效
@ -371,12 +369,10 @@ update.should_open_link=是否更新?
update.newest_version=最新版本為:
update.failed=檢查更新失敗
update.found=(發現更新!)
update.ignore=不再提醒此版本更新
logwindow.terminate_game=結束遊戲進程
logwindow.tieba=貼吧
logwindow.title=日志
logwindow.homepage=官網
selector.choose=選擇

View File

@ -168,7 +168,6 @@ ui.message.launching=\u555f\u52d5\u4e2d
ui.message.making=\u751f\u6210\u4e2d
ui.message.sure_remove=\u771f\u7684\u8981\u5220\u9664\u914d\u7f6e%s\u5417\uff1f
ui.message.update_java=\u8bf7\u66f4\u65b0\u60a8\u7684Java
ui.message.recommend_tip=\u9ede\u64ca\u6253\u958b\u9023\u63a5
ui.label.settings=\u9078\u9805
ui.label.crashing=<html>Hello Minecraft! Launcher\u9047\u5230\u4e86\u7121\u6cd5\u8655\u7406\u7684\u932f\u8aa4\uff0c\u8acb\u8907\u5236\u4e0b\u5217\u5167\u5bb9\u4e26\u901a\u904emcbbs\u3001\u8cbc\u5427\u6216Minecraft Forum\u53cd\u994bbug\u3002 </html>
@ -176,7 +175,7 @@ ui.label.crashing_out_dated=<html>Hello Minecraft! Launcher\u9047\u5230\u4e86\u7
ui.label.failed_set=\u8a2d\u5b9a\u5931\u6557\uff1a
download=\u4e0b\u8f09
download.mojang=Mojang\u5b98\u65b9
download.mojang=\u5b98\u65b9
download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/)
download.rapid_data=RapidData (\u92b3\u7db2\u96f2\u8a08\u7b97, https://www.rapiddata.org/)
download.not_200=\u4e0b\u8f09\u5931\u6557\uff0c\u56de\u590d\u7801
@ -299,9 +298,8 @@ mainwindow.enter_script_name=\u8f38\u5165\u8981\u751f\u6210\u8173\u672c\u7684\u8
mainwindow.make_launch_succeed=\u555f\u52d5\u8173\u672c\u5df2\u751f\u6210\u5b8c\u7562:
mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u662f\u5426\u9032\u5165\u904a\u6232\u4e0b\u8f09\uff1f
launcher.about=<html>\u9ed8\u8a8d\u80cc\u666f\u5716\u611f\u8b1dgamerteam\u63d0\u4f9b\u3002<br/>\u95dc\u65bc\u4f5c\u8005\uff1a<br/>\u4e3b\u9801\uff1ahttp://www.hmclsoft.com<br/>\u90f5\u7bb1\uff1acontact@hmclsoft.com<br/>\u6b61\u8fce\u63d0\u4ea4Bug\u54e6<br/>Copyright (c) 2013-2016 HMCLSoft.<br/>\u514d\u8cac\u8072\u660e\uff1aMinecraft\u8edf\u9ad4\u7248\u6b0a\u6b78Mojang AB\u6240\u6709\uff0c\u904a\u6232\u7531\u65bc\u8aa4\u64cd\u4f5c\u672c\u555f\u52d5\u5668\u800c\u4e1f\u5931\u6578\u64da\u7684\u6982\u4e0d\u8ca0\u8cac\u3002<br/>\u672c\u555f\u52d5\u5668\u5728GPLv3\u5354\u8b70\u4e0b\u958b\u6e90\uff1ahttp://github.com/mclauncher/HMCL\uff0c\u611f\u8c22issues\u548cpull requests\u8d21\u732e\u8005<br>\u672c\u8edf\u9ad4\u4f7f\u7528\u4e86\u57fa\u65bcApache License 2.0\u7684Gson\u9805\u76ee\uff0c\u611f\u8b1d\u8ca2\u737b\u8005\u3002</html>
launcher.about=<html>\u9ed8\u8a8d\u80cc\u666f\u5716\u611f\u8b1dgamerteam\u63d0\u4f9b\u3002<br><a href="http://huangyuhui.duapp.com/link.php?type=sponsor">\u5982\u679c\u60a8\u5e0c\u671b\u672c\u8edf\u4ef6\u7e7c\u7e8c\u767c\u5c55\uff0c\u8acb\u8d0a\u52a9</a><br>\u95dc\u65bc\u4f5c\u8005\uff1a<br>\u767e\u5ea6ID\uff1ahuanghongxun20<br>mcbbs\uff1ahuanghongxun<br>\u90f5\u7bb1\uff1ahuanghongxun2008@126.com<br>Minecraft Forum ID: klkl6523<br>\u6b61\u8fce\u63d0\u4ea4Bug\u54e6<br/>Copyright (c) 2013-2016 huangyuhui.<br>\u514d\u8cac\u8072\u660e\uff1aMinecraft\u8edf\u9ad4\u7248\u6b0a\u6b78Mojang AB\u6240\u6709\uff0c\u904a\u6232\u7531\u65bc\u8aa4\u64cd\u4f5c\u672c\u555f\u52d5\u5668\u800c\u4e1f\u5931\u6578\u64da\u7684\u6982\u4e0d\u8ca0\u8cac\u3002<br>\u672c\u555f\u52d5\u5668\u5728GPLv3\u5354\u8b70\u4e0b\u958b\u6e90:http://github.com/huanghongxun/HMCL/ ,\u611f\u8c22issues\u548cpull requests\u8d21\u732e\u8005<br>\u672c\u8edf\u9ad4\u4f7f\u7528\u4e86\u57fa\u65bcApache License 2.0\u7684Gson\u9805\u76ee\uff0c\u611f\u8b1d\u8ca2\u737b\u8005\u3002</html>
launcher.download_source=\u4e0b\u8f09\u6e90
launcher.homepage=\u5b98\u7db2
launcher.background_location=\u80cc\u666f\u5730\u5740
launcher.exit_failed=\u5f37\u5236\u9000\u51fa\u5931\u6557\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5c0e\u81f4\u7684\uff0c\u7121\u6cd5\u89e3\u6c7a\u3002
launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u898f\u7bc4\uff01\u8a72\u7248\u672c\u8cc7\u6599\u593e\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u9019\u500b\u8cc7\u6599\u4f86\u898f\u7bc4\u683c\u5f0f\uff1f
@ -314,7 +312,7 @@ launcher.enable_shadow=\u542f\u7528\u7a97\u53e3\u9634\u5f71
launcher.theme=\u4e3b\u9898
launcher.proxy=\u4ee3\u7406
launcher.decorated=\u555f\u7528\u7a97\u53e3\u908a\u6846(Linux\u4e0b\u53ef\u89e3\u6c7a\u7a0b\u5e8f\u754c\u9762\u5168\u7070\u554f\u984c)
launcher.modpack=<html><a href="http://client.api.mcgogogo.com:81/link.php?type=modpack">\u6574\u5408\u5305\u4f5c\u8005\u5e2e\u52a9</a></html>
launcher.modpack=<html><a href="http://huangyuhui.duapp.com/link.php?type=modpack">\u6574\u5408\u5305\u4f5c\u8005\u5e2e\u52a9</a></html>
launcher.enable_animation=\u555f\u7528\u52d5\u614b\u6548\u679c
launcher.lang=\u8a9e\u8a00
launcher.restart=\u672c\u754c\u9762\u9078\u9805\u9700\u8981\u91cd\u555f\u672c\u555f\u52d5\u5668\u751f\u6548
@ -371,12 +369,10 @@ update.should_open_link=\u662f\u5426\u66f4\u65b0\uff1f
update.newest_version=\u6700\u65b0\u7248\u672c\u70ba\uff1a
update.failed=\u6aa2\u67e5\u66f4\u65b0\u5931\u6557
update.found=(\u767c\u73fe\u66f4\u65b0!)
update.ignore=\u4e0d\u518d\u63d0\u9192\u6b64\u7248\u672c\u66f4\u65b0
logwindow.terminate_game=\u7d50\u675f\u904a\u6232\u9032\u7a0b
logwindow.tieba=\u8cbc\u5427
logwindow.title=\u65e5\u5fd7
logwindow.homepage=\u5b98\u7db2
selector.choose=\u9078\u64c7

View File

@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Hello Minecraft! Launcher, a Minecraft Launcher which is easy to use.
Copyright (C) 2016 HMCLSoft.
Copyright (C) 2014 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
@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Hello Minecraft! Launcher Copyright (C) 2016 HMCLSoft.
Hello Minecraft! Launcher Copyright (C) 2014 huangyuhui
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

View File

@ -1,9 +1,10 @@
# Hello Minecraft! Launcher [![Build Status](https://travis-ci.org/mclauncher/HMCL.svg?branch=master)](https://travis-ci.org/mclauncher/HMCL)
# Hello Minecraft! Launcher [![Build Status](https://travis-ci.org/huanghongxun/HMCL.svg?branch=master)](https://travis-ci.org/huanghongxun/HMCL)
开源协议为GPL v3, 详情参见http://www.gnu.org/licenses/gpl.html
## 介绍
HMCL是一个Minecraft启动器支持Mod管理游戏定制自动安装整合包制作界面主题定制等功能。
并且一天的使用次数在工作日时有40万左右、节假日有150万左右的使用次数也就是说日活跃用户在10万以上。
但是本项目的代码不够完善希望有更多的人能加入HMCL的开发。
## 贡献

View File

@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2016 HMCLSoft.
* 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