mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-08-03 19:36:53 -04:00
Added logging highlight.
This commit is contained in:
parent
990f830300
commit
b7aa99550d
@ -99,7 +99,7 @@ public final class Launcher {
|
||||
|
||||
Method minecraftMain;
|
||||
try {
|
||||
minecraftMain = new URLClassLoader(urls, URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass).getMethod("main", String[].class);
|
||||
minecraftMain = new URLClassLoader(urls, URLClassLoader.getSystemClassLoader()).loadClass(mainClass).getMethod("main", String[].class);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException t) {
|
||||
MessageBox.Show(C.i18n("crash.main_class_not_found"));
|
||||
println("Minecraft main class not found.");
|
||||
@ -118,9 +118,9 @@ public final class Launcher {
|
||||
final String advice = MinecraftCrashAdvicer.getAdvice(trace);
|
||||
MessageBox.Show(C.i18n("crash.minecraft") + ": " + advice);
|
||||
|
||||
LogWindow.instance.log(C.i18n("crash.minecraft"));
|
||||
LogWindow.instance.log(advice);
|
||||
LogWindow.instance.log(trace);
|
||||
LogWindow.instance.warning(C.i18n("crash.minecraft"));
|
||||
LogWindow.instance.warning(advice);
|
||||
LogWindow.instance.warning(trace);
|
||||
LogWindow.instance.setExit(TrueFunction.instance);
|
||||
LogWindow.instance.setVisible(true);
|
||||
|
||||
|
@ -70,7 +70,7 @@ import org.jackhuang.hellominecraft.utils.system.OS;
|
||||
*/
|
||||
public final class Main implements Runnable {
|
||||
|
||||
private static final X509TrustManager xtm = new X509TrustManager() {
|
||||
private static final X509TrustManager XTM = new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
||||
}
|
||||
@ -84,21 +84,21 @@ public final class Main implements Runnable {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
private static final HostnameVerifier hnv = (hostname, session) -> true;
|
||||
private static final HostnameVerifier HNV = (hostname, session) -> true;
|
||||
|
||||
static {
|
||||
SSLContext sslContext = null;
|
||||
|
||||
try {
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
X509TrustManager[] xtmArray = new X509TrustManager[]{xtm};
|
||||
X509TrustManager[] xtmArray = new X509TrustManager[]{XTM};
|
||||
sslContext.init(null, xtmArray, new java.security.SecureRandom());
|
||||
} catch (GeneralSecurityException gse) {
|
||||
}
|
||||
if (sslContext != null)
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
|
||||
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(hnv);
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(HNV);
|
||||
}
|
||||
|
||||
public static String launcherName = "Hello Minecraft! Launcher";
|
||||
@ -123,7 +123,7 @@ public final class Main implements Runnable {
|
||||
return launcherName + ' ' + makeVersion();
|
||||
}
|
||||
|
||||
public static final Main instance = new Main();
|
||||
public static final Main INSTANCE = new Main();
|
||||
|
||||
public static void main(String[] args) {
|
||||
{
|
||||
|
@ -144,7 +144,7 @@ public class GameLauncher {
|
||||
.environment().put("APPDATA", get.getCanonicalGameDir());
|
||||
JavaProcess jp = new JavaProcess(str, builder.start(), PROCESS_MANAGER);
|
||||
launchEvent.execute(jp);
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
failEvent.execute(C.i18n("launch.failed_creating_process") + "\n" + e.getMessage());
|
||||
HMCLog.err("Failed to launch when creating a new process.", e);
|
||||
}
|
||||
|
@ -16,33 +16,82 @@
|
||||
*/
|
||||
package org.jackhuang.hellominecraft.logging;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public enum Level {
|
||||
|
||||
OFF(0),
|
||||
FATAL(1),
|
||||
ERROR(2),
|
||||
WARN(3),
|
||||
INFO(4),
|
||||
DEBUG(5),
|
||||
TRACE(6),
|
||||
ALL(2147483647);
|
||||
OFF(0, Color.gray),
|
||||
FATAL(1, Color.red),
|
||||
ERROR(2, Color.red),
|
||||
WARN(3, Color.orange),
|
||||
INFO(4, Color.black),
|
||||
DEBUG(5, Color.blue),
|
||||
TRACE(6, Color.blue),
|
||||
ALL(2147483647, Color.black);
|
||||
|
||||
public final int level;
|
||||
public final Color COLOR;
|
||||
|
||||
private Level(int i) {
|
||||
level = i;
|
||||
private Level(int i, Color c) {
|
||||
level = i;
|
||||
COLOR = c;
|
||||
}
|
||||
|
||||
public boolean lessOrEqual(Level level) {
|
||||
return this.level <= level.level;
|
||||
return this.level <= level.level;
|
||||
}
|
||||
|
||||
public boolean lessOrEqual(int level) {
|
||||
return this.level <= level;
|
||||
return this.level <= 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 Level guessLevel(String line, Level level) {
|
||||
Matcher m = MINECRAFT_LOGGER.matcher(line);
|
||||
if (m.find()) {
|
||||
// New style logs from log4j
|
||||
String levelStr = m.group("level");
|
||||
if ("INFO".equals(levelStr))
|
||||
level = INFO;
|
||||
else if ("WARN".equals(levelStr))
|
||||
level = WARN;
|
||||
else if ("ERROR".equals(levelStr))
|
||||
level = ERROR;
|
||||
else if ("FATAL".equals(levelStr))
|
||||
level = FATAL;
|
||||
else if ("TRACE".equals(levelStr))
|
||||
level = TRACE;
|
||||
else if ("DEBUG".equals(levelStr))
|
||||
level = DEBUG;
|
||||
} else {
|
||||
if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]")
|
||||
|| line.contains("[FINER]") || line.contains("[FINEST]"))
|
||||
level = INFO;
|
||||
if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
|
||||
level = ERROR;
|
||||
if (line.contains("[WARNING]"))
|
||||
level = WARN;
|
||||
if (line.contains("[DEBUG]"))
|
||||
level = DEBUG;
|
||||
}
|
||||
if (line.contains("overwriting existing"))
|
||||
return FATAL;
|
||||
|
||||
if (line.contains("Exception in thread")
|
||||
|| line.matches("\\s+at " + JAVA_SYMBOL)
|
||||
|| line.matches("Caused by: " + JAVA_SYMBOL)
|
||||
|| line.matches("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)")
|
||||
|| line.matches("... \\d+ more$"))
|
||||
return ERROR;
|
||||
return level;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public class DefaultLayout extends AbstractStringLayout {
|
||||
|
||||
@Override
|
||||
public String toSerializable(LogEvent event) {
|
||||
return "[" + sdf.format(new Date()) + "][" + event.threadName + "/" + event.level.name() + "] " + event.message.getFormattedMessage() + "\n";
|
||||
return "[" + sdf.format(new Date()) + "] [" + event.threadName + "/" + event.level.name() + "] " + event.message.getFormattedMessage() + "\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,19 +18,21 @@ package org.jackhuang.hellominecraft.utils;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import org.jackhuang.hellominecraft.logging.Level;
|
||||
import org.jackhuang.hellominecraft.views.LogWindow;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public class TextComponentOutputStream extends OutputStream {
|
||||
public class LogWindowOutputStream extends OutputStream {
|
||||
|
||||
private static final Timer TIMER = new Timer();
|
||||
|
||||
private final JTextComponent txt;
|
||||
private final LogWindow txt;
|
||||
private final Level sas;
|
||||
/*
|
||||
private final CacheTask t = new CacheTask();
|
||||
private class CacheTask extends TimerTask {
|
||||
private final Object lock = new Object();
|
||||
@ -53,12 +55,11 @@ public class TextComponentOutputStream extends OutputStream {
|
||||
cachedString.append(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
public TextComponentOutputStream(JTextComponent paramJTextComponent) {
|
||||
txt = paramJTextComponent;
|
||||
|
||||
//TIMER.schedule(t, 20);
|
||||
public LogWindowOutputStream(LogWindow logWindow, Level l) {
|
||||
txt = logWindow;
|
||||
this.sas = l;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -72,12 +73,9 @@ public class TextComponentOutputStream extends OutputStream {
|
||||
}
|
||||
|
||||
private void append(final String newString) {
|
||||
//t.cache(newString);
|
||||
try {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
String t = txt.getText() + newString.replace("\t", " ");
|
||||
txt.setText(t);
|
||||
txt.setCaretPosition(t.length());
|
||||
txt.log(newString, Level.guessLevel(newString, sas));
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
@ -29,10 +29,10 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="jScrollPane2" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="btnTieBa" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -50,7 +50,7 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnClose" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lblCrash" alignment="0" pref="674" max="32767" attributes="0"/>
|
||||
<Component id="lblCrash" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -62,7 +62,7 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblCrash" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="375" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane2" pref="356" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="btnClear" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
@ -80,22 +80,6 @@
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextArea" name="txtLog">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="false"/>
|
||||
<Property name="columns" type="int" value="20"/>
|
||||
<Property name="rows" type="int" value="5"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="btnClear">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
@ -177,5 +161,16 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnGitHubActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextPane" name="txtLog">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -16,13 +16,18 @@
|
||||
*/
|
||||
package org.jackhuang.hellominecraft.views;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.awt.Color;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.SimpleAttributeSet;
|
||||
import javax.swing.text.StyleConstants;
|
||||
import org.jackhuang.hellominecraft.C;
|
||||
import org.jackhuang.hellominecraft.HMCLog;
|
||||
import org.jackhuang.hellominecraft.logging.Level;
|
||||
import org.jackhuang.hellominecraft.utils.functions.NonFunction;
|
||||
import org.jackhuang.hellominecraft.utils.DoubleOutputStream;
|
||||
import org.jackhuang.hellominecraft.utils.LauncherPrintStream;
|
||||
import org.jackhuang.hellominecraft.utils.StrUtils;
|
||||
import org.jackhuang.hellominecraft.utils.TextComponentOutputStream;
|
||||
import org.jackhuang.hellominecraft.utils.LogWindowOutputStream;
|
||||
import org.jackhuang.hellominecraft.utils.Utils;
|
||||
|
||||
/**
|
||||
@ -44,11 +49,10 @@ public class LogWindow extends javax.swing.JFrame {
|
||||
movingEnd = true;
|
||||
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
TextComponentOutputStream tc = new TextComponentOutputStream(txtLog);
|
||||
DoubleOutputStream out = new DoubleOutputStream(tc, System.out);
|
||||
txtLog.setEditable(false);
|
||||
DoubleOutputStream out = new DoubleOutputStream(new LogWindowOutputStream(this, Level.INFO), System.out);
|
||||
System.setOut(new LauncherPrintStream(out));
|
||||
DoubleOutputStream err = new DoubleOutputStream(tc, System.err);
|
||||
DoubleOutputStream err = new DoubleOutputStream(new LogWindowOutputStream(this, Level.ERROR), System.err);
|
||||
System.setErr(new LauncherPrintStream(err));
|
||||
}
|
||||
|
||||
@ -63,8 +67,6 @@ public class LogWindow extends javax.swing.JFrame {
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
txtLog = new javax.swing.JTextArea();
|
||||
btnClear = new javax.swing.JButton();
|
||||
btnClose = new javax.swing.JButton();
|
||||
btnCopy = new javax.swing.JButton();
|
||||
@ -74,6 +76,8 @@ public class LogWindow extends javax.swing.JFrame {
|
||||
btnMCF = new javax.swing.JButton();
|
||||
btnTerminateGame = new javax.swing.JButton();
|
||||
btnGitHub = new javax.swing.JButton();
|
||||
jScrollPane2 = new javax.swing.JScrollPane();
|
||||
txtLog = new javax.swing.JTextPane();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setTitle(C.I18N.getString("logwindow.title")); // NOI18N
|
||||
@ -83,11 +87,6 @@ public class LogWindow extends javax.swing.JFrame {
|
||||
}
|
||||
});
|
||||
|
||||
txtLog.setEditable(false);
|
||||
txtLog.setColumns(20);
|
||||
txtLog.setRows(5);
|
||||
jScrollPane1.setViewportView(txtLog);
|
||||
|
||||
btnClear.setText(C.I18N.getString("ui.button.clear")); // NOI18N
|
||||
btnClear.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
@ -146,15 +145,17 @@ public class LogWindow extends javax.swing.JFrame {
|
||||
}
|
||||
});
|
||||
|
||||
jScrollPane2.setViewportView(txtLog);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane1)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(jScrollPane2)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(btnTieBa)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnMCBBS)
|
||||
@ -170,7 +171,7 @@ public class LogWindow extends javax.swing.JFrame {
|
||||
.addComponent(btnClear)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnClose))
|
||||
.addComponent(lblCrash, javax.swing.GroupLayout.DEFAULT_SIZE, 674, Short.MAX_VALUE))
|
||||
.addComponent(lblCrash, javax.swing.GroupLayout.Alignment.LEADING))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
@ -179,7 +180,7 @@ public class LogWindow extends javax.swing.JFrame {
|
||||
.addContainerGap()
|
||||
.addComponent(lblCrash, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 375, Short.MAX_VALUE)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnClear)
|
||||
@ -235,19 +236,28 @@ public class LogWindow extends javax.swing.JFrame {
|
||||
}//GEN-LAST:event_btnGitHubActionPerformed
|
||||
|
||||
public void log(String status) {
|
||||
String text = txtLog.getText();
|
||||
text += status + System.getProperty("line.separator");
|
||||
txtLog.setText(text);
|
||||
|
||||
if (movingEnd) {
|
||||
int position = text.length();
|
||||
txtLog.setCaretPosition(position);
|
||||
}
|
||||
log(status, Level.INFO);
|
||||
}
|
||||
|
||||
public void log(String status, Throwable t) {
|
||||
log(status);
|
||||
log(StrUtils.getStackTrace(t));
|
||||
public void warning(String status) {
|
||||
log(status, Level.WARN);
|
||||
}
|
||||
|
||||
public void log(String status, Level c) {
|
||||
status = status.replace("\t", " ");
|
||||
Document d = txtLog.getStyledDocument();
|
||||
SimpleAttributeSet sas = new SimpleAttributeSet();
|
||||
StyleConstants.setForeground(sas, c.COLOR);
|
||||
try {
|
||||
d.insertString(d.getLength(), status, sas);
|
||||
} catch (BadLocationException ex) {
|
||||
HMCLog.err("Failed to insert \"" + status + "\" to " + d.getLength(), ex);
|
||||
}
|
||||
|
||||
if (movingEnd) {
|
||||
int position = d.getLength();
|
||||
txtLog.setCaretPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
public void setExit(NonFunction<Boolean> exit) {
|
||||
@ -306,8 +316,8 @@ public class LogWindow extends javax.swing.JFrame {
|
||||
private javax.swing.JButton btnMCF;
|
||||
private javax.swing.JButton btnTerminateGame;
|
||||
private javax.swing.JButton btnTieBa;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JScrollPane jScrollPane2;
|
||||
private javax.swing.JLabel lblCrash;
|
||||
private javax.swing.JTextArea txtLog;
|
||||
private javax.swing.JTextPane txtLog;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -63,10 +63,10 @@ public class Main {
|
||||
HMCLog.err("There's something wrong when running server holder.", t);
|
||||
|
||||
LogWindow.instance.clean();
|
||||
LogWindow.instance.log("开服器崩溃了QAQ");
|
||||
LogWindow.instance.warning("开服器崩溃了QAQ");
|
||||
StringWriter trace = new StringWriter();
|
||||
t.printStackTrace(new PrintWriter(trace));
|
||||
LogWindow.instance.log(trace.toString());
|
||||
LogWindow.instance.warning(trace.toString());
|
||||
LogWindow.instance.setVisible(true);
|
||||
|
||||
System.exit(-1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user