Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41d313baff | ||
|
|
58c3ed9254 | ||
|
|
affe36a568 |
No files matched your search
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> T runInUIThread(Supplier<T> supplier) {
|
||||
if (javafx.application.Platform.isFxApplicationThread()) {
|
||||
return supplier.get();
|
||||
} else {
|
||||
CountDownLatch doneLatch = new CountDownLatch(1);
|
||||
AtomicReference<T> 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() {
|
||||
|
||||
@@ -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> 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> 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<String> input(String message) {
|
||||
|
||||
@@ -89,10 +89,10 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh
|
||||
chkSnapshot.selectedProperty().addListener(listener);
|
||||
chkOld.selectedProperty().addListener(listener);
|
||||
|
||||
list.getSelectionModel().selectedItemProperty().addListener((a, b, newValue) -> {
|
||||
if (newValue == null)
|
||||
list.setOnMouseClicked(e -> {
|
||||
if (list.getSelectionModel().getSelectedIndex() < 0)
|
||||
return;
|
||||
controller.getSettings().put(libraryId, newValue.getRemoteVersion());
|
||||
controller.getSettings().put(libraryId, list.getSelectionModel().getSelectedItem().getRemoteVersion());
|
||||
callback.run();
|
||||
});
|
||||
refresh();
|
||||
|
||||
@@ -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<String> al = new ArrayList<>(args);
|
||||
al.add("--noupdate");
|
||||
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
|
||||
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<Void>) () -> {
|
||||
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<String, String> 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();
|
||||
|
||||
@@ -116,7 +116,7 @@ public final class GameVersion {
|
||||
.getEntry("net/minecraft/client/Minecraft.class");
|
||||
if (minecraft != null)
|
||||
return getVersionOfOldMinecraft(f, minecraft);
|
||||
ZipArchiveEntry main = f.getEntry("net/minecraft/client/main/Launcher.class");
|
||||
ZipArchiveEntry main = f.getEntry("net/minecraft/client/main/Main.class");
|
||||
ZipArchiveEntry minecraftServer = f.getEntry("net/minecraft/server/MinecraftServer.class");
|
||||
if ((main != null) && (minecraftServer != null))
|
||||
return getVersionOfNewMinecraft(f, minecraftServer);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user