diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java index 6300ba466..516dad1e7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java @@ -26,6 +26,7 @@ import java.net.PasswordAuthentication; import java.net.Proxy; import java.security.GeneralSecurityException; import java.security.cert.X509Certificate; +import java.util.Arrays; import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; @@ -142,7 +143,7 @@ public final class Main { } }; - HMCLApi.HMCL_VERSION = VersionNumber.check(LAUNCHER_VERSION); + HMCLApi.HMCL_VERSION = VersionNumber.asVersion(LAUNCHER_VERSION); PluginManager.getPlugin(DefaultPlugin.class); for (String s : args) @@ -161,7 +162,7 @@ public final class Main { } PluginManager.loadPlugins(); - IUpgrader.NOW_UPGRADER.parseArguments(HMCLApi.HMCL_VERSION, args); + IUpgrader.NOW_UPGRADER.parseArguments(HMCLApi.HMCL_VERSION, Arrays.asList(args)); System.setProperty("awt.useSystemAAFontSettings", "on"); System.setProperty("swing.aatext", "true"); @@ -231,12 +232,6 @@ public final class Main { }); } - try { - unpackDefaultLog4jConfiguration(); - } catch(IOException e) { - HMCLog.err("Failed to unpack log4j.xml, log window will not work well.", e); - } - MainFrame.showMainFrame(); } } @@ -244,20 +239,6 @@ public final class Main { public static void invokeUpdate() { MainFrame.INSTANCE.invokeUpdate(); } - - public static final File LOG4J_FILE = new File(MCUtils.getWorkingDirectory("hmcl"), "log4j.xml"); - - public static void unpackDefaultLog4jConfiguration() throws IOException { - LOG4J_FILE.getParentFile().mkdirs(); - if (LOG4J_FILE.exists()) return; - LOG4J_FILE.createNewFile(); - try (InputStream is = Main.class.getResourceAsStream("/org/jackhuang/hmcl/log4j.xml"); - FileOutputStream fos = new FileOutputStream(LOG4J_FILE)) { - int b; - while ((b = is.read()) != -1) - fos.write(b); - } - } public static ImageIcon getIcon(String path) { try { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/AppDataUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/AppDataUpgrader.java index 6e95c4b02..d2268bf99 100755 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/AppDataUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/AppDataUpgrader.java @@ -17,20 +17,19 @@ */ package org.jackhuang.hmcl.util.upgrade; -import com.google.gson.JsonSyntaxException; +import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; @@ -45,13 +44,13 @@ import org.jackhuang.hmcl.core.MCUtils; import org.jackhuang.hmcl.util.task.Task; import org.jackhuang.hmcl.util.task.TaskWindow; import org.jackhuang.hmcl.util.net.FileDownloadTask; -import org.jackhuang.hmcl.util.ArrayUtils; import org.jackhuang.hmcl.util.ui.MessageBox; import org.jackhuang.hmcl.util.Utils; import org.jackhuang.hmcl.api.VersionNumber; import org.jackhuang.hmcl.util.StrUtils; import org.jackhuang.hmcl.util.sys.FileUtils; import org.jackhuang.hmcl.util.sys.IOUtils; +import org.jackhuang.hmcl.util.sys.Java; import org.jackhuang.hmcl.util.sys.OS; /** @@ -60,45 +59,49 @@ import org.jackhuang.hmcl.util.sys.OS; */ public class AppDataUpgrader extends IUpgrader { - private boolean launchNewerVersion(String[] args, File jar) throws IOException, PrivilegedActionException { + private void launchNewerVersion(List args, File jar) throws IOException, ReflectiveOperationException { try (JarFile jarFile = new JarFile(jar)) { String mainClass = jarFile.getManifest().getMainAttributes().getValue("Main-Class"); - if (mainClass != null) { - ArrayList al = new ArrayList<>(Arrays.asList(args)); - al.add("--noupdate"); - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - 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 null; - }); - return true; + if (mainClass == null) + throw new ClassNotFoundException("Main-Class not found in manifest"); + ArrayList al = new ArrayList<>(args); + al.add("--noupdate"); + ClassLoader pre = Thread.currentThread().getContextClassLoader(); + try { + ClassLoader now = new URLClassLoader(new URL[] { jar.toURI().toURL() }, ClassLoader.getSystemClassLoader().getParent()); + Thread.currentThread().setContextClassLoader(now); + now.loadClass(mainClass).getMethod("main", String[].class).invoke(null, new Object[] { al.toArray(new String[0]) }); + } finally { + Thread.currentThread().setContextClassLoader(pre); } } - return false; } @Override - public void parseArguments(VersionNumber nowVersion, String[] args) { + public void parseArguments(VersionNumber nowVersion, List args) { File f = AppDataUpgraderPackGzTask.HMCL_VER_FILE; - if (!ArrayUtils.contains(args, "--noupdate")) + if (!args.contains("--noupdate")) try { if (f.exists()) { - Map m = C.GSON.fromJson(FileUtils.read(f), Map.class); + Map m = C.GSON.fromJson(FileUtils.read(f), new TypeToken>() { + }.getType()); String s = m.get("ver"); - if (s != null && VersionNumber.check(s).compareTo(nowVersion) > 0) { + if (s != null && VersionNumber.asVersion(s).compareTo(nowVersion) > 0) { String j = m.get("loc"); if (j != null) { File jar = new File(j); - if (jar.exists() && launchNewerVersion(args, jar)) + if (jar.exists()) { + launchNewerVersion(args, jar); System.exit(0); + } } } } - } catch (JsonSyntaxException ex) { + } catch (JsonParseException ex) { f.delete(); - } catch (IOException | PrivilegedActionException t) { - HMCLog.err("Failed to execute newer version application", t); + } catch (IOException | ReflectiveOperationException t) { + HMCLog.err("Unable to execute newer version application", t); + AppDataUpgraderPackGzTask.HMCL_VER_FILE.delete(); // delete version json, let HMCL re-download the newer version. } } @@ -106,33 +109,49 @@ public class AppDataUpgrader extends IUpgrader { public void accept(SimpleEvent event) { final VersionNumber version = event.getValue(); ((UpdateChecker) event.getSource()).requestDownloadLink().reg(map -> { - if (MessageBox.show(C.i18n("update.newest_version") + version.firstVer + "." + version.secondVer + "." + version.thirdVer + "\n" + boolean flag = false; + for (Java java : Java.JAVA) + if (java.getName().startsWith("1.8") || java.getName().startsWith("9") || java.getName().startsWith("10")) { + flag = true; + break; + } + if (!flag) { + MessageBox.show("请安装 Java 8"); + try { + java.awt.Desktop.getDesktop().browse(new URI("https://java.com")); + } catch (URISyntaxException | IOException e) { + Utils.setClipboard("https://java.com"); + MessageBox.show(C.i18n("update.no_browser")); + } + } + + if (MessageBox.show(C.i18n("update.newest_version") + version.toString() + "\n" + C.i18n("update.should_open_link"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - if (map != null && map.containsKey("jar") && !StrUtils.isBlank(map.get("jar"))) - try { - String hash = null; - if (map.containsKey("jarsha1")) - hash = map.get("jarsha1"); - if (TaskWindow.factory().append(new AppDataUpgraderJarTask(map.get("jar"), version.version, hash)).execute()) { - new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderJarTask.getSelf(version.version).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start(); - System.exit(0); - } - } catch (IOException ex) { - Main.LOGGER.log(Level.SEVERE, "Failed to create upgrader", ex); - } - else if (map != null && map.containsKey("pack") && !StrUtils.isBlank(map.get("pack"))) + if (map != null && map.containsKey("pack") && !StrUtils.isBlank(map.get("pack"))) try { String hash = null; if (map.containsKey("packsha1")) hash = map.get("packsha1"); - if (TaskWindow.factory().append(new AppDataUpgraderPackGzTask(map.get("pack"), version.version, hash)).execute()) { - new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.version).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start(); + if (TaskWindow.factory().append(new AppDataUpgraderPackGzTask(map.get("pack"), version.toString(), hash)).execute()) { + new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start(); System.exit(0); } } catch (IOException ex) { HMCLog.err("Failed to create upgrader", ex); } + else if (map != null && map.containsKey("jar") && !StrUtils.isBlank(map.get("jar"))) + try { + String hash = null; + if (map.containsKey("jarsha1")) + hash = map.get("jarsha1"); + if (TaskWindow.factory().append(new AppDataUpgraderJarTask(map.get("jar"), version.toString(), hash)).execute()) { + new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderJarTask.getSelf(version.toString()).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start(); + System.exit(0); + } + } catch (IOException ex) { + Main.LOGGER.log(Level.SEVERE, "Failed to create upgrader", ex); + } else { String url = C.URL_PUBLISH; if (map != null) @@ -153,6 +172,8 @@ public class AppDataUpgrader extends IUpgrader { }).execute(); } + ; + public static class AppDataUpgraderPackGzTask extends Task { public static final File BASE_FOLDER = MCUtils.getWorkingDirectory("hmcl"); @@ -174,7 +195,7 @@ public class AppDataUpgrader extends IUpgrader { @Override public Collection getDependTasks() { - return Arrays.asList(new FileDownloadTask(downloadLink, tempFile, expectedHash)); + return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, expectedHash)); } @Override @@ -193,8 +214,9 @@ public class AppDataUpgrader extends IUpgrader { if (!f.createNewFile()) throw new IOException("Failed to create new file: " + f); - try (JarOutputStream jos = new JarOutputStream(FileUtils.openOutputStream(f))) { - Pack200.newUnpacker().unpack(new GZIPInputStream(FileUtils.openInputStream(tempFile)), jos); + try (GZIPInputStream in = new GZIPInputStream(FileUtils.openInputStream(tempFile)); + JarOutputStream jos = new JarOutputStream(FileUtils.openOutputStream(f))) { + Pack200.newUnpacker().unpack(in, jos); } json.put("ver", newestVersion); json.put("loc", f.getAbsolutePath()); @@ -230,7 +252,7 @@ public class AppDataUpgrader extends IUpgrader { @Override public Collection getDependTasks() { - return Arrays.asList(new FileDownloadTask(downloadLink, tempFile, expectedHash)); + return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, expectedHash)); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/IUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/IUpgrader.java index 9812805e1..2907b0668 100755 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/IUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/IUpgrader.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.util.upgrade; +import java.util.List; import org.jackhuang.hmcl.api.event.SimpleEvent; import org.jackhuang.hmcl.api.VersionNumber; import org.jackhuang.hmcl.api.func.Consumer; @@ -35,7 +36,7 @@ public abstract class IUpgrader implements Consumer> * @param nowVersion now launcher version * @param args Application CommandLine Arguments */ - public abstract void parseArguments(VersionNumber nowVersion, String[] args); + public abstract void parseArguments(VersionNumber nowVersion, List args); /** * Just download the new app. diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/NewFileUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/NewFileUpgrader.java deleted file mode 100755 index 19c1fc769..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/NewFileUpgrader.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.upgrade; - -import java.io.File; -import java.io.IOException; -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.util.net.FileDownloadTask; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.api.VersionNumber; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * - * @author huangyuhui - */ -public class NewFileUpgrader extends IUpgrader { - - @Override - public void 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(); - } - } - - @Override - public void accept(SimpleEvent event) { - String str = requestDownloadLink(); - File newf = new File(FileUtils.getName(str)); - if (TaskWindow.factory().append(new FileDownloadTask(str, newf)).execute()) { - try { - new ProcessBuilder(new String[] { newf.getCanonicalPath(), "--removeOldLauncher", IOUtils.getRealPath() }).directory(new File("").getAbsoluteFile()).start(); - } catch (IOException ex) { - HMCLog.err("Failed to start new app", ex); - } - System.exit(0); - } - } - - private String requestDownloadLink() { - return null; - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/UpdateChecker.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/UpdateChecker.java index 4c1aa105e..8ad33c25a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/UpdateChecker.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/UpdateChecker.java @@ -25,6 +25,7 @@ import com.google.gson.JsonSyntaxException; import java.io.IOException; import org.jackhuang.hmcl.api.HMCLog; import java.util.Map; +import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.api.HMCLApi; import org.jackhuang.hmcl.api.event.SimpleEvent; import org.jackhuang.hmcl.api.event.OutOfDateEvent; @@ -61,15 +62,15 @@ public final class UpdateChecker implements IUpdateChecker { @Override protected void work() throws Exception { if (value == null) { - versionString = NetUtils.get("http://huangyuhui.duapp.com/info.php?type=" + type); - value = VersionNumber.check(versionString); + versionString = NetUtils.get("http://hmcl.huangyuhui.net/api/update?version=" + Main.LAUNCHER_VERSION); + value = VersionNumber.asVersion(versionString); } if (value == null) { HMCLog.warn("Failed to check update..."); if (showMessage) MessageBox.show(C.i18n("update.failed")); - } else if (VersionNumber.isOlder(base, value)) + } else if (base.compareTo(value) < 0) outOfDate = true; if (outOfDate) publish(value); @@ -89,7 +90,7 @@ public final class UpdateChecker implements IUpdateChecker { protected void work() throws Exception { if (download_link == null) try { - download_link = C.GSON.>fromJson(NetUtils.get("http://huangyuhui.duapp.com/update_link.php?type=" + type), Map.class); + download_link = C.GSON.>fromJson(NetUtils.get("http://hmcl.huangyuhui.net/api/update_link?version=" + Main.LAUNCHER_VERSION), Map.class); } catch (JsonSyntaxException | IOException e) { HMCLog.warn("Failed to get update link.", e); } diff --git a/HMCL/src/main/resources/org/jackhuang/hmcl/log4j.xml b/HMCL/src/main/resources/org/jackhuang/hmcl/log4j.xml deleted file mode 100644 index 609a674ff..000000000 --- a/HMCL/src/main/resources/org/jackhuang/hmcl/log4j.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ComposedVersionNumber.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ComposedVersionNumber.java new file mode 100644 index 000000000..769d87acf --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ComposedVersionNumber.java @@ -0,0 +1,55 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2013 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.api; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * If a version string contains '-', a {@link ComposedVersionNumber} + * will be generated. + * + * Formats like 1.7.10-OptiFine, 1.12.2-Forge + * + * @author huangyuhui + */ +public final class ComposedVersionNumber extends VersionNumber { + List composed; + + public static boolean isComposedVersionNumber(String version) { + return version.contains("-"); + } + + ComposedVersionNumber(String version) { + composed = Arrays.stream(version.split("-")) + .map(VersionNumber::asVersion) + .collect(Collectors.toList()); + } + + @Override + public int hashCode() { + return Objects.hash(composed); + } + + @Override + public String toString() { + return composed.stream().map(VersionNumber::toString).collect(Collectors.joining("-")); + } +} \ No newline at end of file diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IntVersionNumber.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IntVersionNumber.java new file mode 100644 index 000000000..76eaf487b --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IntVersionNumber.java @@ -0,0 +1,73 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2013 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.api; + +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * If a version string formats x.x.x.x, a {@code IntVersionNumber} + * will be generated. + * + * @author huangyuhui + */ +public final class IntVersionNumber extends VersionNumber { + + final List version; + + public static boolean isIntVersionNumber(String version) { + if (version.contains("..")) return false; + if (version.trim().isEmpty()) return false; + for (char ch : version.toCharArray()) + if (ch != '.' && (ch < '0' || ch > '9')) + return false; + return true; + } + + IntVersionNumber(String version) { + if (!isIntVersionNumber(version)) + throw new IllegalArgumentException("The version " + version + " is malformed, only dots and digits are allowed."); + + String[] slice = version.split("\\."); + List versions = new LinkedList<>(); + for (String str : slice) versions.add(Integer.parseInt(str)); + while (!versions.isEmpty() && versions.get(versions.size() - 1) == 0) + versions.remove(versions.size() - 1); + + this.version = versions; + } + + public int get(int index) { + return version.get(index); + } + + @Override + public int hashCode() { + return Objects.hash(version); + } + + @Override + public String toString() { + List seq = new LinkedList<>(); + for (int str : version) + seq.add(Integer.toString(str)); + return String.join(".", seq); + } +} \ No newline at end of file diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/StringVersionNumber.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/StringVersionNumber.java new file mode 100644 index 000000000..cee4ea221 --- /dev/null +++ b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/StringVersionNumber.java @@ -0,0 +1,51 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2013 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.api; + +import java.util.Objects; + +/** + * If a version string contains alphabets, a {@code StringVersionNumber} + * will be constructed. + * + * @author huangyuhui + */ +public final class StringVersionNumber extends VersionNumber { + + private final String version; + + StringVersionNumber(String version) { + Objects.requireNonNull(version); + this.version = version; + } + + public String getVersion() { + return version; + } + + @Override + public int hashCode() { + return version.hashCode(); + } + + @Override + public String toString() { + return version; + } + +} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/VersionNumber.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/VersionNumber.java index 50d7ef5e2..e11580458 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/VersionNumber.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/VersionNumber.java @@ -17,100 +17,85 @@ */ package org.jackhuang.hmcl.api; +import java.util.*; + /** + * The formatted version number represents a version string. * * @author huangyuhui */ -public final class VersionNumber implements Comparable { +public abstract class VersionNumber implements Comparable { - public final byte firstVer, secondVer, thirdVer; - public final String version; - - public VersionNumber(byte a, byte b, byte c) { - this(a, b, c, null); + public static VersionNumber asVersion(String version) { + Objects.requireNonNull(version); + if (ComposedVersionNumber.isComposedVersionNumber(version)) + return new ComposedVersionNumber(version); + else if (IntVersionNumber.isIntVersionNumber(version)) + return new IntVersionNumber(version); + else + return new StringVersionNumber(version); } - public VersionNumber(byte a, byte b, byte c, String version) { - firstVer = a; - secondVer = b; - thirdVer = c; - this.version = version; + public static Optional parseVersion(String str) { + if (IntVersionNumber.isIntVersionNumber(str)) + return Optional.of(new IntVersionNumber(str).toString()); + else + return Optional.empty(); } @Override - public String toString() { - return "" + firstVer + '.' + secondVer + '.' + thirdVer; - } - - public static VersionNumber check(String data) { - while (!data.isEmpty() && ((data.charAt(0) < '0' || data.charAt(0) > '9') && data.charAt(0) != '.')) - data = data.substring(1); - if (data.isEmpty()) - return null; - VersionNumber ur; - String[] ver = data.split("\\."); - if (ver.length >= 3) { - byte v1, v2, v3; - try { - v1 = Byte.parseByte(ver[0]); - v2 = Byte.parseByte(ver[1]); - v3 = Byte.parseByte(ver[2]); - ur = new VersionNumber(v1, v2, v3, data); - return ur; - } catch (Exception e) { - HMCLog.warn("Failed to parse the version", e); - } - } - return null; - } - - public static boolean isOlder(VersionNumber a, VersionNumber b) { - if (a.firstVer < b.firstVer) - return true; - else if (a.firstVer == b.firstVer) - if (a.secondVer < b.secondVer) - return true; - else if (a.secondVer == b.secondVer) - if (a.thirdVer < b.thirdVer) - return true; - return false; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 83 * hash + this.firstVer; - hash = 83 * hash + this.secondVer; - hash = 83 * hash + this.thirdVer; - return hash; + public int compareTo(VersionNumber o) { + return COMPARATOR.compare(this, o); } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final VersionNumber other = (VersionNumber) obj; - if (this.firstVer != other.firstVer) - return false; - if (this.secondVer != other.secondVer) - return false; - if (this.thirdVer != other.thirdVer) - return false; - return true; - } - - @Override - public int compareTo(VersionNumber o) { - if (isOlder(this, o)) - return -1; - else if (isOlder(o, this)) - return 1; - else - return 0; + if (obj == null) return false; + else return toString().equals(obj.toString()); } -} + private static > int compareTo(List a, List b) { + int i; + for (i = 0; i < a.size() && i < b.size(); ++i) { + int res = a.get(i).compareTo(b.get(i)); + if (res != 0) + return res; + } + if (i < a.size()) return 1; + else if (i < b.size()) return -1; + else return 0; + } + + public static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(VersionNumber a, VersionNumber b) { + if (a == null || b == null) + return 0; + else { + if (a instanceof ComposedVersionNumber) { + if (b instanceof ComposedVersionNumber) + return compareTo(((ComposedVersionNumber) a).composed, ((ComposedVersionNumber) b).composed); + else + return compare(((ComposedVersionNumber) a).composed.get(0), b); + } else if (a instanceof IntVersionNumber) { + if (b instanceof ComposedVersionNumber) + return -compare(b, a); + else if (b instanceof IntVersionNumber) + return compareTo(((IntVersionNumber) a).version, ((IntVersionNumber) b).version); + else if (b instanceof StringVersionNumber) + return a.toString().compareTo(b.toString()); + } else if (a instanceof StringVersionNumber) { + if (b instanceof ComposedVersionNumber) + return -compare(b, a); + else if (b instanceof StringVersionNumber) + return a.toString().compareTo(b.toString()); + else if (b instanceof IntVersionNumber) + return a.toString().compareTo(b.toString()); + } + + throw new IllegalArgumentException("Unrecognized VersionNumber " + a + " and " + b); + } + } + + }; +} \ No newline at end of file diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsMojangLoader.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsMojangLoader.java index b8e78dcfb..630e23b13 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsMojangLoader.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsMojangLoader.java @@ -95,9 +95,9 @@ public class AssetsMojangLoader extends IAssetsHandler { @Override public boolean isVersionAllowed(String formattedVersion) { - VersionNumber ur = VersionNumber.check(formattedVersion); + VersionNumber ur = VersionNumber.asVersion(formattedVersion); if (ur == null) return false; - return VersionNumber.check("1.6.0").compareTo(ur) <= 0; + return VersionNumber.asVersion("1.6.0").compareTo(ur) <= 0; } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/FileUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/FileUtils.java index 18dbcec61..0ab4a630d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/FileUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/FileUtils.java @@ -27,7 +27,6 @@ import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.Objects; import org.jackhuang.hmcl.api.HMCLog; diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.lang b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.lang index a0c15aa91..66157f416 100644 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.lang +++ b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.lang @@ -390,7 +390,7 @@ update.no_browser=无法打开浏览器,网址已经复制到剪贴板了, update.should_open_link=是否更新? update.newest_version=最新版本为: update.failed=检查更新失败 -update.found=(发现更新!) +update.found=(点击此处更新) logwindow.terminate_game=结束游戏进程 logwindow.title=日志 diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.properties b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.properties index f29e92004..1d1571276 100644 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.properties +++ b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.properties @@ -390,7 +390,7 @@ update.no_browser=\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u 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.found=(\u70b9\u51fb\u6b64\u5904\u66f4\u65b0) logwindow.terminate_game=\u7ed3\u675f\u6e38\u620f\u8fdb\u7a0b logwindow.title=\u65e5\u5fd7