diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java index 60136f92d..7db7f66d1 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Launcher.java @@ -22,8 +22,6 @@ import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import javax.swing.SwingUtilities; import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; @@ -91,6 +89,9 @@ public final class Launcher { SwingUtilities.invokeLater(() -> LogWindow.instance.setVisible(true)); } + if (!JdkVersion.isJava64Bit() && Platform.getPlatform() == Platform.BIT_64) + MessageBox.Show(C.i18n("advice.os64butjdk32")); + URL[] urls = new URL[len]; try { @@ -103,12 +104,9 @@ public final class Launcher { return; } - if (!JdkVersion.isJava64Bit() && Platform.getPlatform() == Platform.BIT_64) - MessageBox.Show(C.i18n("advice.os64butjdk32")); - Method minecraftMain; try { - minecraftMain = new URLClassLoader(urls).loadClass(mainClass).getMethod("main", String[].class); + minecraftMain = new URLClassLoader(urls, URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass).getMethod("main", String[].class); } catch (ClassNotFoundException | NoSuchMethodException | SecurityException t) { MessageBox.Show(C.i18n("crash.main_class_not_found")); println("Minecraft main class not found."); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java index 9b9228d32..cfbd18e52 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java @@ -26,19 +26,22 @@ 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.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.utils.functions.NonConsumer; import org.jackhuang.hellominecraft.HMCLog; import org.jackhuang.hellominecraft.launcher.launch.GameLauncher; import org.jackhuang.hellominecraft.launcher.utils.CrashReporter; @@ -47,18 +50,24 @@ 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.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.system.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; /** * * @author huangyuhui */ -public final class Main implements NonConsumer { - +public final class Main implements Runnable { + private static final X509TrustManager xtm = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { @@ -91,7 +100,7 @@ public final class Main implements NonConsumer { } public static String launcherName = "Hello Minecraft! Launcher"; - public static byte firstVer = 2, secondVer = 3, thirdVer = 4, forthVer = 12; + public static byte firstVer = 2, secondVer = 3, thirdVer = 4, forthVer = 13; public static int minimumLauncherVersion = 16; /** @@ -116,6 +125,31 @@ public final class Main implements NonConsumer { public static void main(String[] args) { { + if (!ArrayUtils.contains(args, "nofound")) + try { + File f = Upgrader.HMCL_VER_FILE; + if (f.exists()) { + Map 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) { + new URLClassLoader(new URL[]{jar.toURI().toURL()}, URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass).getMethod("main", String[].class).invoke(null, new Object[]{new String[]{"nofound"}}); + return; + } + } + } + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + Thread.setDefaultUncaughtExceptionHandler(new CrashReporter(true)); try { @@ -152,43 +186,54 @@ public final class Main implements NonConsumer { } }); } - + MainFrame.showMainFrame(Settings.isFirstLoad()); } } @Override - public void onDone() { + public void run() { GameLauncher.PROCESS_MANAGER.stopAllProcesses(); } public static void update() { - 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) { - Map map = Settings.UPDATE_CHECKER.download_link; - 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); + Settings.UPDATE_CHECKER.requestDownloadLink(() -> { + SwingUtilities.invokeLater(() -> { + Map 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")); - } - } else - Settings.getInstance().setCheckUpdate(false); + Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); + cb.setContents(new StringSelection(url), null); + MessageBox.Show(C.i18n("update.no_browser")); + } + } + }); + }); } public static void invokeUpdate() { - if (Settings.getInstance().isCheckUpdate()) update(); MainFrame.instance.invokeUpdate(); } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/AbstractMinecraftLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/AbstractMinecraftLoader.java index 3531475d9..44f115932 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/AbstractMinecraftLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/AbstractMinecraftLoader.java @@ -58,6 +58,11 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader { HMCLog.log("On making head command."); String str = v.getJavaDir(); + if(!v.getJavaDirFile().exists()) { + MessageBox.Show(C.i18n("launch.wrong_javadir")); + v.setJava(null); + str = v.getJavaDir(); + } JdkVersion jv = new JdkVersion(str); if (Settings.getInstance().getJava().contains(jv)) jv = Settings.getInstance().getJava().get(Settings.getInstance().getJava().indexOf(jv)); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncher.java index 333c839c3..4da995ccf 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncher.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/GameLauncher.java @@ -133,6 +133,7 @@ public class GameLauncher { HMCLog.warn("Failed to invoke precalled command", ex); } } + HMCLog.log("Starting process"); ProcessBuilder builder = new ProcessBuilder(str); builder.directory(provider.getRunDirectory(get.getSelectedMinecraftVersion().id)) .environment().put("APPDATA", get.getCanonicalGameDirFile().getPath()); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchFinisher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchFinisher.java index 162c53556..d9491287c 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchFinisher.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LaunchFinisher.java @@ -49,6 +49,7 @@ public class LaunchFinisher implements Event> { System.exit(0); return true; }); + jpm.start(); return true; }); obj.launch(str); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LibraryDownloadTask.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LibraryDownloadTask.java index c4b14d90b..e17e9e416 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LibraryDownloadTask.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/launch/LibraryDownloadTask.java @@ -20,10 +20,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; -import java.io.RandomAccessFile; -import java.net.HttpURLConnection; import java.net.URL; import java.util.Arrays; import java.util.jar.JarEntry; @@ -31,8 +28,7 @@ import java.util.jar.JarOutputStream; import java.util.jar.Pack200; import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; -import org.jackhuang.hellominecraft.tasks.Task; -import org.jackhuang.hellominecraft.tasks.download.NetException; +import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask; import org.jackhuang.hellominecraft.utils.system.IOUtils; import org.tukaani.xz.XZInputStream; @@ -40,13 +36,12 @@ import org.tukaani.xz.XZInputStream; * * @author huangyuhui */ -public class LibraryDownloadTask extends Task { - - private static final int MAX_BUFFER_SIZE = 2048; +public class LibraryDownloadTask extends FileDownloadTask { GameLauncher.DownloadLibraryJob job; public LibraryDownloadTask(GameLauncher.DownloadLibraryJob job) { + super(); this.job = job; } @@ -76,95 +71,11 @@ public class LibraryDownloadTask extends Task { return false; } } - - InputStream stream; - RandomAccessFile file; - boolean shouldContinue = true; - int size = -1; - + boolean download(URL url, File filePath) { - HMCLog.log("Downloading: " + url + " to " + filePath); - size = -1; - int downloaded = 0; - for (int repeat = 0; repeat < 6; repeat++) { - if (repeat > 0) - HMCLog.warn("Failed to download, repeat: " + repeat); - try { - - // Open connection to URL. - HttpURLConnection connection - = (HttpURLConnection) url.openConnection(); - - connection.setConnectTimeout(5000); - connection.setRequestProperty("User-Agent", "Hello Minecraft! Launcher"); - - // Connect to server. - connection.connect(); - - // Make sure response code is in the 200 range. - if (connection.getResponseCode() / 100 != 2) { - setFailReason(new NetException(C.i18n("download.not_200") + " " + connection.getResponseCode())); - return false; - } - - // Check for valid content length. - int contentLength = connection.getContentLength(); - if (contentLength < 1) { - setFailReason(new NetException("The content length is invalid.")); - return false; - } - - // Set the size for this download if it hasn't been already set. - if (size == -1) - size = contentLength; - - filePath.getParentFile().mkdirs(); - - File tempFile = new File(filePath.getAbsolutePath() + ".hmd"); - if (!tempFile.exists()) - tempFile.createNewFile(); - - // Open file and seek to the end of it. - file = new RandomAccessFile(tempFile, "rw"); - file.seek(downloaded); - stream = connection.getInputStream(); - while (true) { - // Size buffer according to how much of the file is left to download. - if (!shouldContinue) { - closeFiles(); - filePath.delete(); - break; - } - - byte buffer[] = new byte[MAX_BUFFER_SIZE]; - - // Read from server into buffer. - int read = stream.read(buffer); - if (read == -1) - break; - - // Write buffer to file. - file.write(buffer, 0, read); - downloaded += read; - - if (ppl != null) - ppl.setProgress(this, downloaded, size); - } - closeFiles(); - if (aborted) - tempFile.delete(); - else - tempFile.renameTo(filePath); - if (ppl != null) - ppl.onProgressProviderDone(this); - return true; - } catch (Exception e) { - setFailReason(new NetException(C.i18n("download.failed") + " " + url, e)); - } finally { - closeFiles(); - } - } - return false; + this.url = url; + this.filePath = filePath; + return super.executeTask(); } public static void unpackLibrary(File output, File input) @@ -211,33 +122,6 @@ public class LibraryDownloadTask extends Task { temp.delete(); } - private void closeFiles() { - // Close file. - if (file != null) - try { - file.close(); - file = null; - } catch (IOException e) { - HMCLog.warn("Failed to close file", e); - } - - // Close connection to server. - if (stream != null) - try { - stream.close(); - stream = null; - } catch (IOException e) { - HMCLog.warn("Failed to close stream", e); - } - } - - @Override - public boolean abort() { - shouldContinue = false; - aborted = true; - return true; - } - @Override public String getInfo() { return C.i18n("download") + ": " + job.name; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Config.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Config.java index 9cf7695ad..051652224 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Config.java @@ -125,15 +125,6 @@ public final class Config { return configurations; } - public boolean isCheckUpdate() { - return checkUpdate; - } - - public void setCheckUpdate(boolean checkUpdate) { - this.checkUpdate = checkUpdate; - Settings.save(); - } - public Map getYggdrasilConfig() { return yggdrasil; } @@ -149,8 +140,6 @@ public final class Config { private int downloadtype; @SerializedName("configurations") private TreeMap configurations; - @SerializedName("checkUpdate") - private boolean checkUpdate; @SerializedName("yggdrasil") private Map yggdrasil; @@ -158,7 +147,6 @@ public final class Config { clientToken = UUID.randomUUID().toString(); username = ""; logintype = downloadtype = 0; - checkUpdate = true; configurations = new TreeMap<>(); Profile profile = new Profile(); configurations.put(profile.getName(), profile); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Profile.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Profile.java index 56599fcf2..08b9750c4 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Profile.java @@ -165,9 +165,13 @@ public final class Profile { } public void setJava(Java java) { - int idx = Settings.JAVA.indexOf(java); - if (idx == -1) return; - this.java = java.getName(); + if (java == null) + this.java = Settings.JAVA.get(0).getName(); + else { + int idx = Settings.JAVA.indexOf(java); + if (idx == -1) return; + this.java = java.getName(); + } Settings.save(); } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Settings.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Settings.java index 61c893d9b..d2e26f649 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/settings/Settings.java @@ -69,7 +69,7 @@ public final class Settings { e.checkFormat(); UPDATE_CHECKER = new UpdateChecker(new VersionNumber(Main.firstVer, Main.secondVer, Main.thirdVer), - "hmcl", settings.isCheckUpdate(), Main::invokeUpdate); + "hmcl", Main::invokeUpdate); List temp = new ArrayList<>(); temp.add(new Java("Default", System.getProperty("java.home"))); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java index a4c40cb93..f338d3e44 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/MCUtils.java @@ -20,15 +20,8 @@ import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Map; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.jackhuang.hellominecraft.C; import org.jackhuang.hellominecraft.HMCLog; import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex; import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsObject; @@ -42,7 +35,6 @@ import org.jackhuang.hellominecraft.utils.system.FileUtils; import org.jackhuang.hellominecraft.utils.system.IOUtils; import org.jackhuang.hellominecraft.version.MinecraftVersionRequest; import org.jackhuang.hellominecraft.utils.NetUtils; -import org.jackhuang.hellominecraft.utils.Pair; import org.jackhuang.hellominecraft.utils.system.OS; /** @@ -188,30 +180,33 @@ public final class MCUtils { } } - public static File getLocation() { - String baseName = "minecraft"; - String str1 = System.getProperty("user.home", "."); + public static File getWorkingDirectory(String baseName) { + String userhome = System.getProperty("user.home", "."); File file; switch (OS.os()) { case LINUX: - file = new File(str1, '.' + (String) baseName + '/'); + file = new File(userhome, '.' + baseName + '/'); break; case WINDOWS: - String str2; - if ((str2 = System.getenv("APPDATA")) != null) - file = new File(str2, "." + baseName + '/'); + String appdata = System.getenv("APPDATA"); + if (appdata != null) + file = new File(appdata, "." + baseName + '/'); else - file = new File(str1, '.' + baseName + '/'); + file = new File(userhome, '.' + baseName + '/'); break; case OSX: - file = new File(str1, "Library/Application Support/" + baseName); + file = new File(userhome, "Library/Application Support/" + baseName); break; default: - file = new File(str1, baseName + '/'); + file = new File(userhome, baseName + '/'); } return file; } + public static File getLocation() { + return getWorkingDirectory("minecraft"); + } + public static boolean is16Folder(String path) { path = IOUtils.addSeparator(path); return new File(path, "versions").exists(); @@ -252,7 +247,7 @@ public final class MCUtils { } return null; } - + public static boolean downloadMinecraftJar(File gameDir, String id, DownloadType sourceType) { String vurl = sourceType.getProvider().getVersionsDownloadURL() + id + "/"; File vpath = new File(gameDir, "versions/" + id); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/upgrade/Upgrader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/upgrade/Upgrader.java new file mode 100644 index 000000000..83fe8ba34 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/utils/upgrade/Upgrader.java @@ -0,0 +1,91 @@ +/* + * Copyright 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 2 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. + */ +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 getDependTasks() { + return Arrays.asList(new FileDownloadTask(downloadLink, tempFile)); + } + + @Override + public boolean executeTask() { + HashMap json = new HashMap<>(); + File f = getSelf(newestVersion); + try { + 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); + return true; + } catch (IOException e) { + setFailReason(e); + return false; + } + } + + @Override + public String getInfo() { + return "Upgrade"; + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainFrame.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainFrame.java index 395015865..e111fbad9 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainFrame.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainFrame.java @@ -372,7 +372,6 @@ public final class MainFrame extends DraggableFrame { } public void invokeUpdate() { - if (!isVisible()) return; defaultTitle = defaultTitle + C.i18n("update.found"); if (!isShowedMessage) { windowTitle.setText(defaultTitle); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java index 069f5416d..a4989432c 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/views/MainPagePanel.java @@ -238,8 +238,8 @@ public class MainPagePanel extends javax.swing.JPanel { .addComponent(pnlPassword, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(pnlMoreLayout.createSequentialGroup() .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel10) - .addComponent(jLabel1)) + .addComponent(jLabel10, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel1, 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) diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/C.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/C.java index 7068c14a8..ad1f0ff26 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/C.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/C.java @@ -51,7 +51,7 @@ public final class C { try { return String.format(C.I18N.getString(a), format); } catch (Exception e) { - HMCLog.warn("Failed to read localization lang: " + a, e); + HMCLog.warn("Failed to read localization key: " + a, e); return a; } } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java index 739e14859..1faef0b43 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskList.java @@ -22,7 +22,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -import org.jackhuang.hellominecraft.utils.functions.NonConsumer; import org.jackhuang.hellominecraft.HMCLog; /** @@ -32,7 +31,7 @@ import org.jackhuang.hellominecraft.HMCLog; public class TaskList extends Thread { List taskQueue = Collections.synchronizedList(new ArrayList()); - ArrayList allDone = new ArrayList(); + ArrayList allDone = new ArrayList(); ArrayList> taskListener = new ArrayList(); int totTask; @@ -46,7 +45,7 @@ public class TaskList extends Thread { taskQueue.clear(); } - public void addAllDoneListener(NonConsumer l) { + public void addAllDoneListener(Runnable l) { allDone.add(l); } @@ -100,8 +99,7 @@ public class TaskList extends Thread { try { if (this.isInterrupted()) return; Thread.sleep(1); - } catch (InterruptedException ex) { - HMCLog.warn("Failed to sleep task thread", ex); + } catch (InterruptedException ignore) { } } @@ -148,8 +146,8 @@ public class TaskList extends Thread { for (Task taskQueue1 : taskQueue) executeTask(taskQueue1); if (shouldContinue) - for (NonConsumer d : allDone) - d.onDone(); + for (Runnable d : allDone) + d.run(); } public boolean isEmpty() { diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java index f95f05d63..5f0497d37 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/TaskWindow.java @@ -19,7 +19,6 @@ package org.jackhuang.hellominecraft.tasks; import java.util.ArrayList; import javax.swing.SwingUtilities; import org.jackhuang.hellominecraft.C; -import org.jackhuang.hellominecraft.utils.functions.NonConsumer; import org.jackhuang.hellominecraft.HMCLog; import org.jackhuang.hellominecraft.utils.system.MessageBox; import org.jackhuang.hellominecraft.utils.StrUtils; @@ -30,7 +29,7 @@ import org.jackhuang.hellominecraft.utils.SwingUtils; * @author huangyuhui */ public class TaskWindow extends javax.swing.JDialog - implements ProgressProviderListener, NonConsumer, DoingDoneListener { + implements ProgressProviderListener, Runnable, DoingDoneListener { private static final TaskWindow instance = new TaskWindow(); @@ -202,7 +201,7 @@ public class TaskWindow extends javax.swing.JDialog } @Override - public void onDone() { + public void run() { suc = true; this.dispose(); HMCLog.log("Tasks are finished."); @@ -259,7 +258,9 @@ public class TaskWindow extends javax.swing.JDialog @Override public void setStatus(Task task, String sta) { SwingUtilities.invokeLater(() -> { - SwingUtils.setValueAt(lstDownload, sta, lstDownload.getRowCount(), 0); + int idx = tasks.indexOf(task); + if (idx == -1) return; + SwingUtils.setValueAt(lstDownload, task.getInfo() + ": " + sta, idx, 0); }); } } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java index 7e54765a3..c59075ca7 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/FileDownloadTask.java @@ -38,12 +38,14 @@ import org.jackhuang.hellominecraft.utils.system.IOUtils; public class FileDownloadTask extends Task implements PreviousResult, PreviousResultRegistrar { // Max size of download buffer. - private static final int MAX_BUFFER_SIZE = 2048; + protected static final int MAX_BUFFER_SIZE = 2048; - private URL url; // download URL - private int size; // size of download in bytes - private int downloaded; // number of bytes downloaded - private final File filePath; + protected URL url; // download URL + protected int downloaded = 0; // number of bytes downloaded + protected File filePath; + + public FileDownloadTask() { + } public FileDownloadTask(File filePath) { this((URL) null, filePath); @@ -56,8 +58,6 @@ public class FileDownloadTask extends Task implements PreviousResult, Prev // Constructor for Download. public FileDownloadTask(URL url, File filePath) { this.url = url; - size = -1; - downloaded = 0; this.filePath = filePath; } @@ -124,10 +124,6 @@ public class FileDownloadTask extends Task implements PreviousResult, Prev return false; } - // Set the size for this download if it hasn't been already set. - if (size == -1) - size = contentLength; - filePath.getParentFile().mkdirs(); File tempFile = new File(filePath.getAbsolutePath() + ".hmd"); @@ -135,10 +131,11 @@ public class FileDownloadTask extends Task implements PreviousResult, Prev tempFile.createNewFile(); // Open file and seek to the end of it. - file = new RandomAccessFile(tempFile, "rw"); - file.seek(downloaded); + file = new RandomAccessFile(tempFile, "rwd"); stream = connection.getInputStream(); + int lastDownloaded = 0; + long lastTime = System.currentTimeMillis(); while (true) { // Size buffer according to how much of the file is left to download. if (!shouldContinue) { @@ -158,14 +155,21 @@ public class FileDownloadTask extends Task implements PreviousResult, Prev file.write(buffer, 0, read); downloaded += read; - if (ppl != null) - ppl.setProgress(this, downloaded, size); + long now = System.currentTimeMillis(); + if (ppl != null && (now - lastTime) >= 1000) { + ppl.setProgress(this, downloaded, contentLength); + ppl.setStatus(this, (downloaded - lastDownloaded) / 1024 + "KB/s"); + lastDownloaded = downloaded; + lastTime = now; + } } closeFiles(); if (aborted) tempFile.delete(); - else + else { + if (filePath.exists()) filePath.delete(); tempFile.renameTo(filePath); + } if (ppl != null) ppl.onProgressProviderDone(this); return true; @@ -184,6 +188,7 @@ public class FileDownloadTask extends Task implements PreviousResult, Prev @Override public boolean abort() { + //for (Downloader d : downloaders) d.abort(); shouldContinue = false; aborted = true; return true; diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/NetException.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/NetException.java index d74bf1ce0..1e1a99df3 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/NetException.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/tasks/download/NetException.java @@ -22,6 +22,10 @@ package org.jackhuang.hellominecraft.tasks.download; */ public class NetException extends RuntimeException { + public NetException(Exception message) { + super(message); + } + public NetException(String message) { super(message); } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/UpdateChecker.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/UpdateChecker.java index a42494d63..593be318c 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/UpdateChecker.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/UpdateChecker.java @@ -19,7 +19,6 @@ package org.jackhuang.hellominecraft.utils; import java.util.Map; import org.jackhuang.hellominecraft.utils.system.MessageBox; import org.jackhuang.hellominecraft.C; -import org.jackhuang.hellominecraft.utils.functions.NonConsumer; import org.jackhuang.hellominecraft.HMCLog; /** @@ -30,16 +29,15 @@ public final class UpdateChecker extends Thread { public static boolean OUT_DATED = false; public VersionNumber base; + public String versionString; public String type; - public boolean continueUpdate; - public NonConsumer dl; - public Map download_link; + public Runnable dl; + public Map download_link = null; - public UpdateChecker(VersionNumber base, String type, boolean continueUpdate, NonConsumer dl) { + public UpdateChecker(VersionNumber base, String type, Runnable dl) { super("UpdateChecker"); this.base = base; this.type = type; - this.continueUpdate = continueUpdate; this.dl = dl; } @@ -48,25 +46,16 @@ public final class UpdateChecker extends Thread { @Override public void run() { - String version; try { - version = NetUtils.doGet("http://huangyuhui.duapp.com/info.php?type=" + type); + versionString = NetUtils.doGet("http://huangyuhui.duapp.com/info.php?type=" + type); } catch (Exception e) { HMCLog.warn("Failed to get update url.", e); return; } - value = VersionNumber.check(version); - if (!continueUpdate) - return; + value = VersionNumber.check(versionString); process(false); - if (OUT_DATED) { - try { - download_link = C.gson.fromJson(NetUtils.doGet("http://huangyuhui.duapp.com/update_link.php?type=" + type), Map.class); - } catch (Exception e) { - HMCLog.warn("Failed to get update link.", e); - } - dl.onDone(); - } + if (OUT_DATED) + dl.run(); } public void process(boolean showMessage) { @@ -74,14 +63,23 @@ public final class UpdateChecker extends Thread { HMCLog.warn("Failed to check update..."); if (showMessage) MessageBox.Show(C.i18n("update.failed")); - } else - if (VersionNumber.isOlder(base, value)) { - OUT_DATED = true; - } + } else if (VersionNumber.isOlder(base, value)) + OUT_DATED = true; } public VersionNumber getNewVersion() { return value; } + public synchronized void requestDownloadLink(Runnable finish) { + new Thread(() -> { + if (download_link == null) + try { + download_link = C.gson.fromJson(NetUtils.doGet("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(); + } } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/FileUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/FileUtils.java index ed436e374..da853e591 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/FileUtils.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/FileUtils.java @@ -344,11 +344,13 @@ public class FileUtils { return filename.substring(0, index); } - public static void writeQuietly(File file, CharSequence data) { + public static boolean writeQuietly(File file, CharSequence data) { try { write(file, data); + return true; } catch (IOException e) { HMCLog.warn("Failed to write data to file: " + file, e); + return false; } } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/JavaProcessMonitor.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/JavaProcessMonitor.java index 1a9b1189e..8a5312f78 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/JavaProcessMonitor.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/JavaProcessMonitor.java @@ -38,23 +38,24 @@ public class JavaProcessMonitor { this.p = p; } - void start() { + public void start() { Event event = (sender2, t) -> { processThreadStopped((ProcessThread) sender2, false); return true; }; - ProcessThread a = new ProcessThread(p, true, true); - a.stopEvent.register((sender3, p1) -> { + Event event2 = (sender3, p1) -> { if (p1.getExitCode() != 0 && p1.getStdErrLines().size() > 0 && StrUtils.containsOne(p1.getStdErrLines(), Arrays.asList("Could not create the Java Virtual Machine.", "Error occurred during initialization of VM", "A fatal exception has occurred. Program will exit."))) MessageBox.Show(C.i18n("launch.cannot_create_jvm")); processThreadStopped((ProcessThread) sender3, false); return true; - }); + }; + ProcessThread a = new ProcessThread(p, true, true); + a.stopEvent.register(event2); a.start(); al.add(a); a = new ProcessThread(p, false, true); - a.stopEvent.register(event); + a.stopEvent.register(event2); a.start(); al.add(a); a = new ProcessThread(p, false, false); diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/NonConsumer.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/ThreadExecutor.java similarity index 57% rename from HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/NonConsumer.java rename to HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/ThreadExecutor.java index 221823184..59edbd9f1 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/functions/NonConsumer.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/utils/system/ThreadExecutor.java @@ -14,13 +14,33 @@ * You should have received a copy of the GNU General Public License * along with this program. */ -package org.jackhuang.hellominecraft.utils.functions; +package org.jackhuang.hellominecraft.utils.system; + +import org.jackhuang.hellominecraft.utils.functions.Consumer; /** * * @author huangyuhui */ -public interface NonConsumer { +public class ThreadExecutor extends Thread { + + public final Consumer c; + public final Runnable r; + + public ThreadExecutor(Consumer c, Runnable r) { + super(); + this.c = c; + this.r = r; + } + + @Override + public void run() { + try { + r.run(); + c.accept(null); + } catch (Throwable t) { + c.accept(t); + } + } - void onDone(); } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java index 52ea57aa7..0ed6a6622 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/views/LogWindow.java @@ -17,7 +17,6 @@ package org.jackhuang.hellominecraft.views; import org.jackhuang.hellominecraft.C; -import org.jackhuang.hellominecraft.utils.functions.NonConsumer; import org.jackhuang.hellominecraft.utils.functions.NonFunction; import org.jackhuang.hellominecraft.utils.DoubleOutputStream; import org.jackhuang.hellominecraft.utils.LauncherPrintStream; @@ -33,7 +32,7 @@ public class LogWindow extends javax.swing.JFrame { boolean movingEnd; NonFunction listener; - NonConsumer terminateGameListener; + Runnable terminateGameListener; /** * Creates new form LogWindow @@ -226,7 +225,7 @@ public class LogWindow extends javax.swing.JFrame { private void btnTerminateGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTerminateGameActionPerformed if (terminateGameListener != null) - terminateGameListener.onDone(); + terminateGameListener.run(); }//GEN-LAST:event_btnTerminateGameActionPerformed private void btnGitHubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGitHubActionPerformed @@ -253,7 +252,7 @@ public class LogWindow extends javax.swing.JFrame { this.listener = exit; } - public void setTerminateGame(NonConsumer l) { + public void setTerminateGame(Runnable l) { this.terminateGameListener = l; } diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties index d77ec2c13..de2bf61dc 100644 --- a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N.properties @@ -23,6 +23,7 @@ launch.cannot_create_jvm=\u622a\u83b7\u5230\u65e0\u6cd5\u521b\u5efaJava\u865a\u6 launch.circular_dependency_versions=\u53d1\u73b0\u6e38\u620f\u7248\u672c\u5faa\u73af\u5f15\u7528\uff0c\u8bf7\u786e\u8ba4\u60a8\u7684\u5ba2\u6237\u7aef\u672a\u88ab\u4fee\u6539\u6216\u4fee\u6539\u5bfc\u81f4\u51fa\u73b0\u6b64\u95ee\u9898\u3002 launch.not_finished_downloading_libraries=\u672a\u5b8c\u6210\u6e38\u620f\u4f9d\u8d56\u5e93\u7684\u4e0b\u8f7d\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f launch.not_finished_decompressing_natives=\u672a\u80fd\u89e3\u538b\u6e38\u620f\u672c\u5730\u5e93\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f +launch.wrong_javadir=\u9519\u8bef\u7684Java\u8def\u5f84\uff0c\u5c06\u81ea\u52a8\u91cd\u7f6e\u4e3a\u9ed8\u8ba4Java\u8def\u5f84\u3002 install.no_version=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c install.no_version_if_intall=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c\uff0c\u662f\u5426\u81ea\u52a8\u5b89\u88c5\u9700\u8981\u7684MC\u7248\u672c\uff1f diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties index c39b5ec08..04a957a3c 100644 --- a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_en_US.properties @@ -23,6 +23,7 @@ launch.cannot_create_jvm=We find that it cannot create java virutal machine. The launch.circular_dependency_versions=Found circular dependency versions, please check if your client has been modified. launch.not_finished_downloading_libraries=Did not finish downloading libraries, continue launching game? launch.not_finished_decompressing_natives=Did not finish decompressing native libraries, continue launching game? +launch.wrong_javadir=Wrong Java Dir, will reset to default Java dir. install.no_version=The version is not found. install.no_version_if_intall=The needed version is not found, should install the version automatically? diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties index c23d7b560..3f4f6f487 100644 --- a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_CN.properties @@ -23,6 +23,7 @@ launch.cannot_create_jvm=\u622a\u83b7\u5230\u65e0\u6cd5\u521b\u5efaJava\u865a\u6 launch.circular_dependency_versions=\u53d1\u73b0\u6e38\u620f\u7248\u672c\u5faa\u73af\u5f15\u7528\uff0c\u8bf7\u786e\u8ba4\u60a8\u7684\u5ba2\u6237\u7aef\u672a\u88ab\u4fee\u6539\u6216\u4fee\u6539\u5bfc\u81f4\u51fa\u73b0\u6b64\u95ee\u9898\u3002 launch.not_finished_downloading_libraries=\u672a\u5b8c\u6210\u6e38\u620f\u4f9d\u8d56\u5e93\u7684\u4e0b\u8f7d\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f launch.not_finished_decompressing_natives=\u672a\u80fd\u89e3\u538b\u6e38\u620f\u672c\u5730\u5e93\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f +launch.wrong_javadir=\u9519\u8bef\u7684Java\u8def\u5f84\uff0c\u5c06\u81ea\u52a8\u91cd\u7f6e\u4e3a\u9ed8\u8ba4Java\u8def\u5f84\u3002 install.no_version=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c install.no_version_if_intall=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c\uff0c\u662f\u5426\u81ea\u52a8\u5b89\u88c5\u9700\u8981\u7684MC\u7248\u672c\uff1f diff --git a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties index 77af0af46..9691cb77e 100644 --- a/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties +++ b/HMCLAPI/src/main/resources/org/jackhuang/hellominecraft/launcher/I18N_zh_TW.properties @@ -23,6 +23,7 @@ launch.cannot_create_jvm=\u622a\u7372\u5230\u7121\u6cd5\u5275\u5efaJava\u865b\u6 launch.circular_dependency_versions=\u767c\u73fe\u904a\u6232\u7248\u672c\u5faa\u74b0\u5f15\u7528\uff0c\u8acb\u78ba\u8a8d\u60a8\u7684\u5ba2\u6236\u7aef\u672a\u88ab\u4fee\u6539\u6216\u4fee\u6539\u5c0e\u81f4\u51fa\u73fe\u6b64\u554f\u984c\u3002 launch.not_finished_downloading_libraries=\u672a\u5b8c\u6210\u904a\u6232\u4f9d\u8cf4\u5eab\u7684\u4e0b\u8f09\uff0c\u9084\u8981\u7e7c\u7e8c\u555f\u52d5\u904a\u6232\u55ce\uff1f launch.not_finished_decompressing_natives=\u672a\u80fd\u89e3\u58d3\u904a\u6232\u672c\u5730\u5eab\uff0c\u9084\u8981\u7e7c\u7e8c\u555f\u52d5\u904a\u6232\u55ce\uff1f +launch.wrong_javadir=\u932f\u8aa4\u7684Java\u8def\u5f91\uff0c\u5c07\u81ea\u52d5\u91cd\u7f6e\u70ba\u9ed8\u8a8dJava\u8def\u5f91\u3002 install.no_version=\u672a\u627e\u5230\u8981\u5b89\u88dd\u7684\u5c0d\u61c9MC\u7248\u672c install.no_version_if_intall=\u672a\u627e\u5230\u8981\u5b89\u88dd\u7684\u5c0d\u61c9MC\u7248\u672c\uff0c\u662f\u5426\u81ea\u52a8\u5b89\u88c5\u9700\u8981\u7684MC\u7248\u672c\uff1f