mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-08-03 19:36:53 -04:00
Reset the java directory when javadir is wrong.
This commit is contained in:
parent
9fc1470a63
commit
10bb60f998
@ -22,8 +22,6 @@ import java.lang.reflect.Method;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.jackhuang.hellominecraft.C;
|
import org.jackhuang.hellominecraft.C;
|
||||||
import org.jackhuang.hellominecraft.HMCLog;
|
import org.jackhuang.hellominecraft.HMCLog;
|
||||||
@ -91,6 +89,9 @@ public final class Launcher {
|
|||||||
SwingUtilities.invokeLater(() -> LogWindow.instance.setVisible(true));
|
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];
|
URL[] urls = new URL[len];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -103,12 +104,9 @@ public final class Launcher {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JdkVersion.isJava64Bit() && Platform.getPlatform() == Platform.BIT_64)
|
|
||||||
MessageBox.Show(C.i18n("advice.os64butjdk32"));
|
|
||||||
|
|
||||||
Method minecraftMain;
|
Method minecraftMain;
|
||||||
try {
|
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) {
|
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException t) {
|
||||||
MessageBox.Show(C.i18n("crash.main_class_not_found"));
|
MessageBox.Show(C.i18n("crash.main_class_not_found"));
|
||||||
println("Minecraft main class not found.");
|
println("Minecraft main class not found.");
|
||||||
|
@ -26,19 +26,22 @@ import java.net.Authenticator;
|
|||||||
import java.net.PasswordAuthentication;
|
import java.net.PasswordAuthentication;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.UnsupportedLookAndFeelException;
|
import javax.swing.UnsupportedLookAndFeelException;
|
||||||
import org.jackhuang.hellominecraft.C;
|
import org.jackhuang.hellominecraft.C;
|
||||||
import org.jackhuang.hellominecraft.utils.functions.NonConsumer;
|
|
||||||
import org.jackhuang.hellominecraft.HMCLog;
|
import org.jackhuang.hellominecraft.HMCLog;
|
||||||
import org.jackhuang.hellominecraft.launcher.launch.GameLauncher;
|
import org.jackhuang.hellominecraft.launcher.launch.GameLauncher;
|
||||||
import org.jackhuang.hellominecraft.launcher.utils.CrashReporter;
|
import org.jackhuang.hellominecraft.launcher.utils.CrashReporter;
|
||||||
@ -47,17 +50,23 @@ import org.jackhuang.hellominecraft.logging.appender.ConsoleAppender;
|
|||||||
import org.jackhuang.hellominecraft.logging.layout.DefaultLayout;
|
import org.jackhuang.hellominecraft.logging.layout.DefaultLayout;
|
||||||
import org.jackhuang.hellominecraft.views.LogWindow;
|
import org.jackhuang.hellominecraft.views.LogWindow;
|
||||||
import org.jackhuang.hellominecraft.launcher.settings.Settings;
|
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.launcher.views.MainFrame;
|
||||||
import org.jackhuang.hellominecraft.lookandfeel.HelloMinecraftLookAndFeel;
|
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.system.MessageBox;
|
||||||
import org.jackhuang.hellominecraft.utils.StrUtils;
|
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 org.jackhuang.hellominecraft.utils.system.OS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class Main implements NonConsumer {
|
public final class Main implements Runnable {
|
||||||
|
|
||||||
private static final X509TrustManager xtm = new X509TrustManager() {
|
private static final X509TrustManager xtm = new X509TrustManager() {
|
||||||
@Override
|
@Override
|
||||||
@ -91,7 +100,7 @@ public final class Main implements NonConsumer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String launcherName = "Hello Minecraft! Launcher";
|
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;
|
public static int minimumLauncherVersion = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,6 +125,31 @@ public final class Main implements NonConsumer {
|
|||||||
|
|
||||||
public static void main(String[] args) {
|
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) {
|
||||||
|
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));
|
Thread.setDefaultUncaughtExceptionHandler(new CrashReporter(true));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -158,37 +192,48 @@ public final class Main implements NonConsumer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDone() {
|
public void run() {
|
||||||
GameLauncher.PROCESS_MANAGER.stopAllProcesses();
|
GameLauncher.PROCESS_MANAGER.stopAllProcesses();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void update() {
|
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"
|
Settings.UPDATE_CHECKER.requestDownloadLink(() -> {
|
||||||
+ C.i18n("update.should_open_link"),
|
SwingUtilities.invokeLater(() -> {
|
||||||
MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) {
|
Map<String, String> map = Settings.UPDATE_CHECKER.download_link;
|
||||||
Map<String, String> map = Settings.UPDATE_CHECKER.download_link;
|
if (map != null && map.containsKey("pack"))
|
||||||
String url = C.URL_PUBLISH;
|
try {
|
||||||
if (map != null)
|
if (TaskWindow.getInstance().addTask(new Upgrader(map.get("pack"), Settings.UPDATE_CHECKER.versionString)).start()) {
|
||||||
if (map.containsKey(OS.os().checked_name))
|
new ProcessBuilder(new String[]{IOUtils.getJavaDir(), "-jar", Upgrader.getSelf(Settings.UPDATE_CHECKER.versionString).getAbsolutePath()}).directory(new File(".")).start();
|
||||||
url = map.get(OS.os().checked_name);
|
System.exit(0);
|
||||||
else if (map.containsKey(OS.UNKOWN.checked_name))
|
}
|
||||||
url = map.get(OS.UNKOWN.checked_name);
|
} catch (IOException ex) {
|
||||||
if (url == null) url = C.URL_PUBLISH;
|
HMCLog.warn("Failed to create upgrader", ex);
|
||||||
try {
|
}
|
||||||
java.awt.Desktop.getDesktop().browse(new URI(url));
|
if (MessageBox.Show(C.i18n("update.newest_version") + Settings.UPDATE_CHECKER.getNewVersion().firstVer + "." + Settings.UPDATE_CHECKER.getNewVersion().secondVer + "." + Settings.UPDATE_CHECKER.getNewVersion().thirdVer + "\n"
|
||||||
} catch (URISyntaxException | IOException e) {
|
+ C.i18n("update.should_open_link"),
|
||||||
HMCLog.warn("Failed to browse uri: " + url, e);
|
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();
|
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||||
cb.setContents(new StringSelection(url), null);
|
cb.setContents(new StringSelection(url), null);
|
||||||
MessageBox.Show(C.i18n("update.no_browser"));
|
MessageBox.Show(C.i18n("update.no_browser"));
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
Settings.getInstance().setCheckUpdate(false);
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void invokeUpdate() {
|
public static void invokeUpdate() {
|
||||||
if (Settings.getInstance().isCheckUpdate()) update();
|
|
||||||
MainFrame.instance.invokeUpdate();
|
MainFrame.instance.invokeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,11 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
|
|||||||
HMCLog.log("On making head command.");
|
HMCLog.log("On making head command.");
|
||||||
|
|
||||||
String str = v.getJavaDir();
|
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);
|
JdkVersion jv = new JdkVersion(str);
|
||||||
if (Settings.getInstance().getJava().contains(jv))
|
if (Settings.getInstance().getJava().contains(jv))
|
||||||
jv = Settings.getInstance().getJava().get(Settings.getInstance().getJava().indexOf(jv));
|
jv = Settings.getInstance().getJava().get(Settings.getInstance().getJava().indexOf(jv));
|
||||||
|
@ -133,6 +133,7 @@ public class GameLauncher {
|
|||||||
HMCLog.warn("Failed to invoke precalled command", ex);
|
HMCLog.warn("Failed to invoke precalled command", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HMCLog.log("Starting process");
|
||||||
ProcessBuilder builder = new ProcessBuilder(str);
|
ProcessBuilder builder = new ProcessBuilder(str);
|
||||||
builder.directory(provider.getRunDirectory(get.getSelectedMinecraftVersion().id))
|
builder.directory(provider.getRunDirectory(get.getSelectedMinecraftVersion().id))
|
||||||
.environment().put("APPDATA", get.getCanonicalGameDirFile().getPath());
|
.environment().put("APPDATA", get.getCanonicalGameDirFile().getPath());
|
||||||
|
@ -49,6 +49,7 @@ public class LaunchFinisher implements Event<List<String>> {
|
|||||||
System.exit(0);
|
System.exit(0);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
jpm.start();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
obj.launch(str);
|
obj.launch(str);
|
||||||
|
@ -20,10 +20,7 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
@ -31,8 +28,7 @@ import java.util.jar.JarOutputStream;
|
|||||||
import java.util.jar.Pack200;
|
import java.util.jar.Pack200;
|
||||||
import org.jackhuang.hellominecraft.C;
|
import org.jackhuang.hellominecraft.C;
|
||||||
import org.jackhuang.hellominecraft.HMCLog;
|
import org.jackhuang.hellominecraft.HMCLog;
|
||||||
import org.jackhuang.hellominecraft.tasks.Task;
|
import org.jackhuang.hellominecraft.tasks.download.FileDownloadTask;
|
||||||
import org.jackhuang.hellominecraft.tasks.download.NetException;
|
|
||||||
import org.jackhuang.hellominecraft.utils.system.IOUtils;
|
import org.jackhuang.hellominecraft.utils.system.IOUtils;
|
||||||
import org.tukaani.xz.XZInputStream;
|
import org.tukaani.xz.XZInputStream;
|
||||||
|
|
||||||
@ -40,13 +36,12 @@ import org.tukaani.xz.XZInputStream;
|
|||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public class LibraryDownloadTask extends Task {
|
public class LibraryDownloadTask extends FileDownloadTask {
|
||||||
|
|
||||||
private static final int MAX_BUFFER_SIZE = 2048;
|
|
||||||
|
|
||||||
GameLauncher.DownloadLibraryJob job;
|
GameLauncher.DownloadLibraryJob job;
|
||||||
|
|
||||||
public LibraryDownloadTask(GameLauncher.DownloadLibraryJob job) {
|
public LibraryDownloadTask(GameLauncher.DownloadLibraryJob job) {
|
||||||
|
super();
|
||||||
this.job = job;
|
this.job = job;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,94 +72,10 @@ public class LibraryDownloadTask extends Task {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream stream;
|
|
||||||
RandomAccessFile file;
|
|
||||||
boolean shouldContinue = true;
|
|
||||||
int size = -1;
|
|
||||||
|
|
||||||
boolean download(URL url, File filePath) {
|
boolean download(URL url, File filePath) {
|
||||||
HMCLog.log("Downloading: " + url + " to " + filePath);
|
this.url = url;
|
||||||
size = -1;
|
this.filePath = filePath;
|
||||||
int downloaded = 0;
|
return super.executeTask();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unpackLibrary(File output, File input)
|
public static void unpackLibrary(File output, File input)
|
||||||
@ -211,33 +122,6 @@ public class LibraryDownloadTask extends Task {
|
|||||||
temp.delete();
|
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
|
@Override
|
||||||
public String getInfo() {
|
public String getInfo() {
|
||||||
return C.i18n("download") + ": " + job.name;
|
return C.i18n("download") + ": " + job.name;
|
||||||
|
@ -125,15 +125,6 @@ public final class Config {
|
|||||||
return configurations;
|
return configurations;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCheckUpdate() {
|
|
||||||
return checkUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCheckUpdate(boolean checkUpdate) {
|
|
||||||
this.checkUpdate = checkUpdate;
|
|
||||||
Settings.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map getYggdrasilConfig() {
|
public Map getYggdrasilConfig() {
|
||||||
return yggdrasil;
|
return yggdrasil;
|
||||||
}
|
}
|
||||||
@ -149,8 +140,6 @@ public final class Config {
|
|||||||
private int downloadtype;
|
private int downloadtype;
|
||||||
@SerializedName("configurations")
|
@SerializedName("configurations")
|
||||||
private TreeMap<String, Profile> configurations;
|
private TreeMap<String, Profile> configurations;
|
||||||
@SerializedName("checkUpdate")
|
|
||||||
private boolean checkUpdate;
|
|
||||||
@SerializedName("yggdrasil")
|
@SerializedName("yggdrasil")
|
||||||
private Map yggdrasil;
|
private Map yggdrasil;
|
||||||
|
|
||||||
@ -158,7 +147,6 @@ public final class Config {
|
|||||||
clientToken = UUID.randomUUID().toString();
|
clientToken = UUID.randomUUID().toString();
|
||||||
username = "";
|
username = "";
|
||||||
logintype = downloadtype = 0;
|
logintype = downloadtype = 0;
|
||||||
checkUpdate = true;
|
|
||||||
configurations = new TreeMap<>();
|
configurations = new TreeMap<>();
|
||||||
Profile profile = new Profile();
|
Profile profile = new Profile();
|
||||||
configurations.put(profile.getName(), profile);
|
configurations.put(profile.getName(), profile);
|
||||||
|
@ -165,9 +165,13 @@ public final class Profile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setJava(Java java) {
|
public void setJava(Java java) {
|
||||||
int idx = Settings.JAVA.indexOf(java);
|
if (java == null)
|
||||||
if (idx == -1) return;
|
this.java = Settings.JAVA.get(0).getName();
|
||||||
this.java = java.getName();
|
else {
|
||||||
|
int idx = Settings.JAVA.indexOf(java);
|
||||||
|
if (idx == -1) return;
|
||||||
|
this.java = java.getName();
|
||||||
|
}
|
||||||
Settings.save();
|
Settings.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public final class Settings {
|
|||||||
e.checkFormat();
|
e.checkFormat();
|
||||||
|
|
||||||
UPDATE_CHECKER = new UpdateChecker(new VersionNumber(Main.firstVer, Main.secondVer, Main.thirdVer),
|
UPDATE_CHECKER = new UpdateChecker(new VersionNumber(Main.firstVer, Main.secondVer, Main.thirdVer),
|
||||||
"hmcl", settings.isCheckUpdate(), Main::invokeUpdate);
|
"hmcl", Main::invokeUpdate);
|
||||||
|
|
||||||
List<Java> temp = new ArrayList<>();
|
List<Java> temp = new ArrayList<>();
|
||||||
temp.add(new Java("Default", System.getProperty("java.home")));
|
temp.add(new Java("Default", System.getProperty("java.home")));
|
||||||
|
@ -20,15 +20,8 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
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.ZipEntry;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
import org.jackhuang.hellominecraft.C;
|
|
||||||
import org.jackhuang.hellominecraft.HMCLog;
|
import org.jackhuang.hellominecraft.HMCLog;
|
||||||
import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex;
|
import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsIndex;
|
||||||
import org.jackhuang.hellominecraft.launcher.utils.assets.AssetsObject;
|
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.utils.system.IOUtils;
|
||||||
import org.jackhuang.hellominecraft.version.MinecraftVersionRequest;
|
import org.jackhuang.hellominecraft.version.MinecraftVersionRequest;
|
||||||
import org.jackhuang.hellominecraft.utils.NetUtils;
|
import org.jackhuang.hellominecraft.utils.NetUtils;
|
||||||
import org.jackhuang.hellominecraft.utils.Pair;
|
|
||||||
import org.jackhuang.hellominecraft.utils.system.OS;
|
import org.jackhuang.hellominecraft.utils.system.OS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -188,30 +180,33 @@ public final class MCUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getLocation() {
|
public static File getWorkingDirectory(String baseName) {
|
||||||
String baseName = "minecraft";
|
String userhome = System.getProperty("user.home", ".");
|
||||||
String str1 = System.getProperty("user.home", ".");
|
|
||||||
File file;
|
File file;
|
||||||
switch (OS.os()) {
|
switch (OS.os()) {
|
||||||
case LINUX:
|
case LINUX:
|
||||||
file = new File(str1, '.' + (String) baseName + '/');
|
file = new File(userhome, '.' + baseName + '/');
|
||||||
break;
|
break;
|
||||||
case WINDOWS:
|
case WINDOWS:
|
||||||
String str2;
|
String appdata = System.getenv("APPDATA");
|
||||||
if ((str2 = System.getenv("APPDATA")) != null)
|
if (appdata != null)
|
||||||
file = new File(str2, "." + baseName + '/');
|
file = new File(appdata, "." + baseName + '/');
|
||||||
else
|
else
|
||||||
file = new File(str1, '.' + baseName + '/');
|
file = new File(userhome, '.' + baseName + '/');
|
||||||
break;
|
break;
|
||||||
case OSX:
|
case OSX:
|
||||||
file = new File(str1, "Library/Application Support/" + baseName);
|
file = new File(userhome, "Library/Application Support/" + baseName);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
file = new File(str1, baseName + '/');
|
file = new File(userhome, baseName + '/');
|
||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static File getLocation() {
|
||||||
|
return getWorkingDirectory("minecraft");
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean is16Folder(String path) {
|
public static boolean is16Folder(String path) {
|
||||||
path = IOUtils.addSeparator(path);
|
path = IOUtils.addSeparator(path);
|
||||||
return new File(path, "versions").exists();
|
return new File(path, "versions").exists();
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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 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<Task> getDependTasks() {
|
||||||
|
return Arrays.asList(new FileDownloadTask(downloadLink, tempFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean executeTask() {
|
||||||
|
HashMap<String, String> 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";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -372,7 +372,6 @@ public final class MainFrame extends DraggableFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void invokeUpdate() {
|
public void invokeUpdate() {
|
||||||
if (!isVisible()) return;
|
|
||||||
defaultTitle = defaultTitle + C.i18n("update.found");
|
defaultTitle = defaultTitle + C.i18n("update.found");
|
||||||
if (!isShowedMessage) {
|
if (!isShowedMessage) {
|
||||||
windowTitle.setText(defaultTitle);
|
windowTitle.setText(defaultTitle);
|
||||||
|
@ -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)
|
.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.createSequentialGroup()
|
||||||
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(jLabel10)
|
.addComponent(jLabel10, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||||
.addComponent(jLabel1))
|
.addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
@ -51,7 +51,7 @@ public final class C {
|
|||||||
try {
|
try {
|
||||||
return String.format(C.I18N.getString(a), format);
|
return String.format(C.I18N.getString(a), format);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
HMCLog.warn("Failed to read localization lang: " + a, e);
|
HMCLog.warn("Failed to read localization key: " + a, e);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import java.util.Collections;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.jackhuang.hellominecraft.utils.functions.NonConsumer;
|
|
||||||
import org.jackhuang.hellominecraft.HMCLog;
|
import org.jackhuang.hellominecraft.HMCLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +31,7 @@ import org.jackhuang.hellominecraft.HMCLog;
|
|||||||
public class TaskList extends Thread {
|
public class TaskList extends Thread {
|
||||||
|
|
||||||
List<Task> taskQueue = Collections.synchronizedList(new ArrayList());
|
List<Task> taskQueue = Collections.synchronizedList(new ArrayList());
|
||||||
ArrayList<NonConsumer> allDone = new ArrayList();
|
ArrayList<Runnable> allDone = new ArrayList();
|
||||||
ArrayList<DoingDoneListener<Task>> taskListener = new ArrayList();
|
ArrayList<DoingDoneListener<Task>> taskListener = new ArrayList();
|
||||||
|
|
||||||
int totTask;
|
int totTask;
|
||||||
@ -46,7 +45,7 @@ public class TaskList extends Thread {
|
|||||||
taskQueue.clear();
|
taskQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAllDoneListener(NonConsumer l) {
|
public void addAllDoneListener(Runnable l) {
|
||||||
allDone.add(l);
|
allDone.add(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,8 +99,7 @@ public class TaskList extends Thread {
|
|||||||
try {
|
try {
|
||||||
if (this.isInterrupted()) return;
|
if (this.isInterrupted()) return;
|
||||||
Thread.sleep(1);
|
Thread.sleep(1);
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ignore) {
|
||||||
HMCLog.warn("Failed to sleep task thread", ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -148,8 +146,8 @@ public class TaskList extends Thread {
|
|||||||
for (Task taskQueue1 : taskQueue)
|
for (Task taskQueue1 : taskQueue)
|
||||||
executeTask(taskQueue1);
|
executeTask(taskQueue1);
|
||||||
if (shouldContinue)
|
if (shouldContinue)
|
||||||
for (NonConsumer d : allDone)
|
for (Runnable d : allDone)
|
||||||
d.onDone();
|
d.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
|
@ -19,7 +19,6 @@ package org.jackhuang.hellominecraft.tasks;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.jackhuang.hellominecraft.C;
|
import org.jackhuang.hellominecraft.C;
|
||||||
import org.jackhuang.hellominecraft.utils.functions.NonConsumer;
|
|
||||||
import org.jackhuang.hellominecraft.HMCLog;
|
import org.jackhuang.hellominecraft.HMCLog;
|
||||||
import org.jackhuang.hellominecraft.utils.system.MessageBox;
|
import org.jackhuang.hellominecraft.utils.system.MessageBox;
|
||||||
import org.jackhuang.hellominecraft.utils.StrUtils;
|
import org.jackhuang.hellominecraft.utils.StrUtils;
|
||||||
@ -30,7 +29,7 @@ import org.jackhuang.hellominecraft.utils.SwingUtils;
|
|||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public class TaskWindow extends javax.swing.JDialog
|
public class TaskWindow extends javax.swing.JDialog
|
||||||
implements ProgressProviderListener, NonConsumer, DoingDoneListener<Task> {
|
implements ProgressProviderListener, Runnable, DoingDoneListener<Task> {
|
||||||
|
|
||||||
private static final TaskWindow instance = new TaskWindow();
|
private static final TaskWindow instance = new TaskWindow();
|
||||||
|
|
||||||
@ -202,7 +201,7 @@ public class TaskWindow extends javax.swing.JDialog
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDone() {
|
public void run() {
|
||||||
suc = true;
|
suc = true;
|
||||||
this.dispose();
|
this.dispose();
|
||||||
HMCLog.log("Tasks are finished.");
|
HMCLog.log("Tasks are finished.");
|
||||||
@ -259,7 +258,9 @@ public class TaskWindow extends javax.swing.JDialog
|
|||||||
@Override
|
@Override
|
||||||
public void setStatus(Task task, String sta) {
|
public void setStatus(Task task, String sta) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,14 @@ import org.jackhuang.hellominecraft.utils.system.IOUtils;
|
|||||||
public class FileDownloadTask extends Task implements PreviousResult<File>, PreviousResultRegistrar<String> {
|
public class FileDownloadTask extends Task implements PreviousResult<File>, PreviousResultRegistrar<String> {
|
||||||
|
|
||||||
// Max size of download buffer.
|
// 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
|
protected URL url; // download URL
|
||||||
private int size; // size of download in bytes
|
protected int downloaded = 0; // number of bytes downloaded
|
||||||
private int downloaded; // number of bytes downloaded
|
protected File filePath;
|
||||||
private final File filePath;
|
|
||||||
|
public FileDownloadTask() {
|
||||||
|
}
|
||||||
|
|
||||||
public FileDownloadTask(File filePath) {
|
public FileDownloadTask(File filePath) {
|
||||||
this((URL) null, filePath);
|
this((URL) null, filePath);
|
||||||
@ -56,8 +58,6 @@ public class FileDownloadTask extends Task implements PreviousResult<File>, Prev
|
|||||||
// Constructor for Download.
|
// Constructor for Download.
|
||||||
public FileDownloadTask(URL url, File filePath) {
|
public FileDownloadTask(URL url, File filePath) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
size = -1;
|
|
||||||
downloaded = 0;
|
|
||||||
this.filePath = filePath;
|
this.filePath = filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,10 +124,6 @@ public class FileDownloadTask extends Task implements PreviousResult<File>, Prev
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the size for this download if it hasn't been already set.
|
|
||||||
if (size == -1)
|
|
||||||
size = contentLength;
|
|
||||||
|
|
||||||
filePath.getParentFile().mkdirs();
|
filePath.getParentFile().mkdirs();
|
||||||
|
|
||||||
File tempFile = new File(filePath.getAbsolutePath() + ".hmd");
|
File tempFile = new File(filePath.getAbsolutePath() + ".hmd");
|
||||||
@ -135,10 +131,11 @@ public class FileDownloadTask extends Task implements PreviousResult<File>, Prev
|
|||||||
tempFile.createNewFile();
|
tempFile.createNewFile();
|
||||||
|
|
||||||
// Open file and seek to the end of it.
|
// Open file and seek to the end of it.
|
||||||
file = new RandomAccessFile(tempFile, "rw");
|
file = new RandomAccessFile(tempFile, "rwd");
|
||||||
file.seek(downloaded);
|
|
||||||
|
|
||||||
stream = connection.getInputStream();
|
stream = connection.getInputStream();
|
||||||
|
int lastDownloaded = 0;
|
||||||
|
long lastTime = System.currentTimeMillis();
|
||||||
while (true) {
|
while (true) {
|
||||||
// Size buffer according to how much of the file is left to download.
|
// Size buffer according to how much of the file is left to download.
|
||||||
if (!shouldContinue) {
|
if (!shouldContinue) {
|
||||||
@ -158,14 +155,21 @@ public class FileDownloadTask extends Task implements PreviousResult<File>, Prev
|
|||||||
file.write(buffer, 0, read);
|
file.write(buffer, 0, read);
|
||||||
downloaded += read;
|
downloaded += read;
|
||||||
|
|
||||||
if (ppl != null)
|
long now = System.currentTimeMillis();
|
||||||
ppl.setProgress(this, downloaded, size);
|
if (ppl != null && (now - lastTime) >= 1000) {
|
||||||
|
ppl.setProgress(this, downloaded, contentLength);
|
||||||
|
ppl.setStatus(this, (downloaded - lastDownloaded) / 1024 + "KB/s");
|
||||||
|
lastDownloaded = downloaded;
|
||||||
|
lastTime = now;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
closeFiles();
|
closeFiles();
|
||||||
if (aborted)
|
if (aborted)
|
||||||
tempFile.delete();
|
tempFile.delete();
|
||||||
else
|
else {
|
||||||
|
if (filePath.exists()) filePath.delete();
|
||||||
tempFile.renameTo(filePath);
|
tempFile.renameTo(filePath);
|
||||||
|
}
|
||||||
if (ppl != null)
|
if (ppl != null)
|
||||||
ppl.onProgressProviderDone(this);
|
ppl.onProgressProviderDone(this);
|
||||||
return true;
|
return true;
|
||||||
@ -184,6 +188,7 @@ public class FileDownloadTask extends Task implements PreviousResult<File>, Prev
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean abort() {
|
public boolean abort() {
|
||||||
|
//for (Downloader d : downloaders) d.abort();
|
||||||
shouldContinue = false;
|
shouldContinue = false;
|
||||||
aborted = true;
|
aborted = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -22,6 +22,10 @@ package org.jackhuang.hellominecraft.tasks.download;
|
|||||||
*/
|
*/
|
||||||
public class NetException extends RuntimeException {
|
public class NetException extends RuntimeException {
|
||||||
|
|
||||||
|
public NetException(Exception message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
public NetException(String message) {
|
public NetException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ package org.jackhuang.hellominecraft.utils;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.jackhuang.hellominecraft.utils.system.MessageBox;
|
import org.jackhuang.hellominecraft.utils.system.MessageBox;
|
||||||
import org.jackhuang.hellominecraft.C;
|
import org.jackhuang.hellominecraft.C;
|
||||||
import org.jackhuang.hellominecraft.utils.functions.NonConsumer;
|
|
||||||
import org.jackhuang.hellominecraft.HMCLog;
|
import org.jackhuang.hellominecraft.HMCLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,16 +29,15 @@ public final class UpdateChecker extends Thread {
|
|||||||
|
|
||||||
public static boolean OUT_DATED = false;
|
public static boolean OUT_DATED = false;
|
||||||
public VersionNumber base;
|
public VersionNumber base;
|
||||||
|
public String versionString;
|
||||||
public String type;
|
public String type;
|
||||||
public boolean continueUpdate;
|
public Runnable dl;
|
||||||
public NonConsumer dl;
|
public Map<String, String> download_link = null;
|
||||||
public Map<String, String> download_link;
|
|
||||||
|
|
||||||
public UpdateChecker(VersionNumber base, String type, boolean continueUpdate, NonConsumer dl) {
|
public UpdateChecker(VersionNumber base, String type, Runnable dl) {
|
||||||
super("UpdateChecker");
|
super("UpdateChecker");
|
||||||
this.base = base;
|
this.base = base;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.continueUpdate = continueUpdate;
|
|
||||||
this.dl = dl;
|
this.dl = dl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,25 +46,16 @@ public final class UpdateChecker extends Thread {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
String version;
|
|
||||||
try {
|
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) {
|
} catch (Exception e) {
|
||||||
HMCLog.warn("Failed to get update url.", e);
|
HMCLog.warn("Failed to get update url.", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
value = VersionNumber.check(version);
|
value = VersionNumber.check(versionString);
|
||||||
if (!continueUpdate)
|
|
||||||
return;
|
|
||||||
process(false);
|
process(false);
|
||||||
if (OUT_DATED) {
|
if (OUT_DATED)
|
||||||
try {
|
dl.run();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(boolean showMessage) {
|
public void process(boolean showMessage) {
|
||||||
@ -74,14 +63,23 @@ public final class UpdateChecker extends Thread {
|
|||||||
HMCLog.warn("Failed to check update...");
|
HMCLog.warn("Failed to check update...");
|
||||||
if (showMessage)
|
if (showMessage)
|
||||||
MessageBox.Show(C.i18n("update.failed"));
|
MessageBox.Show(C.i18n("update.failed"));
|
||||||
} else
|
} else if (VersionNumber.isOlder(base, value))
|
||||||
if (VersionNumber.isOlder(base, value)) {
|
OUT_DATED = true;
|
||||||
OUT_DATED = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public VersionNumber getNewVersion() {
|
public VersionNumber getNewVersion() {
|
||||||
return value;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,11 +344,13 @@ public class FileUtils {
|
|||||||
return filename.substring(0, index);
|
return filename.substring(0, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeQuietly(File file, CharSequence data) {
|
public static boolean writeQuietly(File file, CharSequence data) {
|
||||||
try {
|
try {
|
||||||
write(file, data);
|
write(file, data);
|
||||||
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
HMCLog.warn("Failed to write data to file: " + file, e);
|
HMCLog.warn("Failed to write data to file: " + file, e);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,23 +38,24 @@ public class JavaProcessMonitor {
|
|||||||
this.p = p;
|
this.p = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start() {
|
public void start() {
|
||||||
Event<JavaProcess> event = (sender2, t) -> {
|
Event<JavaProcess> event = (sender2, t) -> {
|
||||||
processThreadStopped((ProcessThread) sender2, false);
|
processThreadStopped((ProcessThread) sender2, false);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
ProcessThread a = new ProcessThread(p, true, true);
|
Event<JavaProcess> event2 = (sender3, p1) -> {
|
||||||
a.stopEvent.register((sender3, p1) -> {
|
|
||||||
if (p1.getExitCode() != 0 && p1.getStdErrLines().size() > 0 && StrUtils.containsOne(p1.getStdErrLines(), Arrays.asList("Could not create the Java Virtual Machine.",
|
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",
|
"Error occurred during initialization of VM",
|
||||||
"A fatal exception has occurred. Program will exit."))) MessageBox.Show(C.i18n("launch.cannot_create_jvm"));
|
"A fatal exception has occurred. Program will exit."))) MessageBox.Show(C.i18n("launch.cannot_create_jvm"));
|
||||||
processThreadStopped((ProcessThread) sender3, false);
|
processThreadStopped((ProcessThread) sender3, false);
|
||||||
return true;
|
return true;
|
||||||
});
|
};
|
||||||
|
ProcessThread a = new ProcessThread(p, true, true);
|
||||||
|
a.stopEvent.register(event2);
|
||||||
a.start();
|
a.start();
|
||||||
al.add(a);
|
al.add(a);
|
||||||
a = new ProcessThread(p, false, true);
|
a = new ProcessThread(p, false, true);
|
||||||
a.stopEvent.register(event);
|
a.stopEvent.register(event2);
|
||||||
a.start();
|
a.start();
|
||||||
al.add(a);
|
al.add(a);
|
||||||
a = new ProcessThread(p, false, false);
|
a = new ProcessThread(p, false, false);
|
||||||
|
@ -14,13 +14,33 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program.
|
* 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
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public interface NonConsumer {
|
public class ThreadExecutor extends Thread {
|
||||||
|
|
||||||
|
public final Consumer<Throwable> c;
|
||||||
|
public final Runnable r;
|
||||||
|
|
||||||
|
public ThreadExecutor(Consumer<Throwable> 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();
|
|
||||||
}
|
}
|
@ -17,7 +17,6 @@
|
|||||||
package org.jackhuang.hellominecraft.views;
|
package org.jackhuang.hellominecraft.views;
|
||||||
|
|
||||||
import org.jackhuang.hellominecraft.C;
|
import org.jackhuang.hellominecraft.C;
|
||||||
import org.jackhuang.hellominecraft.utils.functions.NonConsumer;
|
|
||||||
import org.jackhuang.hellominecraft.utils.functions.NonFunction;
|
import org.jackhuang.hellominecraft.utils.functions.NonFunction;
|
||||||
import org.jackhuang.hellominecraft.utils.DoubleOutputStream;
|
import org.jackhuang.hellominecraft.utils.DoubleOutputStream;
|
||||||
import org.jackhuang.hellominecraft.utils.LauncherPrintStream;
|
import org.jackhuang.hellominecraft.utils.LauncherPrintStream;
|
||||||
@ -33,7 +32,7 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
|
|
||||||
boolean movingEnd;
|
boolean movingEnd;
|
||||||
NonFunction<Boolean> listener;
|
NonFunction<Boolean> listener;
|
||||||
NonConsumer terminateGameListener;
|
Runnable terminateGameListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form LogWindow
|
* 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
|
private void btnTerminateGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTerminateGameActionPerformed
|
||||||
if (terminateGameListener != null)
|
if (terminateGameListener != null)
|
||||||
terminateGameListener.onDone();
|
terminateGameListener.run();
|
||||||
}//GEN-LAST:event_btnTerminateGameActionPerformed
|
}//GEN-LAST:event_btnTerminateGameActionPerformed
|
||||||
|
|
||||||
private void btnGitHubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGitHubActionPerformed
|
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;
|
this.listener = exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTerminateGame(NonConsumer l) {
|
public void setTerminateGame(Runnable l) {
|
||||||
this.terminateGameListener = l;
|
this.terminateGameListener = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.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_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.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=\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
|
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
|
||||||
|
@ -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.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_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.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=The version is not found.
|
||||||
install.no_version_if_intall=The needed version is not found, should install the version automatically?
|
install.no_version_if_intall=The needed version is not found, should install the version automatically?
|
||||||
|
@ -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.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_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.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=\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
|
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
|
||||||
|
@ -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.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_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.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=\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
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user