diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 74911b03b..17855e8b7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -67,6 +67,8 @@ public final class Launcher extends Application { Thread.setDefaultUncaughtExceptionHandler(CRASH_REPORTER); try { + Logging.start(); + // NetworkUtils.setUserAgentSupplier(() -> "Hello Minecraft! Launcher"); Constants.UI_THREAD_SCHEDULER = Constants.JAVAFX_UI_THREAD_SCHEDULER; UPGRADER.parseArguments(VersionNumber.asVersion(VERSION), Arrays.asList(args)); @@ -134,7 +136,7 @@ public final class Launcher extends Application { public static final File MINECRAFT_DIRECTORY = getWorkingDirectory("minecraft"); public static final File HMCL_DIRECTORY = getWorkingDirectory("hmcl"); - public static final String VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@"; + public static final String VERSION = "2.9"; public static final String NAME = "HMCL"; public static final String TITLE = NAME + " " + VERSION; public static final ResourceBundle RESOURCE_BUNDLE = Settings.INSTANCE.getLocale().getResourceBundle(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java index 7642e2153..d59c831a2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Main.java @@ -26,9 +26,8 @@ public final class Main { public static void main(String[] args) { String currentDirectory = new File("").getAbsolutePath(); - Logging.LOG.info("Current directory: " + currentDirectory); if (currentDirectory.contains("!")) { - Logging.LOG.severe("Exclamation mark(!) is not allowed in the path where HMCL is in. Forcibly exit."); + System.err.println("Exclamation mark(!) is not allowed in the path where HMCL is in. Forcibly exit."); // No Chinese translation because both Swing and JavaFX cannot render Chinese character properly when exclamation mark exists in the path. String message = "Exclamation mark(!) is not allowed in the path where HMCL is in.\nThe path is " + currentDirectory; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index e09ed5c0e..d62349ce6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -23,6 +23,7 @@ import javafx.animation.Animation; import javafx.animation.Interpolator; import javafx.animation.KeyFrame; import javafx.animation.Timeline; +import javafx.application.Platform; import javafx.beans.property.Property; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; @@ -48,7 +49,10 @@ import java.io.File; import java.io.IOException; import java.net.URI; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import java.util.function.Supplier; import java.util.logging.Level; import static org.jackhuang.hmcl.util.ReflectionHelper.call; @@ -368,6 +372,31 @@ public final class FXUtils { }); } + public static T runInUIThread(Supplier supplier) { + if (javafx.application.Platform.isFxApplicationThread()) { + return supplier.get(); + } else { + CountDownLatch doneLatch = new CountDownLatch(1); + AtomicReference reference = new AtomicReference<>(); + Platform.runLater(() -> { + try { + reference.set(supplier.get()); + } finally { + doneLatch.countDown(); + } + + }); + + try { + doneLatch.await(); + } catch (InterruptedException var3) { + Thread.currentThread().interrupt(); + } + + return reference.get(); + } + } + public static final Image DEFAULT_ICON = new Image("/assets/img/icon.png"); public static final Interpolator SINE = new Interpolator() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java index 4d10f1a64..528e0b55a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageBox.java @@ -17,10 +17,12 @@ */ package org.jackhuang.hmcl.ui.construct; +import com.jfoenix.concurrency.JFXUtilities; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.TextInputDialog; import org.jackhuang.hmcl.Launcher; +import org.jackhuang.hmcl.ui.FXUtils; import javax.swing.*; import java.util.Optional; @@ -123,30 +125,32 @@ public final class MessageBox { } public static int confirm(String message, String title, int option) { - Alert alert = new Alert(Alert.AlertType.CONFIRMATION); - alert.setTitle(title); - alert.setHeaderText(title); - alert.setContentText(message); - switch (option) { - case YES_NO_OPTION: - alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO); - break; - case YES_NO_CANCEL_OPTION: - alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); - break; - case OK_CANCEL_OPTION: - alert.getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL); - break; - default: - throw new IllegalArgumentException("Unrecognized message box option " + option); - } - Optional buttonType = alert.showAndWait(); - if (!buttonType.isPresent()) return CLOSED_OPTION; - else if (buttonType.get() == ButtonType.OK) return OK_OPTION; - else if (buttonType.get() == ButtonType.YES) return YES_OPTION; - else if (buttonType.get() == ButtonType.NO) return NO_OPTION; - else if (buttonType.get() == ButtonType.CANCEL) return CANCEL_OPTION; - else throw new IllegalStateException("Unrecognized button type:" + buttonType.get()); + return FXUtils.runInUIThread(() -> { + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setTitle(title); + alert.setHeaderText(title); + alert.setContentText(message); + switch (option) { + case YES_NO_OPTION: + alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO); + break; + case YES_NO_CANCEL_OPTION: + alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); + break; + case OK_CANCEL_OPTION: + alert.getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL); + break; + default: + throw new IllegalArgumentException("Unrecognized message box option " + option); + } + Optional buttonType = alert.showAndWait(); + if (!buttonType.isPresent()) return CLOSED_OPTION; + else if (buttonType.get() == ButtonType.OK) return OK_OPTION; + else if (buttonType.get() == ButtonType.YES) return YES_OPTION; + else if (buttonType.get() == ButtonType.NO) return NO_OPTION; + else if (buttonType.get() == ButtonType.CANCEL) return CANCEL_OPTION; + else throw new IllegalStateException("Unexpected button type:" + buttonType.get()); + }); } public static Optional input(String message) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java index b0c590e58..eca7caf91 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java @@ -19,6 +19,7 @@ package org.jackhuang.hmcl.upgrade; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; +import com.jfoenix.concurrency.JFXUtilities; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Schedulers; @@ -54,12 +55,19 @@ public class AppDataUpgrader extends IUpgrader { if (mainClass != null) { ArrayList al = new ArrayList<>(args); al.add("--noupdate"); - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - new URLClassLoader(new URL[]{jar.toURI().toURL()}, - ClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass) - .getMethod("main", String[].class).invoke(null, new Object[]{al.toArray(new String[0])}); - return null; - }); + ClassLoader pre = Thread.currentThread().getContextClassLoader(); + try { + AccessController.doPrivileged((PrivilegedExceptionAction) () -> { + Logging.stop(); + ClassLoader now = new URLClassLoader(new URL[]{jar.toURI().toURL()}, ClassLoader.getSystemClassLoader().getParent()); + Thread.currentThread().setContextClassLoader(now); + now.loadClass(mainClass).getMethod("main", String[].class).invoke(null, new Object[]{al.toArray(new String[0])}); + return null; + }); + } finally { + Logging.start(); + Thread.currentThread().setContextClassLoader(pre); + } return true; } } @@ -96,10 +104,10 @@ public class AppDataUpgrader extends IUpgrader { if (!(ver instanceof IntVersionNumber)) return; IntVersionNumber version = (IntVersionNumber) ver; - checker.requestDownloadLink().then(Task.of(Schedulers.javafx(), variables -> { + checker.requestDownloadLink().then(Task.of(variables -> { Map map = variables.get(UpdateChecker.REQUEST_DOWNLOAD_LINK_ID); - if (MessageBox.confirm(Launcher.i18n("update.newest_version") + version.toString() + "\n" + if (MessageBox.confirm(Launcher.i18n("update.newest_version", version.toString()) + "\n" + Launcher.i18n("update.should_open_link"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) if (map != null && map.containsKey("jar") && !StringUtils.isBlank(map.get("jar"))) @@ -122,7 +130,7 @@ public class AppDataUpgrader extends IUpgrader { String hash = null; if (map.containsKey("packsha1")) hash = map.get("packsha1"); - Controllers.dialog(Launcher.i18n("message.downloading")); + JFXUtilities.runInFX(() -> Controllers.dialog(Launcher.i18n("message.downloading"))); if (new AppDataUpgraderPackGzTask(NetworkUtils.toURL(map.get("pack")), version.toString(), hash).test()) { new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath()) .directory(new File("").getAbsoluteFile()).start(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java index 107d69aca..26b88cac9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.java @@ -35,6 +35,9 @@ public final class Logging { static { LOG = Logger.getLogger("HMCL"); + } + + public static void start() { LOG.setLevel(Level.FINER); LOG.setUseParentHandlers(false); @@ -63,6 +66,11 @@ public final class Logging { LOG.addHandler(streamHandler); } + public static void stop() { + for (Handler handler : LOG.getHandlers()) + LOG.removeHandler(handler); + } + public static String getLogs() { return OUTPUT_STREAM.toString(); }