Reconstruct codes

This commit is contained in:
huanghongxun 2015-12-15 21:39:53 +08:00
parent b3fb372e3b
commit 713a0171cc
25 changed files with 546 additions and 285 deletions

0
Apache License 2.0~ Normal file
View File

View File

@ -80,8 +80,8 @@ jar {
}
launch4j {
//launch4jCmd = 'D:\\Develop\\Java\\Launch4j\\launch4j.exe'
launch4jCmd = '/home/huangyuhui/softwares/launch4j/launch4j'
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'

View File

@ -17,34 +17,21 @@
*/
package org.jackhuang.hellominecraft.launcher;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.jar.JarFile;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.launch.GameLauncher;
import org.jackhuang.hellominecraft.launcher.utils.CrashReporter;
@ -53,18 +40,13 @@ import org.jackhuang.hellominecraft.logging.appender.ConsoleAppender;
import org.jackhuang.hellominecraft.logging.layout.DefaultLayout;
import org.jackhuang.hellominecraft.views.LogWindow;
import org.jackhuang.hellominecraft.launcher.settings.Settings;
import org.jackhuang.hellominecraft.launcher.utils.upgrade.Upgrader;
import org.jackhuang.hellominecraft.launcher.utils.upgrade.IUpgrader;
import org.jackhuang.hellominecraft.launcher.views.MainFrame;
import org.jackhuang.hellominecraft.lookandfeel.HelloMinecraftLookAndFeel;
import org.jackhuang.hellominecraft.tasks.TaskWindow;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.utils.MathUtils;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.VersionNumber;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.utils.system.IOUtils;
import org.jackhuang.hellominecraft.utils.system.OS;
import rx.concurrency.Schedulers;
/**
*
@ -104,7 +86,7 @@ public final class Main implements Runnable {
}
public static String launcherName = "Hello Minecraft! Launcher";
public static byte firstVer = 2, secondVer = 3, thirdVer = 5, forthVer = 6;
public static byte firstVer = 2, secondVer = 3, thirdVer = 1, forthVer = 6;
public static int minimumLauncherVersion = 16;
//public static Proxy PROXY;
@ -131,34 +113,8 @@ public final class Main implements Runnable {
@SuppressWarnings( {"CallToPrintStackTrace", "UseSpecificCatch"})
public static void main(String[] args) {
{
if (!ArrayUtils.contains(args, "nofound"))
try {
File f = Upgrader.HMCL_VER_FILE;
if (f.exists()) {
Map<String, String> m = C.gson.fromJson(FileUtils.readFileToString(f), Map.class);
String s = m.get("ver");
if (s != null && VersionNumber.check(s).compareTo(new VersionNumber(firstVer, secondVer, thirdVer)) > 0) {
String j = m.get("loc");
if (j != null) {
File jar = new File(j);
if (jar.exists()) {
JarFile jarFile = new JarFile(jar);
String mainClass = jarFile.getManifest().getMainAttributes().getValue("Main-Class");
if (mainClass != null) {
ArrayList<String> al = new ArrayList<>(Arrays.asList(args));
al.add("notfound");
new URLClassLoader(new URL[] {jar.toURI().toURL()},
URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass)
.getMethod("main", String[].class).invoke(null, new Object[] {al.toArray(new String[0])});
if (IUpgrader.NOW_UPGRADER.parseArguments(new VersionNumber(firstVer, secondVer, thirdVer), args))
return;
}
}
}
}
}
} catch (Throwable t) {
t.printStackTrace();
}
System.setProperty("sun.java2d.noddraw", "true");
@ -185,7 +141,9 @@ public final class Main implements Runnable {
HMCLog.warn("Failed to set look and feel...", ex);
}
Settings.UPDATE_CHECKER.start();
Settings.UPDATE_CHECKER.outdated.register(IUpgrader.NOW_UPGRADER);
Settings.UPDATE_CHECKER.process(false).subscribeOn(Schedulers.newThread()).subscribe(t ->
Main.invokeUpdate());
if (StrUtils.isNotBlank(Settings.getInstance().getProxyHost()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPort()) && MathUtils.canParseInt(Settings.getInstance().getProxyPort())) {
HMCLog.log("Initializing customized proxy");
@ -198,9 +156,6 @@ public final class Main implements Runnable {
return new PasswordAuthentication(Settings.getInstance().getProxyUserName(), Settings.getInstance().getProxyPassword().toCharArray());
}
});
//PROXY = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(Settings.getInstance().getProxyHost(), Integer.parseInt(Settings.getInstance().getProxyPort())));
} else {
//PROXY = Proxy.NO_PROXY;
}
try {
@ -217,44 +172,6 @@ public final class Main implements Runnable {
GameLauncher.PROCESS_MANAGER.stopAllProcesses();
}
public static void update() {
Settings.UPDATE_CHECKER.requestDownloadLink(() -> {
SwingUtilities.invokeLater(() -> {
Map<String, String> map = Settings.UPDATE_CHECKER.download_link;
if (map != null && map.containsKey("pack"))
try {
if (TaskWindow.getInstance().addTask(new Upgrader(map.get("pack"), Settings.UPDATE_CHECKER.versionString)).start()) {
new ProcessBuilder(new String[] {IOUtils.getJavaDir(), "-jar", Upgrader.getSelf(Settings.UPDATE_CHECKER.versionString).getAbsolutePath()}).directory(new File(".")).start();
System.exit(0);
}
} catch (IOException ex) {
HMCLog.warn("Failed to create upgrader", ex);
}
if (MessageBox.Show(C.i18n("update.newest_version") + Settings.UPDATE_CHECKER.getNewVersion().firstVer + "." + Settings.UPDATE_CHECKER.getNewVersion().secondVer + "." + Settings.UPDATE_CHECKER.getNewVersion().thirdVer + "\n"
+ C.i18n("update.should_open_link"),
MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) {
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);
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.setContents(new StringSelection(url), null);
MessageBox.Show(C.i18n("update.no_browser"));
}
}
});
});
}
public static void invokeUpdate() {
MainFrame.INSTANCE.invokeUpdate();
}

View File

@ -159,7 +159,9 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
res.add(v.getWidth());
}
if (StrUtils.isNotBlank(v.getServerIp())) {
String serverIp = v.getServerIp();
if (lr.getServerIp() != null) serverIp = lr.getServerIp();
if (StrUtils.isNotBlank(serverIp)) {
String[] args = v.getServerIp().split(":");
res.add("--server");
res.add(args[0]);

View File

@ -70,7 +70,7 @@ public final class Settings {
e.checkFormat();
UPDATE_CHECKER = new UpdateChecker(new VersionNumber(Main.firstVer, Main.secondVer, Main.thirdVer),
"hmcl", Main::invokeUpdate);
"hmcl");
List<Java> temp = new ArrayList<>();
temp.add(new Java("Default", System.getProperty("java.home")));
@ -119,7 +119,8 @@ public final class Settings {
}
public static Profile getProfile(String name) {
if (name == null) return getProfiles().get("Default");
if (name == null)
return getProfiles().get("Default");
return getProfiles().get(name);
}

View File

@ -26,8 +26,8 @@ import javax.swing.SwingUtilities;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.Main;
import org.jackhuang.hellominecraft.launcher.settings.Settings;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.utils.UpdateChecker;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.views.LogWindow;
@ -105,8 +105,8 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
System.out.println(text);
if (checkThrowable(e) && !System.getProperty("java.vm.name").contains("OpenJDK")) {
SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.showAsCrashWindow(UpdateChecker.OUT_DATED));
if (!UpdateChecker.OUT_DATED)
SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.showAsCrashWindow(Settings.UPDATE_CHECKER.OUT_DATED));
if (!Settings.UPDATE_CHECKER.OUT_DATED)
reportToServer(text, s);
}
} catch (Throwable ex) {

View File

@ -52,7 +52,8 @@ public final class UserProfileProvider {
}
public void setAccessToken(String accessToken) {
if (accessToken == null) accessToken = "0";
if (accessToken == null)
accessToken = "0";
this.accessToken = accessToken;
}
@ -114,4 +115,13 @@ public final class UserProfileProvider {
private String otherInfo = "";
private String clientIdentifier = "";
private String userType = "Offline";
private String serverIp = "";
public String getServerIp() {
return serverIp;
}
public void setServerIp(String serverIp) {
this.serverIp = serverIp;
}
}

View File

@ -19,7 +19,6 @@ package org.jackhuang.hellominecraft.launcher.utils.installers;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.settings.Profile;
import org.jackhuang.hellominecraft.launcher.settings.Settings;
import org.jackhuang.hellominecraft.launcher.utils.installers.InstallerVersionList.InstallerVersion;
import org.jackhuang.hellominecraft.launcher.utils.installers.forge.ForgeInstaller;
import org.jackhuang.hellominecraft.launcher.utils.installers.liteloader.LiteLoaderInstaller;
@ -64,7 +63,7 @@ public final class InstallerService {
File filepath = IOUtils.tryGetCanonicalFile(IOUtils.currentDirWithSeparator() + "forge-installer.jar");
if (v.installer != null)
TaskWindow.getInstance()
.addTask(new FileDownloadTask(Settings.getInstance().getDownloadSource().getProvider().getParsedLibraryDownloadURL(v.installer), filepath).setTag("forge"))
.addTask(new FileDownloadTask(p.getDownloadType().getProvider().getParsedLibraryDownloadURL(v.installer), filepath).setTag("forge"))
.addTask(new ForgeInstaller(p.getMinecraftProvider(), filepath, v))
.start();
}

View File

@ -0,0 +1,180 @@
/*
* 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.utils.upgrade;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
import java.util.zip.GZIPInputStream;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.utils.MCUtils;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.tasks.TaskWindow;
import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.UpdateChecker;
import org.jackhuang.hellominecraft.utils.VersionNumber;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.utils.system.IOUtils;
import org.jackhuang.hellominecraft.utils.system.OS;
import rx.concurrency.Schedulers;
/**
*
* @author huangyuhui
*/
public class AppDataUpgrader extends IUpgrader {
@Override
public boolean parseArguments(VersionNumber nowVersion, String[] args) {
if (!ArrayUtils.contains(args, "nofound"))
try {
File f = AppDataUpgraderTask.HMCL_VER_FILE;
if (f.exists()) {
Map<String, String> m = C.gson.fromJson(FileUtils.readFileToString(f), Map.class);
String s = m.get("ver");
if (s != null && VersionNumber.check(s).compareTo(nowVersion) > 0) {
String j = m.get("loc");
if (j != null) {
File jar = new File(j);
if (jar.exists()) {
JarFile jarFile = new JarFile(jar);
String mainClass = jarFile.getManifest().getMainAttributes().getValue("Main-Class");
if (mainClass != null) {
ArrayList<String> al = new ArrayList<>(Arrays.asList(args));
al.add("notfound");
new URLClassLoader(new URL[] {jar.toURI().toURL()},
URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass)
.getMethod("main", String[].class).invoke(null, new Object[] {al.toArray(new String[0])});
return true;
}
}
}
}
}
} catch (Throwable t) {
t.printStackTrace();
}
return false;
}
@Override
public boolean call(Object sender, VersionNumber number) {
((UpdateChecker) sender).requestDownloadLink().subscribeOn(Schedulers.newThread()).observeOn(Schedulers.eventQueue()).subscribe(map -> {
if (map != null && map.containsKey("pack"))
try {
if (TaskWindow.getInstance().addTask(new AppDataUpgraderTask(map.get("pack"), number.version)).start()) {
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);
}
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) {
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);
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.setContents(new StringSelection(url), null);
MessageBox.Show(C.i18n("update.no_browser"));
}
}
});
return true;
}
public static class AppDataUpgraderTask extends Task {
public static final File BASE_FOLDER = MCUtils.getWorkingDirectory("hmcl");
public static final File HMCL_VER_FILE = new File(BASE_FOLDER, "hmclver.json");
public static File getSelf(String ver) {
return new File(BASE_FOLDER, "HMCL-" + ver + ".jar");
}
private final String downloadLink, newestVersion;
File tempFile;
public AppDataUpgraderTask(String downloadLink, String newestVersion) throws IOException {
this.downloadLink = downloadLink;
this.newestVersion = newestVersion;
tempFile = File.createTempFile("hmcl", ".pack.xz");
}
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(new FileDownloadTask(downloadLink, tempFile));
}
@Override
public void executeTask() throws Exception {
HashMap<String, String> json = new HashMap<>();
File f = getSelf(newestVersion);
if (!f.getParentFile().exists())
f.getParentFile().mkdirs();
for (int i = 0; f.exists(); i++)
f = new File(BASE_FOLDER, "HMCL-" + newestVersion + (i > 0 ? "-" + i : "") + ".jar");
f.createNewFile();
try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(f))) {
Pack200.newUnpacker().unpack(new GZIPInputStream(new FileInputStream(tempFile)), jos);
}
json.put("ver", newestVersion);
json.put("loc", f.getAbsolutePath());
String result = C.gson.toJson(json);
FileUtils.write(HMCL_VER_FILE, result);
}
@Override
public String getInfo() {
return "Upgrade";
}
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.utils.upgrade;
import org.jackhuang.hellominecraft.utils.Event;
import org.jackhuang.hellominecraft.utils.VersionNumber;
/**
*
* @author huangyuhui
*/
public abstract class IUpgrader implements Event<VersionNumber> {
public static final IUpgrader NOW_UPGRADER = new AppDataUpgrader();
/**
* Paring arguments to decide on whether the upgrade is needed.
*
* @param nowVersion now launcher version
* @param args Application CommandLine Arguments
* @return true if it is needed to break the main thread to shutdown this
* application.
*/
public abstract boolean parseArguments(VersionNumber nowVersion, String[] args);
/**
* Just download the new app.
*
* @param sender Should be VersionChecker
* @param number the newest version
* @return should return true
*/
@Override
public abstract boolean call(Object sender, VersionNumber number);
}

View File

@ -0,0 +1,68 @@
/*
* 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.utils.upgrade;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.tasks.TaskWindow;
import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.utils.ArrayUtils;
import org.jackhuang.hellominecraft.utils.VersionNumber;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.jackhuang.hellominecraft.utils.system.IOUtils;
/**
*
* @author huangyuhui
*/
public class NewFileUpgrader extends IUpgrader {
@Override
public boolean parseArguments(VersionNumber nowVersion, String[] args) {
int i = ArrayUtils.indexOf(args, "--removeOldLauncher");
if (i != -1 && i < args.length - 1) {
File f = new File(args[i + 1]);
if (f.exists())
f.deleteOnExit();
}
return false;
}
@Override
public boolean call(Object sender, VersionNumber number) {
String str = requestDownloadLink();
File newf = new File(FileUtils.getName(str));
if (TaskWindow.getInstance().addTask(new FileDownloadTask(str, newf)).start()) {
try {
new ProcessBuilder(new String[] {IOUtils.tryGetCanonicalFilePath(newf), "--removeOldLauncher", IOUtils.getRealPath()}).directory(new File(".")).start();
} catch (IOException ex) {
HMCLog.err("Failed to start new app", ex);
}
System.exit(0);
}
return true;
}
private String requestDownloadLink() {
return null;
}
}

View File

@ -1,88 +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.utils.upgrade;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.launcher.utils.MCUtils;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask;
import org.jackhuang.hellominecraft.utils.system.FileUtils;
import org.tukaani.xz.XZInputStream;
/**
*
* @author huangyuhui
*/
public class Upgrader extends Task {
public static final File BASE_FOLDER = MCUtils.getWorkingDirectory("hmcl");
public static final File HMCL_VER_FILE = new File(BASE_FOLDER, "hmclver.json");
public static File getSelf(String ver) {
return new File(BASE_FOLDER, "HMCL-" + ver + ".jar");
}
private final String downloadLink, newestVersion;
File tempFile;
public Upgrader(String downloadLink, String newestVersion) throws IOException {
this.downloadLink = downloadLink;
this.newestVersion = newestVersion;
tempFile = File.createTempFile("hmcl", ".pack.xz");
}
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(new FileDownloadTask(downloadLink, tempFile));
}
@Override
public void executeTask() throws Exception {
HashMap<String, String> json = new HashMap<>();
File f = getSelf(newestVersion);
if (!f.getParentFile().exists())
f.getParentFile().mkdirs();
for (int i = 0; f.exists(); i++)
f = new File(BASE_FOLDER, "HMCL-" + newestVersion + (i > 0 ? "-" + i : "") + ".jar");
f.createNewFile();
try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(f))) {
Pack200.newUnpacker().unpack(new XZInputStream(new FileInputStream(tempFile)), jos);
}
json.put("ver", newestVersion);
json.put("loc", f.getAbsolutePath());
String result = C.gson.toJson(json);
FileUtils.write(HMCL_VER_FILE, result);
}
@Override
public String getInfo() {
return "Upgrade";
}
}

View File

@ -18,7 +18,6 @@
package org.jackhuang.hellominecraft.launcher.views;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

View File

@ -28,7 +28,7 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane12" pref="308" max="32767" attributes="0"/>
<Component id="jScrollPane12" pref="147" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="btnInstall" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>

View File

@ -18,7 +18,6 @@
package org.jackhuang.hellominecraft.launcher.views;
import java.util.List;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import org.jackhuang.hellominecraft.C;
@ -104,7 +103,7 @@ public class InstallerPanel extends AnimatedPanel {
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 308, Short.MAX_VALUE)
.addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 147, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(btnInstall)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

View File

@ -41,7 +41,6 @@ import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.launcher.Main;
import org.jackhuang.hellominecraft.launcher.settings.Settings;
import org.jackhuang.hellominecraft.utils.UpdateChecker;
import org.jackhuang.hellominecraft.utils.Utils;
import org.jackhuang.hellominecraft.views.DropShadowBorder;
import org.jackhuang.hellominecraft.views.TintablePanel;
@ -187,8 +186,7 @@ public final class MainFrame extends DraggableFrame {
@Override
public void mouseClicked(MouseEvent e) {
if (UpdateChecker.OUT_DATED)
Main.update();
Settings.UPDATE_CHECKER.checkOutdate();
}
@Override
@ -314,7 +312,7 @@ public final class MainFrame extends DraggableFrame {
isShowedMessage = false;
reloadColor();
windowTitle.setText(defaultTitle);
windowTitle.setForeground(UpdateChecker.OUT_DATED ? Color.red : Color.white);
windowTitle.setForeground(Settings.UPDATE_CHECKER.OUT_DATED ? Color.red : Color.white);
}
}
@ -354,14 +352,15 @@ public final class MainFrame extends DraggableFrame {
}
private void paintImpl(Graphics g) {
super.paint(g);
g.setColor(borderColor);
int off = enableShadow ? 16 : 0;
int width = 800;
int height = header.getHeight() + 480 - 1;
super.paint(g);
g.setColor(borderColor);
g.drawLine(off, off, off, height + off + 1);
g.drawLine(off + width + 1, off, off + width + 1, height + off + 1);
g.drawLine(off, height + off + 1, off + width + 1, height + off + 1);
g.dispose();
}
@Override

View File

@ -17,7 +17,6 @@
*/
package org.jackhuang.hellominecraft.tasks;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.swing.SwingUtilities;
@ -300,28 +299,16 @@ public class TaskWindow extends javax.swing.JDialog
}
public boolean start() {
Runnable r = () -> {
return SwingUtils.invokeAndWait(() -> {
synchronized (INSTANCE) {
if (INSTANCE.isVisible()) {
flag = false;
return;
}
if (INSTANCE.isVisible())
return false;
TaskWindow tw = inst();
for (Task t : ll)
tw.addTask(t);
flag = tw.start();
return tw.start();
}
};
if (EventQueue.isDispatchThread())
r.run();
else
try {
EventQueue.invokeAndWait(r);
} catch (Exception e) {
HMCLog.err("Failed to invokeAndWait, the UI will work abnormally.", e);
r.run();
}
return flag;
});
}
}
}

View File

@ -0,0 +1,55 @@
/*
* 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.utils;
import java.util.Map;
import rx.Observable;
/**
*
* @author huangyuhui
*/
public interface IUpdateChecker {
/**
*
*/
void checkOutdate();
/**
* Get the <b>cached</b> newest version number, use "process" method to download!
* @return the newest version number
* @see process
*/
VersionNumber getNewVersion();
/**
* Download the version number synchronously.
* When you execute this method first, should leave "showMessage" false.
* @param showMessage If it is requested to warn the user that there is a new version.
* @return the process observable.
*/
Observable process(boolean showMessage);
/**
* Get the download links.
* @return a JSON, which contains the server response.
*/
Observable<Map<String, String>> requestDownloadLink();
}

View File

@ -97,9 +97,9 @@ public class MessageBox {
case YES_NO_OPTION:
case YES_NO_CANCEL_OPTION:
case OK_CANCEL_OPTION:
return JOptionPane.showConfirmDialog(null, Msg, Title, Option - 10);
return SwingUtils.invokeAndWait(() -> JOptionPane.showConfirmDialog(null, Msg, Title, Option - 10));
default:
JOptionPane.showMessageDialog(null, Msg, Title, Option);
SwingUtils.invokeAndWait(() -> JOptionPane.showMessageDialog(null, Msg, Title, Option));
}
return 0;
}

View File

@ -18,6 +18,7 @@
package org.jackhuang.hellominecraft.utils;
import java.util.Map;
import java.util.Objects;
/**
*
@ -52,4 +53,28 @@ public class Pair<K, V> implements Map.Entry<K, V> {
return t;
}
@Override
public int hashCode() {
int hash = 5;
hash = 29 * hash + Objects.hashCode(this.key);
hash = 29 * hash + Objects.hashCode(this.value);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Pair<?, ?> other = (Pair<?, ?>) obj;
if (!Objects.equals(this.key, other.key))
return false;
if (!Objects.equals(this.value, other.value))
return false;
return true;
}
}

View File

@ -17,6 +17,7 @@
*/
package org.jackhuang.hellominecraft.utils;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.net.URI;
import javax.swing.DefaultListModel;
@ -28,6 +29,7 @@ import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableModel;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.utils.functions.NonFunction;
/**
*
@ -177,4 +179,24 @@ public class SwingUtils {
}
return builder.toString();
}
private static final ThreadLocal<Object> THREAD_LOCAL = new ThreadLocal<>();
public static <T> T invokeAndWait(NonFunction<T> x) {
Runnable r = () -> THREAD_LOCAL.set(x.apply());
invokeAndWait(r);
return (T) THREAD_LOCAL.get();
}
public static void invokeAndWait(Runnable r) {
if (EventQueue.isDispatchThread())
r.run();
else
try {
EventQueue.invokeAndWait(r);
} catch (Exception e) {
HMCLog.err("Failed to invokeAndWait, the UI will work abnormally.", e);
r.run();
}
}
}

View File

@ -20,32 +20,31 @@ package org.jackhuang.hellominecraft.utils;
import java.util.Map;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import rx.Observable;
/**
*
* @author huangyuhui
*/
public final class UpdateChecker extends Thread {
public final class UpdateChecker implements IUpdateChecker {
public static boolean OUT_DATED = false;
public boolean OUT_DATED = false;
public VersionNumber base;
public String versionString;
public String type;
public Runnable dl;
public Map<String, String> download_link = null;
private Map<String, String> download_link = null;
public UpdateChecker(VersionNumber base, String type, Runnable dl) {
super("UpdateChecker");
public UpdateChecker(VersionNumber base, String type) {
this.base = base;
this.type = type;
this.dl = dl;
}
VersionNumber value;
@Override
public void run() {
public Observable<VersionNumber> process(boolean showMessage) {
return Observable.createWithEmptySubscription(t -> {
if (value == null) {
try {
versionString = NetUtils.get("http://huangyuhui.duapp.com/info.php?type=" + type);
} catch (Exception e) {
@ -53,33 +52,42 @@ public final class UpdateChecker extends Thread {
return;
}
value = VersionNumber.check(versionString);
process(false);
if (OUT_DATED)
dl.run();
}
public void process(boolean showMessage) {
if (value == null) {
HMCLog.warn("Failed to check update...");
if (showMessage)
MessageBox.Show(C.i18n("update.failed"));
} else if (VersionNumber.isOlder(base, value))
OUT_DATED = true;
if (OUT_DATED)
t.onNext(value);
});
}
@Override
public VersionNumber getNewVersion() {
return value;
}
public synchronized void requestDownloadLink(Runnable finish) {
new Thread(() -> {
@Override
public synchronized Observable<Map<String, String>> requestDownloadLink() {
return Observable.createWithEmptySubscription(t -> {
if (download_link == null)
try {
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);
}
finish.run();
}).start();
t.onNext(download_link);
});
}
public final EventHandler<VersionNumber> outdated = new EventHandler<>(this);
@Override
public void checkOutdate() {
if (OUT_DATED)
outdated.execute(getNewVersion());
}
}

View File

@ -25,12 +25,18 @@ import org.jackhuang.hellominecraft.HMCLog;
*/
public final class VersionNumber implements Comparable<VersionNumber> {
public byte firstVer, secondVer, thirdVer;
public final byte firstVer, secondVer, thirdVer;
public final String version;
public VersionNumber(byte a, byte b, byte c) {
this(a, b, c, null);
}
public VersionNumber(byte a, byte b, byte c, String version) {
firstVer = a;
secondVer = b;
thirdVer = c;
this.version = version;
}
public static VersionNumber check(String data) {
@ -46,7 +52,7 @@ public final class VersionNumber implements Comparable<VersionNumber> {
v1 = Byte.parseByte(ver[0]);
v2 = Byte.parseByte(ver[1]);
v3 = Byte.parseByte(ver[2]);
ur = new VersionNumber(v1, v2, v3);
ur = new VersionNumber(v1, v2, v3, data);
return ur;
} catch (Exception e) {
HMCLog.warn("Failed to parse the version", e);

View File

@ -112,6 +112,18 @@ public class IOUtils {
return arr;
}
public static String getRealPath() {
String realPath = IOUtils.class.getClassLoader().getResource("").getFile();
java.io.File file = new java.io.File(realPath);
realPath = file.getAbsolutePath();
try {
realPath = java.net.URLDecoder.decode(realPath, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return realPath;
}
public static File currentDir() {
return new File(".");
}

View File

@ -26,7 +26,9 @@ import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import javax.swing.border.AbstractBorder;
import org.jackhuang.hellominecraft.utils.Pair;
public class DropShadowBorder extends AbstractBorder {
@ -61,8 +63,14 @@ public class DropShadowBorder extends AbstractBorder {
return getBorderInsets(c);
}
private static final HashMap<Pair<Integer, Integer>, BufferedImage> CACHE = new HashMap<>();
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Pair<Integer, Integer> pair = new Pair<>(width, height);
if (CACHE.containsKey(pair))
g.drawImage(CACHE.get(pair), x, y, width, height, null);
else {
BufferedImage shadow = new BufferedImage(width, height, 2);
Graphics2D g2 = shadow.createGraphics();
@ -84,6 +92,8 @@ public class DropShadowBorder extends AbstractBorder {
shadow = blur.filter(shadow, null);
shadow = blur.filter(shadow, null);
CACHE.put(pair, shadow);
g.drawImage(shadow, x, y, width, height, null);
}
}
}