mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-10 12:26:16 -04:00
Modify logging system
This commit is contained in:
parent
0dfd8af7d5
commit
7436736040
@ -53,13 +53,12 @@ import org.jackhuang.hmcl.util.log.layout.DefaultLayout;
|
|||||||
import org.jackhuang.hmcl.util.ui.MyRepaintManager;
|
import org.jackhuang.hmcl.util.ui.MyRepaintManager;
|
||||||
import org.jackhuang.hmcl.util.upgrade.IUpgrader;
|
import org.jackhuang.hmcl.util.upgrade.IUpgrader;
|
||||||
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
|
import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper;
|
||||||
import org.jackhuang.hmcl.util.sys.JavaProcess;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class Main implements Runnable {
|
public final class Main {
|
||||||
|
|
||||||
private static final X509TrustManager XTM = new X509TrustManager() {
|
private static final X509TrustManager XTM = new X509TrustManager() {
|
||||||
@Override
|
@Override
|
||||||
@ -192,7 +191,6 @@ public final class Main implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LogWindow.INSTANCE.clean();
|
LogWindow.INSTANCE.clean();
|
||||||
LogWindow.INSTANCE.setTerminateGame(new Main()::run);
|
|
||||||
|
|
||||||
Settings.UPDATE_CHECKER.upgrade.register(IUpgrader.NOW_UPGRADER);
|
Settings.UPDATE_CHECKER.upgrade.register(IUpgrader.NOW_UPGRADER);
|
||||||
Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute();
|
Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute();
|
||||||
@ -214,12 +212,6 @@ public final class Main implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (Process p : JavaProcess.processes)
|
|
||||||
p.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void invokeUpdate() {
|
public static void invokeUpdate() {
|
||||||
MainFrame.INSTANCE.invokeUpdate();
|
MainFrame.INSTANCE.invokeUpdate();
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import org.jackhuang.hmcl.api.HMCLApi;
|
import org.jackhuang.hmcl.api.HMCLApi;
|
||||||
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
|
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
|
||||||
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
|
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
|
||||||
@ -40,7 +41,6 @@ import org.jackhuang.hmcl.api.HMCLog;
|
|||||||
import org.jackhuang.hmcl.util.DefaultPlugin;
|
import org.jackhuang.hmcl.util.DefaultPlugin;
|
||||||
import org.jackhuang.hmcl.util.sys.FileUtils;
|
import org.jackhuang.hmcl.util.sys.FileUtils;
|
||||||
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
|
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
|
||||||
import org.jackhuang.hmcl.util.net.WebFrame;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -89,29 +89,22 @@ public class LaunchingUIDaemon {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!LogWindow.INSTANCE.isVisible()) {
|
String msg = C.i18n("launch.exited_abnormally") + " exit code: " + exitCode;
|
||||||
String msg = C.i18n("launch.exited_abnormally") + " exit code: " + exitCode;
|
if (errorText != null)
|
||||||
if (errorText != null)
|
msg += ", advice: " + MinecraftCrashAdvicer.getAdvice(FileUtils.readQuietly(new File(errorText)));
|
||||||
msg += ", advice: " + MinecraftCrashAdvicer.getAdvice(FileUtils.readQuietly(new File(errorText)));
|
HMCLog.err(msg);
|
||||||
WebFrame f = new WebFrame(logs);
|
SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.setVisible(true));
|
||||||
f.setModal(true);
|
noExitThisTime = true;
|
||||||
f.setTitle(msg);
|
|
||||||
f.setVisible(true);
|
|
||||||
}
|
|
||||||
checkExit((LauncherVisibility) ((ProcessMonitor) event.getSource()).getTag());
|
|
||||||
});
|
});
|
||||||
HMCLApi.EVENT_BUS.channel(JVMLaunchFailedEvent.class).register(event -> {
|
HMCLApi.EVENT_BUS.channel(JVMLaunchFailedEvent.class).register(event -> {
|
||||||
int exitCode = event.getValue().getExitCode();
|
int exitCode = event.getValue().getExitCode();
|
||||||
HMCLog.err("Cannot create jvm, exit code: " + exitCode);
|
HMCLog.err("Cannot create jvm, exit code: " + exitCode);
|
||||||
if (!LogWindow.INSTANCE.isVisible()) {
|
SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.setVisible(true));
|
||||||
WebFrame f = new WebFrame(event.getValue().getStdOutLines().toArray(new String[0]));
|
noExitThisTime = true;
|
||||||
f.setModal(true);
|
|
||||||
f.setTitle(C.i18n("launch.cannot_create_jvm") + " exit code: " + exitCode);
|
|
||||||
f.setVisible(true);
|
|
||||||
}
|
|
||||||
checkExit((LauncherVisibility) ((ProcessMonitor) event.getSource()).getTag());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean noExitThisTime = false;
|
||||||
|
|
||||||
void runGame(Profile profile) {
|
void runGame(Profile profile) {
|
||||||
MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching"));
|
MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching"));
|
||||||
@ -168,12 +161,14 @@ public class LaunchingUIDaemon {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void checkExit(LauncherVisibility v) {
|
private void checkExit(LauncherVisibility v) {
|
||||||
if (v != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible()) {
|
if (v != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible() && !noExitThisTime) {
|
||||||
HMCLog.log("Launcher will exit now.");
|
HMCLog.log("Launcher will exit now.");
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
} else
|
} else {
|
||||||
HMCLog.log("Launcher will not exit now.");
|
HMCLog.log("Launcher will not exit now.");
|
||||||
|
noExitThisTime = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Consumer<LaunchSucceededEvent> LAUNCH_SCRIPT_FINISHER = event -> {
|
private static final Consumer<LaunchSucceededEvent> LAUNCH_SCRIPT_FINISHER = event -> {
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
<Group type="102" alignment="1" attributes="0">
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="1" attributes="0">
|
<Group type="103" groupAlignment="1" attributes="0">
|
||||||
<Component id="jScrollPane2" max="32767" attributes="0"/>
|
<Component id="pnlLog" max="32767" attributes="0"/>
|
||||||
<Group type="102" alignment="1" attributes="0">
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<Component id="btnTieBa" min="-2" max="-2" attributes="0"/>
|
<Component id="btnTieBa" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
@ -62,7 +62,7 @@
|
|||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="lblCrash" min="-2" max="-2" attributes="0"/>
|
<Component id="lblCrash" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="jScrollPane2" pref="356" max="32767" attributes="0"/>
|
<Component id="pnlLog" pref="356" max="32767" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="3" attributes="0">
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
<Component id="btnClear" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="btnClear" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
@ -161,7 +161,7 @@
|
|||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnGitHubActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnGitHubActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
|
<Container class="javax.swing.JScrollPane" name="pnlLog">
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package org.jackhuang.hmcl.ui;
|
package org.jackhuang.hmcl.ui;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
import javax.swing.JScrollBar;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.text.Document;
|
import javax.swing.text.Document;
|
||||||
import javax.swing.text.SimpleAttributeSet;
|
import javax.swing.text.SimpleAttributeSet;
|
||||||
@ -28,6 +29,7 @@ import org.jackhuang.hmcl.util.log.Level;
|
|||||||
import org.jackhuang.hmcl.api.func.NonFunction;
|
import org.jackhuang.hmcl.api.func.NonFunction;
|
||||||
import org.jackhuang.hmcl.util.DoubleOutputStream;
|
import org.jackhuang.hmcl.util.DoubleOutputStream;
|
||||||
import org.jackhuang.hmcl.util.Utils;
|
import org.jackhuang.hmcl.util.Utils;
|
||||||
|
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
|
||||||
import org.jackhuang.hmcl.util.ui.SwingUtils;
|
import org.jackhuang.hmcl.util.ui.SwingUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,9 +38,7 @@ import org.jackhuang.hmcl.util.ui.SwingUtils;
|
|||||||
*/
|
*/
|
||||||
public class LogWindow extends javax.swing.JFrame {
|
public class LogWindow extends javax.swing.JFrame {
|
||||||
|
|
||||||
boolean movingEnd;
|
|
||||||
NonFunction<Boolean> listener;
|
NonFunction<Boolean> listener;
|
||||||
Runnable terminateGameListener;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form LogWindow
|
* Creates new form LogWindow
|
||||||
@ -46,8 +46,6 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
public LogWindow() {
|
public LogWindow() {
|
||||||
initComponents();
|
initComponents();
|
||||||
|
|
||||||
movingEnd = true;
|
|
||||||
|
|
||||||
DoubleOutputStream out = new DoubleOutputStream(new LogWindowOutputStream(this, Level.INFO), System.out);
|
DoubleOutputStream out = new DoubleOutputStream(new LogWindowOutputStream(this, Level.INFO), System.out);
|
||||||
System.setOut(new PrintStream(out));
|
System.setOut(new PrintStream(out));
|
||||||
DoubleOutputStream err = new DoubleOutputStream(new LogWindowOutputStream(this, Level.ERROR), System.err);
|
DoubleOutputStream err = new DoubleOutputStream(new LogWindowOutputStream(this, Level.ERROR), System.err);
|
||||||
@ -79,7 +77,7 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
btnMCF = new javax.swing.JButton();
|
btnMCF = new javax.swing.JButton();
|
||||||
btnTerminateGame = new javax.swing.JButton();
|
btnTerminateGame = new javax.swing.JButton();
|
||||||
btnGitHub = new javax.swing.JButton();
|
btnGitHub = new javax.swing.JButton();
|
||||||
jScrollPane2 = new javax.swing.JScrollPane();
|
pnlLog = new javax.swing.JScrollPane();
|
||||||
txtLog = new javax.swing.JTextPane();
|
txtLog = new javax.swing.JTextPane();
|
||||||
|
|
||||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
@ -148,7 +146,7 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
jScrollPane2.setViewportView(txtLog);
|
pnlLog.setViewportView(txtLog);
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||||
getContentPane().setLayout(layout);
|
getContentPane().setLayout(layout);
|
||||||
@ -157,7 +155,7 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||||
.addComponent(jScrollPane2)
|
.addComponent(pnlLog)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addComponent(btnTieBa)
|
.addComponent(btnTieBa)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
@ -183,7 +181,7 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addComponent(lblCrash)
|
.addComponent(lblCrash)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE)
|
.addComponent(pnlLog, javax.swing.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addComponent(btnClear)
|
.addComponent(btnClear)
|
||||||
@ -201,8 +199,8 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed
|
private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed
|
||||||
if (listener != null && listener.apply() && terminateGameListener != null)
|
if (listener != null && listener.apply())
|
||||||
terminateGameListener.run();
|
terminateGames();
|
||||||
SwingUtils.exitIfNoWindow(this, true);
|
SwingUtils.exitIfNoWindow(this, true);
|
||||||
}//GEN-LAST:event_btnCloseActionPerformed
|
}//GEN-LAST:event_btnCloseActionPerformed
|
||||||
|
|
||||||
@ -227,8 +225,7 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
}//GEN-LAST:event_btnMCFActionPerformed
|
}//GEN-LAST:event_btnMCFActionPerformed
|
||||||
|
|
||||||
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)
|
terminateGames();
|
||||||
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
|
||||||
@ -236,11 +233,15 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
}//GEN-LAST:event_btnGitHubActionPerformed
|
}//GEN-LAST:event_btnGitHubActionPerformed
|
||||||
|
|
||||||
private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
|
private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
|
||||||
if (listener != null && listener.apply() && terminateGameListener != null)
|
if (listener != null && listener.apply())
|
||||||
terminateGameListener.run();
|
terminateGames();
|
||||||
SwingUtils.exitIfNoWindow(this);
|
SwingUtils.exitIfNoWindow(this);
|
||||||
}//GEN-LAST:event_formWindowClosing
|
}//GEN-LAST:event_formWindowClosing
|
||||||
|
|
||||||
|
void terminateGames() {
|
||||||
|
ProcessMonitor.stopAll();
|
||||||
|
}
|
||||||
|
|
||||||
public void log(final String status, final Level c) {
|
public void log(final String status, final Level c) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
String newStatus = status.replace("\t", " ");
|
String newStatus = status.replace("\t", " ");
|
||||||
@ -252,11 +253,6 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
HMCLog.err("Failed to insert \"" + newStatus + "\" to " + d.getLength(), ex);
|
HMCLog.err("Failed to insert \"" + newStatus + "\" to " + d.getLength(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (movingEnd) {
|
|
||||||
int position = d.getLength();
|
|
||||||
txtLog.setCaretPosition(position);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,22 +260,10 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
this.listener = exit;
|
this.listener = exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTerminateGame(Runnable l) {
|
|
||||||
this.terminateGameListener = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clean() {
|
public void clean() {
|
||||||
txtLog.setText("");
|
txtLog.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getMovingEnd() {
|
|
||||||
return movingEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMovingEnd(boolean b) {
|
|
||||||
movingEnd = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setVisible(boolean b) {
|
public void setVisible(boolean b) {
|
||||||
lblCrash.setVisible(false);
|
lblCrash.setVisible(false);
|
||||||
@ -316,8 +300,8 @@ public class LogWindow extends javax.swing.JFrame {
|
|||||||
private javax.swing.JButton btnMCF;
|
private javax.swing.JButton btnMCF;
|
||||||
private javax.swing.JButton btnTerminateGame;
|
private javax.swing.JButton btnTerminateGame;
|
||||||
private javax.swing.JButton btnTieBa;
|
private javax.swing.JButton btnTieBa;
|
||||||
private javax.swing.JScrollPane jScrollPane2;
|
|
||||||
private javax.swing.JLabel lblCrash;
|
private javax.swing.JLabel lblCrash;
|
||||||
|
private javax.swing.JScrollPane pnlLog;
|
||||||
private javax.swing.JTextPane txtLog;
|
private javax.swing.JTextPane txtLog;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ package org.jackhuang.hmcl.ui;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.jackhuang.hmcl.util.code.Charsets;
|
|
||||||
import org.jackhuang.hmcl.util.log.Level;
|
import org.jackhuang.hmcl.util.log.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,7 +167,7 @@ public abstract class GameLauncher {
|
|||||||
ProcessBuilder builder = new ProcessBuilder(str);
|
ProcessBuilder builder = new ProcessBuilder(str);
|
||||||
if (options.getLaunchVersion() == null || service.baseDirectory() == null)
|
if (options.getLaunchVersion() == null || service.baseDirectory() == null)
|
||||||
throw new Error("Fucking bug!");
|
throw new Error("Fucking bug!");
|
||||||
builder.redirectErrorStream(true).directory(service.version().getRunDirectory(options.getLaunchVersion()))
|
builder.directory(service.version().getRunDirectory(options.getLaunchVersion()))
|
||||||
.environment().put("APPDATA", service.baseDirectory().getAbsolutePath());
|
.environment().put("APPDATA", service.baseDirectory().getAbsolutePath());
|
||||||
JavaProcess jp = new JavaProcess(str, builder.start());
|
JavaProcess jp = new JavaProcess(str, builder.start());
|
||||||
HMCLog.log("Have started the process");
|
HMCLog.log("Have started the process");
|
||||||
|
@ -50,7 +50,8 @@ public enum Level {
|
|||||||
public static final Pattern MINECRAFT_LOGGER = Pattern.compile("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
|
public static final Pattern MINECRAFT_LOGGER = Pattern.compile("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
|
||||||
public static final String JAVA_SYMBOL = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*";
|
public static final String JAVA_SYMBOL = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*";
|
||||||
|
|
||||||
public static Level guessLevel(String line, Level level) {
|
public static Level guessLevel(String line, Level preLevel) {
|
||||||
|
Level level = preLevel;
|
||||||
Matcher m = MINECRAFT_LOGGER.matcher(line);
|
Matcher m = MINECRAFT_LOGGER.matcher(line);
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
// New style logs from log4j
|
// New style logs from log4j
|
||||||
@ -98,7 +99,7 @@ public enum Level {
|
|||||||
|| line.matches("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)")
|
|| line.matches("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)")
|
||||||
|| line.matches("... \\d+ more$"))
|
|| line.matches("... \\d+ more$"))
|
||||||
return ERROR;
|
return ERROR;
|
||||||
return level;
|
return preLevel.level < level.level ? preLevel : level;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ package org.jackhuang.hmcl.util.sys;
|
|||||||
import org.jackhuang.hmcl.api.IProcess;
|
import org.jackhuang.hmcl.api.IProcess;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,7 +27,6 @@ import java.util.List;
|
|||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public class JavaProcess implements IProcess {
|
public class JavaProcess implements IProcess {
|
||||||
public static HashSet<Process> processes = new HashSet<>();
|
|
||||||
|
|
||||||
private final List<String> commands;
|
private final List<String> commands;
|
||||||
private final Process process;
|
private final Process process;
|
||||||
@ -37,7 +35,6 @@ public class JavaProcess implements IProcess {
|
|||||||
public JavaProcess(List<String> commands, Process process) {
|
public JavaProcess(List<String> commands, Process process) {
|
||||||
this.commands = commands;
|
this.commands = commands;
|
||||||
this.process = process;
|
this.process = process;
|
||||||
processes.add(process);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JavaProcess(String[] commands, Process process) {
|
public JavaProcess(String[] commands, Process process) {
|
||||||
|
@ -19,7 +19,6 @@ package org.jackhuang.hmcl.util.sys;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import org.jackhuang.hmcl.util.CollectionUtils;
|
|
||||||
import org.jackhuang.hmcl.api.HMCLApi;
|
import org.jackhuang.hmcl.api.HMCLApi;
|
||||||
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
|
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
|
||||||
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
|
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
|
||||||
@ -36,7 +35,9 @@ import org.jackhuang.hmcl.api.IProcess;
|
|||||||
*/
|
*/
|
||||||
public class ProcessMonitor {
|
public class ProcessMonitor {
|
||||||
|
|
||||||
private final HashSet<Thread> al = new HashSet<>();
|
public static final HashSet<ProcessMonitor> MONITORS = new HashSet<>();
|
||||||
|
|
||||||
|
ProcessThread inputThread, errorThread;
|
||||||
private final IProcess p;
|
private final IProcess p;
|
||||||
|
|
||||||
public ProcessMonitor(IProcess p) {
|
public ProcessMonitor(IProcess p) {
|
||||||
@ -46,7 +47,7 @@ public class ProcessMonitor {
|
|||||||
public IProcess getProcess() {
|
public IProcess getProcess() {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object tag;
|
private Object tag;
|
||||||
|
|
||||||
public Object getTag() {
|
public Object getTag() {
|
||||||
@ -56,36 +57,44 @@ public class ProcessMonitor {
|
|||||||
public void setTag(Object tag) {
|
public void setTag(Object tag) {
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
|
MONITORS.add(this);
|
||||||
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStartingEvent(this, p));
|
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStartingEvent(this, p));
|
||||||
ProcessThread a = new ProcessThread(p);
|
inputThread = new ProcessThread(p, false);
|
||||||
a.stopEvent.register(event -> {
|
errorThread = new ProcessThread(p, true);
|
||||||
HMCLog.log("Process exit code: " + p.getExitCode());
|
inputThread.stopEvent.register(this::threadStopped);
|
||||||
if (p.getExitCode() != 0 || StrUtils.containsOne(p.getStdOutLines(),
|
inputThread.stopEvent.register(event -> processThreadStopped((ProcessThread) event.getSource()));
|
||||||
Arrays.asList("Unable to launch"),
|
errorThread.stopEvent.register(this::threadStopped);
|
||||||
x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR)))
|
inputThread.start();
|
||||||
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(ProcessMonitor.this, p));
|
|
||||||
if (p.getExitCode() != 0 && StrUtils.containsOne(p.getStdOutLines(),
|
|
||||||
Arrays.asList("Could not create the Java Virtual Machine.",
|
|
||||||
"Error occurred during initialization of VM",
|
|
||||||
"A fatal exception has occurred. Program will exit.",
|
|
||||||
"Unable to launch"),
|
|
||||||
x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR)))
|
|
||||||
HMCLApi.EVENT_BUS.fireChannel(new JVMLaunchFailedEvent(ProcessMonitor.this, p));
|
|
||||||
processThreadStopped((ProcessThread) event.getSource(), false);
|
|
||||||
});
|
|
||||||
a.start();
|
|
||||||
al.add(a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void processThreadStopped(ProcessThread t1, boolean forceTermintate) {
|
private void threadStopped() {
|
||||||
CollectionUtils.removeIf(al, t -> t == t1 || !t.isAlive());
|
HMCLog.log("Process exit code: " + p.getExitCode());
|
||||||
if (al.isEmpty() || forceTermintate) {
|
if (p.getExitCode() != 0 || StrUtils.containsOne(p.getStdOutLines(),
|
||||||
for (Thread a : al)
|
Arrays.asList("Unable to launch"),
|
||||||
a.interrupt();
|
x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR)))
|
||||||
al.clear();
|
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(ProcessMonitor.this, p));
|
||||||
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStoppedEvent(this, p));
|
if (p.getExitCode() != 0 && StrUtils.containsOne(p.getStdOutLines(),
|
||||||
|
Arrays.asList("Could not create the Java Virtual Machine.",
|
||||||
|
"Error occurred during initialization of VM",
|
||||||
|
"A fatal exception has occurred. Program will exit.",
|
||||||
|
"Unable to launch"),
|
||||||
|
x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR)))
|
||||||
|
HMCLApi.EVENT_BUS.fireChannel(new JVMLaunchFailedEvent(ProcessMonitor.this, p));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processThreadStopped(ProcessThread t1) {
|
||||||
|
MONITORS.remove(this);
|
||||||
|
errorThread.interrupt();
|
||||||
|
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStoppedEvent(this, p));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopAll() {
|
||||||
|
for (ProcessMonitor monitor : MONITORS) {
|
||||||
|
monitor.getProcess().getRawProcess().destroy();
|
||||||
|
monitor.inputThread.interrupt();
|
||||||
|
monitor.errorThread.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,12 +34,14 @@ import org.jackhuang.hmcl.api.IProcess;
|
|||||||
public class ProcessThread extends Thread {
|
public class ProcessThread extends Thread {
|
||||||
|
|
||||||
IProcess p;
|
IProcess p;
|
||||||
|
boolean readError;
|
||||||
public final EventHandler<SimpleEvent<String>> printlnEvent = new EventHandler<>();
|
public final EventHandler<SimpleEvent<String>> printlnEvent = new EventHandler<>();
|
||||||
public final EventHandler<SimpleEvent<IProcess>> stopEvent = new EventHandler<>();
|
public final EventHandler<SimpleEvent<IProcess>> stopEvent = new EventHandler<>();
|
||||||
|
|
||||||
public ProcessThread(IProcess process) {
|
public ProcessThread(IProcess process, boolean readError) {
|
||||||
p = process;
|
p = process;
|
||||||
|
this.readError = readError;
|
||||||
|
setDaemon(readError);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IProcess getProcess() {
|
public IProcess getProcess() {
|
||||||
@ -51,7 +53,7 @@ public class ProcessThread extends Thread {
|
|||||||
setName("ProcessMonitor");
|
setName("ProcessMonitor");
|
||||||
BufferedReader br = null;
|
BufferedReader br = null;
|
||||||
try {
|
try {
|
||||||
InputStream in = p.getRawProcess().getInputStream();
|
InputStream in = readError ? p.getRawProcess().getErrorStream() : p.getRawProcess().getInputStream();
|
||||||
br = new BufferedReader(new InputStreamReader(in, Charsets.toCharset()));
|
br = new BufferedReader(new InputStreamReader(in, Charsets.toCharset()));
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
@ -66,7 +68,6 @@ public class ProcessThread extends Thread {
|
|||||||
System.out.println("MC: " + line);
|
System.out.println("MC: " + line);
|
||||||
p.getStdOutLines().add(line);
|
p.getStdOutLines().add(line);
|
||||||
}
|
}
|
||||||
JavaProcess.processes.remove(p.getRawProcess());
|
|
||||||
stopEvent.fire(new SimpleEvent<>(this, p));
|
stopEvent.fire(new SimpleEvent<>(this, p));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
HMCLog.err("An error occured when reading process stdout/stderr.", e);
|
HMCLog.err("An error occured when reading process stdout/stderr.", e);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user