Might fix game log watcher?

This commit is contained in:
huangyuhui
2016-02-16 18:57:26 +08:00
parent cb125b83cb
commit afecb87c6d
29 changed files with 280 additions and 223 deletions

View File

@@ -25,6 +25,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import org.jackhuang.hellominecraft.util.func.Function;
import org.jackhuang.hellominecraft.util.func.Predicate;
/**
*
@@ -115,6 +117,14 @@ public final class StrUtils {
return false;
}
public static boolean containsOne(List<String> base, List<String> match, Predicate<String> pred) {
for (String a : base)
for (String b : match)
if (pred.apply(a) && a.toLowerCase().contains(b.toLowerCase()))
return true;
return false;
}
public static int getCharShowTime(String s, char c) {
int res = 0;
for (int i = 0; i < s.length(); i++)
@@ -141,33 +151,37 @@ public final class StrUtils {
return parseParams(addBefore, paramArrayOfObject.toArray(), paramString);
}
public static String parseParams(String addBefore, Object[] paramArrayOfObject, String paramString) {
if (paramArrayOfObject == null)
return "";
StringBuilder localStringBuffer = new StringBuilder();
for (int i = 0; i < paramArrayOfObject.length; i++) {
Object localObject = paramArrayOfObject[i];
if (i > 0)
localStringBuffer.append(addBefore).append(paramString);
if (localObject == null)
localStringBuffer.append("null");
else if (localObject.getClass().isArray()) {
localStringBuffer.append("[");
public static String parseParams(String addBefore, Object[] params, String addAfter) {
return parseParams(t -> addBefore, params, t -> addAfter);
}
if ((localObject instanceof Object[])) {
Object[] arrayOfObject = (Object[]) localObject;
localStringBuffer.append(parseParams(addBefore, arrayOfObject, paramString));
public static String parseParams(Function<Object, String> beforeFunc, Object[] params, Function<Object, String> afterFunc) {
if (params == null)
return "";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.length; i++) {
Object param = params[i];
String addBefore = beforeFunc.apply(param), addAfter = afterFunc.apply(param);
if (i > 0)
sb.append(addAfter).append(addBefore);
if (param == null)
sb.append("null");
else if (param.getClass().isArray()) {
sb.append("[");
if ((param instanceof Object[])) {
Object[] objs = (Object[]) param;
sb.append(parseParams(beforeFunc, objs, afterFunc));
} else
for (int j = 0; j < Array.getLength(localObject); j++) {
for (int j = 0; j < Array.getLength(param); j++) {
if (j > 0)
localStringBuffer.append(paramString);
localStringBuffer.append(addBefore).append(Array.get(localObject, j));
sb.append(addAfter);
sb.append(addBefore).append(Array.get(param, j));
}
localStringBuffer.append("]");
sb.append("]");
} else
localStringBuffer.append(addBefore).append(paramArrayOfObject[i]);
sb.append(addBefore).append(params[i]);
}
return localStringBuffer.toString();
return sb.toString();
}
public static boolean isEquals(String base, String to) {

View File

@@ -30,7 +30,6 @@ public class JavaProcess {
private final List<String> commands;
private final Process process;
private final ArrayList<String> stdOutLines = new ArrayList<>();
private final ArrayList<String> stdErrLines = new ArrayList<>();
public JavaProcess(List<String> commands, Process process, ProcessManager pm) {
this.commands = commands;
@@ -59,10 +58,6 @@ public class JavaProcess {
return this.stdOutLines;
}
public ArrayList<String> getStdErrLines() {
return this.stdErrLines;
}
public boolean isRunning() {
try {
this.process.exitValue();

View File

@@ -20,9 +20,10 @@ package org.jackhuang.hellominecraft.util.system;
import java.util.Arrays;
import java.util.HashSet;
import org.jackhuang.hellominecraft.util.CollectionUtils;
import org.jackhuang.hellominecraft.util.Event;
import org.jackhuang.hellominecraft.util.EventHandler;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.logging.HMCLog;
import org.jackhuang.hellominecraft.util.logging.Level;
/**
*
@@ -51,31 +52,28 @@ public class JavaProcessMonitor {
this.p = p;
}
public JavaProcess getJavaProcess() {
return p;
}
public void start() {
Event<JavaProcess> event = (sender2, t) -> {
if (t.getExitCode() != 0)
ProcessThread a = new ProcessThread(p);
a.stopEvent.register((sender, t) -> {
HMCLog.log("Process exit code: " + t.getExitCode());
if (t.getExitCode() != 0 || StrUtils.containsOne(t.getStdOutLines(),
Arrays.asList("Unable to launch"),
x -> Level.guessLevel(x, Level.INFO).lessOrEqual(Level.ERROR)))
applicationExitedAbnormallyEvent.execute(t.getExitCode());
processThreadStopped((ProcessThread) sender2, false);
if (t.getExitCode() != 0 && StrUtils.containsOne(t.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)))
jvmLaunchFailedEvent.execute(t.getExitCode());
processThreadStopped((ProcessThread) sender, false);
return true;
};
Event<JavaProcess> event2 = (sender3, p1) -> {
if (p1.getExitCode() != 0 && p1.getStdErrLines().size() > 0 && StrUtils.containsOne(p1.getStdErrLines(), Arrays.asList("Could not create the Java Virtual Machine.",
"Error occurred during initialization of VM",
"A fatal exception has occurred. Program will exit.")))
jvmLaunchFailedEvent.execute(p1.getExitCode());
processThreadStopped((ProcessThread) sender3, false);
return true;
};
ProcessThread a = new ProcessThread(p, true, true);
a.stopEvent.register(event2);
a.start();
al.add(a);
a = new ProcessThread(p, false, true);
a.stopEvent.register(event2);
a.start();
al.add(a);
a = new ProcessThread(p, false, false);
a.stopEvent.register(event);
});
a.start();
al.add(a);
}

View File

@@ -30,15 +30,12 @@ import org.jackhuang.hellominecraft.util.EventHandler;
public class ProcessThread extends Thread {
JavaProcess p;
boolean readError = false, enableReading = true;
public final EventHandler<String> printlnEvent = new EventHandler<>(this);
public final EventHandler<JavaProcess> stopEvent = new EventHandler<>(this);
public ProcessThread(JavaProcess process, boolean readError, boolean enableReading) {
public ProcessThread(JavaProcess process) {
p = process;
this.readError = readError;
this.enableReading = enableReading;
}
public JavaProcess getProcess() {
@@ -47,58 +44,33 @@ public class ProcessThread extends Thread {
@Override
public void run() {
setName("ProcessMonitor");
InputStreamReader br = null;
try {
InputStreamReader br;
if (enableReading) {
InputStream in = readError ? p.getRawProcess().getErrorStream() : p.getRawProcess().getInputStream();
try {
br = new InputStreamReader(in, System.getProperty("sun.jnu.encoding", "UTF-8"));
} catch (UnsupportedEncodingException ex) {
HMCLog.warn("Unsupported encoding: " + System.getProperty("sun.jnu.encoding", "UTF-8"), ex);
br = new InputStreamReader(in);
}
} else
br = null;
InputStream in = p.getRawProcess().getInputStream();
try {
br = new InputStreamReader(in, System.getProperty("sun.jnu.encoding", "UTF-8"));
} catch (UnsupportedEncodingException ex) {
HMCLog.warn("Unsupported encoding: " + System.getProperty("sun.jnu.encoding", "UTF-8"), ex);
br = new InputStreamReader(in);
}
int ch;
String line = "";
while (p.isRunning())
if (br != null)
while ((ch = br.read()) != -1)
if (ch == '\n') {
printlnEvent.execute(line);
if (readError) {
System.err.println(line);
p.getStdErrLines().add(line);
} else {
System.out.println(line);
p.getStdOutLines().add(line);
}
line = "";
} else
line += (char) ch;
else
try {
Thread.sleep(1);
} catch (Exception e) {
}
if (br != null)
while ((ch = br.read()) != -1)
if (ch == '\n') {
printlnEvent.execute(line);
if (readError) {
System.err.println(line);
p.getStdErrLines().add(line);
} else {
System.out.println(line);
p.getStdOutLines().add(line);
}
System.out.println("Minecraft: " + line);
p.getStdOutLines().add(line);
line = "";
} else
line += (char) ch;
stopEvent.execute(p);
} catch (Exception e) {
e.printStackTrace();
HMCLog.err("An error occured when reading process stdout/stderr.", e);
} finally {
IOUtils.closeQuietly(br);
}
}
}

View File

@@ -0,0 +1,207 @@
package org.jackhuang.hellominecraft.util.ui;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthGraphicsUtils;
/**
* NimbusGraphicsUtils - extends SynthGraphicsUtils to force all Synth painted
* text to be antialiased and provides some static helper methods.
*
* @author Created by Jasper Potts (Jan 4, 2007)
* @version 1.0
*/
public class GraphicsUtils extends SynthGraphicsUtils {
private Map<?, ?> desktopHints;
/**
* Get rendering hints from a Graphics instance. "hintsToSave" is a Map of
* RenderingHint key-values. For each hint key present in that map, the
* value of that hint is obtained from the Graphics and stored as the value
* for the key in savedHints.
*
* @param g2d the graphics surface
* @param hintsToSave the list of rendering hints to set on the graphics
* @param savedHints a set where to save the previous rendering hints,
* might
* be null
*
* @return the previous set of rendering hints
*/
public static RenderingHints getRenderingHints(Graphics2D g2d,
Map<?, ?> hintsToSave,
RenderingHints savedHints) {
if (savedHints == null)
savedHints = new RenderingHints(null);
else
savedHints.clear();
if (hintsToSave.isEmpty())
return savedHints;
/* RenderingHints.keySet() returns Set */
for (Object o : hintsToSave.keySet()) {
RenderingHints.Key key = (RenderingHints.Key) o;
Object value = g2d.getRenderingHint(key);
savedHints.put(key, value);
}
return savedHints;
}
/**
* Overrides paintText in SynthGraphicsUtils to force all Synth painted text
* to be antialiased
*/
@Override
public void paintText(SynthContext ss, Graphics g, String text, int x, int y, int mnemonicIndex) {
Graphics2D g2 = (Graphics2D) g;
// XXX: In Java SE 6, Synth already uses the desktop hints, this code should just check whether java.version < 1.6
if (desktopHints == null) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
desktopHints = (Map<?, ?>) (toolkit.getDesktopProperty("awt.font.desktophints"));
}
Object oldAA = null;
RenderingHints oldHints = null;
if (desktopHints != null) {
oldHints = getRenderingHints(g2, desktopHints, null);
g2.addRenderingHints(desktopHints);
} else {
oldAA = g2.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
super.paintText(ss, g, text, x, y, mnemonicIndex);
if (oldHints != null)
g2.addRenderingHints(oldHints);
else if (oldAA != null)
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
oldAA);
}
/**
* Load an image using ImageIO from resource in
* org.jdesktop.swingx.plaf.nimbus.images. Catches and prints all Exceptions
* so that it can safely be used in a static context.
*
* @param imgName The name of the image to load, eg. "border.png"
*
* @return The loaded image
*/
public static BufferedImage loadImage(String imgName) {
try {
return ImageIO.read(GraphicsUtils.class.getClassLoader().getResource("org/jackhuang/hellominecraft/lookandfeel/images/" + imgName));
} catch (Exception e) {
System.err.println("Error loading image \"org/jackhuang/hellominecraft/lookandfeel/images/" + imgName + "\"");
e.printStackTrace();
}
return null;
}
public static String getColor(Color c) {
return Integer.toHexString(c.getRGB() & 0xFFFFFF);
}
/**
* Get a Color object from a web color string of the form "FF00AB" or
* "#FF00AB".
*
* @param c The color string
*
* @return The Color described
*/
public static Color getWebColor(String c) {
if (c.startsWith("#"))
c = c.substring(1);
return new Color(
Integer.parseInt(c.substring(0, 2), 16),
Integer.parseInt(c.substring(2, 4), 16),
Integer.parseInt(c.substring(4, 6), 16)
);
}
/**
* Get a Color object from a web color string of the form "FF00AB" or
* "#FF00AB".
*
* @param c The color string
*
* @return The Color described
*/
public static Color getWebColorWithAlpha(String c) {
if (c.startsWith("#"))
c = c.substring(1);
return new Color(
Integer.parseInt(c.substring(0, 2), 16),
Integer.parseInt(c.substring(2, 4), 16),
Integer.parseInt(c.substring(4, 6), 16),
Integer.parseInt(c.substring(6, 8), 16)
);
}
/**
* Get a Color that is 50% inbetween the two web colors given. The Web
* colors are of the form "FF00AB" or "#FF00AB".
*
* @param c1 The first color string
* @param c2 The second color string
*
* @return The Color middle color
*/
public static Color getMidWebColor(String c1, String c2) {
return getMidWebColor(c1, c2, 50);
}
/**
* Get a Color that is 50% inbetween the two web colors given. The Web
* colors are of the form "FF00AB" or "#FF00AB".
*
* @param c1 The first color string
* @param c2 The second color string
*
* @return The Color middle color
*/
public static Color getMidWebColor(String c1, String c2, int percent) {
if (c1.startsWith("#"))
c1 = c1.substring(1);
if (c2.startsWith("#"))
c2 = c2.substring(1);
int rTop = Integer.parseInt(c1.substring(0, 2), 16);
int gTop = Integer.parseInt(c1.substring(2, 4), 16);
int bTop = Integer.parseInt(c1.substring(4, 6), 16);
int rBot = Integer.parseInt(c2.substring(0, 2), 16);
int gBot = Integer.parseInt(c2.substring(2, 4), 16);
int bBot = Integer.parseInt(c2.substring(4, 6), 16);
int rMid = rTop + ((rBot - rTop) * percent / 100);
int gMid = gTop + ((gBot - gTop) * percent / 100);
int bMid = bTop + ((bBot - bTop) * percent / 100);
return new Color(rMid, gMid, bMid);
}
public static Color getMidWebColor(Color c1, Color c2, int percent) {
int rTop = c1.getRed();
int gTop = c1.getGreen();
int bTop = c1.getBlue();
int aTop = c1.getAlpha();
int rBot = c2.getRed();
int gBot = c2.getGreen();
int bBot = c2.getBlue();
int aBot = c2.getAlpha();
int rMid = rTop + ((rBot - rTop) * percent / 100);
int gMid = gTop + ((gBot - gTop) * percent / 100);
int bMid = bTop + ((bBot - bTop) * percent / 100);
int aMid = aTop + ((aBot - aTop) * percent / 100);
return new Color(rMid, gMid, bMid, aMid);
}
}

View File

@@ -33,31 +33,6 @@ public class LogWindowOutputStream extends OutputStream {
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();
* private StringBuilder cachedString = new StringBuilder();
*
* @Override
* public void run() {
* synchronized(lock) {
* SwingUtilities.invokeLater(() -> {
* String t = txt.getText() + cachedString.toString().replace("\t", " ");
* txt.setText(t);
* txt.setCaretPosition(t.length());
* cachedString = new StringBuilder();
* });
* }
* }
*
* void cache(String s) {
* synchronized(lock) {
* cachedString.append(s);
* }
* }
* }
*/
public LogWindowOutputStream(LogWindow logWindow, Level l) {
txt = logWindow;
this.sas = l;

View File

@@ -0,0 +1,85 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.util.ui;
import java.awt.Frame;
import java.awt.HeadlessException;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.List;
import javax.swing.JFrame;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.logging.Level;
/**
*
* @author huangyuhui
*/
public class WebFrame extends JFrame {
public WebFrame(String... strs) {
this(("<html>" + StrUtils.parseParams(t -> ("<font color='#" + GraphicsUtils.getColor(Level.guessLevel((String) t, Level.INFO).COLOR) + "'>"), strs, t -> "</font><br />") + "</html>")
.replace(" ", "&nbsp;").replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"));
}
public WebFrame(String content) throws HeadlessException {
addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
boolean flag = false;
for (Frame f : Frame.getFrames()) {
if (f == WebFrame.this)
continue;
if (f.isVisible())
flag = true;
}
if (!flag)
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
add(new WebPage(content));
pack();
setLocationRelativeTo(null);
}
}