diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index 8746e079a..e08115e5a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -40,6 +40,7 @@ import org.jackhuang.hmcl.util.*; import java.io.*; import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; public final class LauncherHelper { @@ -282,6 +283,7 @@ public final class LauncherHelper { private boolean lwjgl; private LogWindow logWindow; private final LinkedList> logs; + private final CountDownLatch latch = new CountDownLatch(1); public HMCLProcessListener(AuthInfo authInfo, VersionSetting setting) { this.setting = setting; @@ -307,11 +309,12 @@ public final class LauncherHelper { Platform.runLater(() -> { logWindow = new LogWindow(); logWindow.show(); + latch.countDown(); }); } @Override - public void onLog(String log, Log4jLevel level) { + public synchronized void onLog(String log, Log4jLevel level) { String newLog = log; for (Map.Entry entry : forbiddenTokens.entrySet()) newLog = newLog.replace(entry.getKey(), entry.getValue()); @@ -321,13 +324,19 @@ public final class LauncherHelper { else System.out.print(log); - Platform.runLater(() -> { - logs.add(new Pair<>(log, level)); - if (logs.size() > Settings.INSTANCE.getLogLines()) - logs.removeFirst(); - if (logWindow != null) - logWindow.logLine(log, level); - }); + logs.add(new Pair<>(log, level)); + if (logs.size() > Settings.INSTANCE.getLogLines()) + logs.removeFirst(); + + if (setting.isShowLogs()) { + Lang.invoke(() -> { + latch.await(); + logWindow.waitForLoaded(); + }); + + Platform.runLater(() -> logWindow.logLine(log, level)); + } + if (!lwjgl && log.contains("LWJGL Version: ")) { lwjgl = true; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java index f40794ee7..2edea87e7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java @@ -116,9 +116,9 @@ public final class LogWindow extends Stage { } public void logLine(String line, Log4jLevel level) { - Element div = impl.engine.getDocument().createElement("div"); + Element div = impl.document.createElement("div"); // a
 element to prevent multiple spaces and tabs being removed.
-        Element pre = impl.engine.getDocument().createElement("pre");
+        Element pre = impl.document.createElement("pre");
         pre.setTextContent(line);
         div.appendChild(pre);
         impl.body.appendChild(div);
@@ -143,6 +143,10 @@ public final class LogWindow extends Stage {
         }
     }
 
+    public void waitForLoaded() throws InterruptedException {
+        latch.await();
+    }
+
     public class LogWindowImpl extends StackPane {
 
         @FXML
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java
index 0a9840c9d..5efd70a9c 100644
--- a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java
+++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java
@@ -36,6 +36,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
 
     private static final HashMap SOURCE = new HashMap() {
         {
+            put("javafx.fxml.LoadException", Main.i18n("crash.NoClassDefFound"));
             put("UnsatisfiedLinkError", Main.i18n("crash.user_fault"));
             put("java.lang.NoClassDefFoundError", Main.i18n("crash.NoClassDefFound"));
             put("java.lang.VerifyError", Main.i18n("crash.NoClassDefFound"));
@@ -68,10 +69,14 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
 
     @Override
     public void uncaughtException(Thread t, Throwable e) {
-        String s = StringUtils.getStackTrace(e);
-        if (!s.contains("org.jackhuang"))
+        String stackTrace = StringUtils.getStackTrace(e);
+        if (!stackTrace.contains("org.jackhuang"))
             return;
 
+        if (THROWABLE_SET.contains(stackTrace))
+            return;
+        THROWABLE_SET.add(stackTrace);
+
         try {
             StringBuilder builder = new StringBuilder();
             builder.append("---- Hello Minecraft! Crash Report ----\n");
@@ -79,7 +84,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
             builder.append("  Time: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append("\n");
             builder.append("  Thread: ").append(t.toString()).append("\n");
             builder.append("\n  Content: \n    ");
-            builder.append(s).append("\n\n");
+            builder.append(stackTrace).append("\n\n");
             builder.append("-- System Details --\n");
             builder.append("  Operating System: ").append(System.getProperty("os.name")).append(' ').append(OperatingSystem.SYSTEM_VERSION).append("\n");
             builder.append("  Java Version: ").append(System.getProperty("java.version")).append(", ").append(System.getProperty("java.vendor")).append("\n");
@@ -91,7 +96,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
             if (checkThrowable(e) && !text.contains("OpenJDK")) {
                 Platform.runLater(() -> new CrashWindow(text).show());
                 if (!Main.UPDATE_CHECKER.isOutOfDate())
-                    reportToServer(text, s);
+                    reportToServer(text);
             }
         } catch (Throwable ex) {
             Logging.LOG.log(Level.SEVERE, "Unable to caught exception", ex);
@@ -101,10 +106,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
 
     private static final HashSet THROWABLE_SET = new HashSet<>();
 
-    private void reportToServer(final String text, String stacktrace) {
-        if (THROWABLE_SET.contains(stacktrace) || stacktrace.contains("Font") || stacktrace.contains("InternalError"))
-            return;
-        THROWABLE_SET.add(stacktrace);
+    private void reportToServer(final String text) {
         Thread t = new Thread(() -> {
             HashMap map = new HashMap<>();
             map.put("crash_report", text);
diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/Log4jHandler.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/Log4jHandler.java
index 26544e4a9..3d5da7539 100644
--- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/Log4jHandler.java
+++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/Log4jHandler.java
@@ -18,10 +18,7 @@
 package org.jackhuang.hmcl.launch;
 
 import org.jackhuang.hmcl.task.Schedulers;
-import org.jackhuang.hmcl.util.Constants;
-import org.jackhuang.hmcl.util.Lang;
-import org.jackhuang.hmcl.util.Log4jLevel;
-import org.jackhuang.hmcl.util.OperatingSystem;
+import org.jackhuang.hmcl.util.*;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
@@ -34,10 +31,15 @@ import java.io.InterruptedIOException;
 import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
 import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Optional;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.BiConsumer;
+import java.util.logging.Level;
+import java.util.stream.Collectors;
 
 /**
  * This class is to parse log4j classic XML layout logging,
@@ -54,6 +56,7 @@ final class Log4jHandler extends Thread {
     private final PipedOutputStream outputStream = new PipedOutputStream();
     private final PipedInputStream inputStream = Lang.invoke(() -> new PipedInputStream(outputStream));
     private final AtomicBoolean interrupted = new AtomicBoolean(false);
+    private final List logs = new LinkedList<>();
 
     public Log4jHandler(BiConsumer callback) {
         this.callback = callback;
@@ -73,7 +76,7 @@ final class Log4jHandler extends Thread {
             // Game has been interrupted.
             interrupted.set(true);
         } catch (SAXException | IOException e) {
-            Lang.throwable(e);
+            Logging.LOG.log(Level.WARNING, "An error occurred when reading console lines", e);
         }
     }
 
@@ -83,7 +86,7 @@ final class Log4jHandler extends Thread {
 
         Lang.invoke(() -> Schedulers.newThread().schedule(() -> {
             if (!interrupted.get()) {
-                Lang.invoke(() -> newLine("").get());
+                newLine("").get();
                 outputStream.close();
                 join();
             }
@@ -92,13 +95,22 @@ final class Log4jHandler extends Thread {
 
     public Future newLine(String log) {
         return Schedulers.computation().schedule(() -> {
-            byte[] bytes = (log + OperatingSystem.LINE_SEPARATOR)
-                    .replace("log4j:Event", "log4j_Event")
-                    .replace("log4j:Message", "log4j_Message")
-                    .replace("log4j:Throwable", "log4j_Throwable")
-                    .getBytes();
-            outputStream.write(bytes);
-            outputStream.flush();
+            try {
+                String line = (log + OperatingSystem.LINE_SEPARATOR)
+                        .replace("", "")
+                        .replace("log4j:Event", "log4j_Event")
+                        .replace("", "", "]]>")
+                        .replace("log4j:Throwable", "log4j_Throwable");
+                logs.add(line);
+                byte[] bytes = line.getBytes(Charsets.UTF_8);
+                outputStream.write(bytes);
+                outputStream.flush();
+            } catch (IOException e) {
+                // Ignoring IOException, including read end dead.
+                Logging.LOG.log(Level.WARNING, "An error occurred when writing console lines", e);
+            }
         });
     }
 
diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java
index cc110750c..6e39b8fa0 100644
--- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java
+++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java
@@ -60,7 +60,7 @@ public final class Lang {
             return function.apply(t);
         } catch (Exception e) {
             throwable(e);
-            return null; // won't get to here.
+            throw new Error(); // won't get to here.
         }
     }
 
@@ -88,7 +88,7 @@ public final class Lang {
             return supplier.get();
         } catch (Exception e) {
             throwable(e);
-            return null; // won't get to here.
+            throw new Error(); // won't get to here.
         }
     }