Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3721842c8b | ||
|
|
47d8b59b93 |
No files matched your search
+5
-5
@@ -24,9 +24,9 @@ import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
plugins {
|
||||
id "edu.sc.seis.macAppBundle" version "2.1.6"
|
||||
id "me.tatarka.retrolambda" version "3.5.0"
|
||||
id 'edu.sc.seis.launch4j' version '2.3.0'
|
||||
id "edu.sc.seis.macAppBundle" version "2.1.8"
|
||||
id "me.tatarka.retrolambda" version "3.7.0"
|
||||
id 'edu.sc.seis.launch4j' version '2.4.2'
|
||||
//id "org.jetbrains.kotlin.jvm" version "1.1.2-2"
|
||||
}
|
||||
|
||||
@@ -38,11 +38,11 @@ def buildnumber = System.getenv("TRAVIS_BUILD_NUMBER")
|
||||
if (buildnumber == null)
|
||||
buildnumber = System.getenv("BUILD_NUMBER")
|
||||
if (buildnumber == null)
|
||||
buildnumber = "42"
|
||||
buildnumber = "51"
|
||||
|
||||
def versionroot = System.getenv("VERSION_ROOT")
|
||||
if (versionroot == null)
|
||||
versionroot = "2.7.8"
|
||||
versionroot = "2.7.9"
|
||||
|
||||
String mavenGroupId = 'HMCL'
|
||||
String mavenVersion = versionroot + '.' + buildnumber
|
||||
|
||||
@@ -69,7 +69,6 @@ import org.jackhuang.hmcl.api.auth.IAuthenticator;
|
||||
import org.jackhuang.hmcl.api.ui.Theme;
|
||||
import org.jackhuang.hmcl.api.ui.TopTabPage;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huangyuhui
|
||||
@@ -256,7 +255,7 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
|
||||
|
||||
realPanel.setBounds(1, 0, 800, 511);
|
||||
add(realPanel);
|
||||
|
||||
|
||||
reloadColor(Settings.getInstance().getTheme());
|
||||
}
|
||||
|
||||
@@ -396,11 +395,10 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
|
||||
public void reloadColor(Theme t) {
|
||||
if (isShowedMessage)
|
||||
return;
|
||||
for (Map.Entry<String, String> entry : t.settings.entrySet()) {
|
||||
for (Map.Entry<String, String> entry : t.settings.entrySet())
|
||||
if (entry.getValue().startsWith("#"))
|
||||
UIManager.put(entry.getKey(), GraphicsUtils.getWebColor(entry.getValue()));
|
||||
}
|
||||
|
||||
|
||||
initBorderColor();
|
||||
if (border != null)
|
||||
border.setColor(borderColor);
|
||||
@@ -423,14 +421,14 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
if (!enableShadow)
|
||||
int off = enableShadow ? 16 : 0;
|
||||
int width = this.getWidth();
|
||||
int height = this.getHeight();
|
||||
int contentWidth = width - off - off;
|
||||
int contentHeight = height - off - off;
|
||||
if (!enableShadow || contentWidth <= 0 || contentHeight <= 0)
|
||||
paintImpl(g);
|
||||
else {
|
||||
int off = enableShadow ? 16 : 0;
|
||||
int width = this.getWidth();
|
||||
int height = this.getHeight();
|
||||
int contentWidth = width - off - off;
|
||||
int contentHeight = height - off - off;
|
||||
BufferedImage contentImage = new BufferedImage(contentWidth,
|
||||
contentHeight, Transparency.OPAQUE);
|
||||
Graphics2D contentG2d = contentImage.createGraphics();
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
@@ -27,20 +24,15 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.jackhuang.hmcl.api.HMCLApi;
|
||||
import org.jackhuang.hmcl.api.HMCLog;
|
||||
import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent;
|
||||
import org.jackhuang.hmcl.api.func.Consumer;
|
||||
import org.jackhuang.hmcl.ui.LogWindow;
|
||||
import org.jackhuang.hmcl.util.log.Level;
|
||||
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -48,70 +40,28 @@ import org.xml.sax.helpers.XMLReaderFactory;
|
||||
*/
|
||||
public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedEvent> {
|
||||
|
||||
XMLReader reader;
|
||||
ProcessMonitor monitor;
|
||||
PipedInputStream inputStream;
|
||||
PipedOutputStream outputStream;
|
||||
List<Pair<String, String>> forbiddenTokens = new LinkedList<>();
|
||||
AtomicBoolean interrupted = new AtomicBoolean(false);
|
||||
ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
boolean enabled = true;
|
||||
|
||||
public Log4jHandler(ProcessMonitor monitor, PipedOutputStream outputStream, boolean enabled) throws ParserConfigurationException, IOException, SAXException {
|
||||
reader = XMLReaderFactory.createXMLReader();
|
||||
inputStream = new PipedInputStream(outputStream);
|
||||
this.outputStream = outputStream;
|
||||
public Log4jHandler(ProcessMonitor monitor, PipedOutputStream outputStream, boolean enabled) {
|
||||
this.monitor = monitor;
|
||||
this.enabled = enabled;
|
||||
|
||||
|
||||
HMCLApi.EVENT_BUS.channel(JavaProcessStoppedEvent.class).register((Consumer<JavaProcessStoppedEvent>) this);
|
||||
}
|
||||
|
||||
|
||||
public void addForbiddenToken(String token, String replacement) {
|
||||
forbiddenTokens.add(new Pair<>(token, replacement));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
setName("log4j-handler");
|
||||
if (enabled)
|
||||
newLogLine("<output>");
|
||||
reader.setContentHandler(new Log4jHandlerImpl());
|
||||
reader.parse(new InputSource(inputStream));
|
||||
} catch (InterruptedIOException e) {
|
||||
interrupted.set(true);
|
||||
} catch (SAXException | IOException e) {
|
||||
throw new Error(e);
|
||||
} finally {
|
||||
executorService.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JavaProcessStoppedEvent t) {
|
||||
if (!interrupted.get())
|
||||
return;
|
||||
if (t.getSource() == monitor) {
|
||||
try {
|
||||
executorService.submit(() -> {
|
||||
if (!interrupted.get()) {
|
||||
if (enabled) {
|
||||
Future f = newLogLine("</output>");
|
||||
if (f != null)
|
||||
f.get();
|
||||
}
|
||||
outputStream.close();
|
||||
join();
|
||||
}
|
||||
return null;
|
||||
}).get();
|
||||
} catch (Exception e) {
|
||||
HMCLog.err("Please contact author", e);
|
||||
} finally {
|
||||
executorService.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,32 +76,12 @@ public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedE
|
||||
* @param content The content to be written to the log
|
||||
*/
|
||||
public Future newLogLine(String content) {
|
||||
try {
|
||||
return executorService.submit(() -> {
|
||||
if (enabled)
|
||||
try {
|
||||
String log = content;
|
||||
if (!log.trim().startsWith("<")) { // without logging configuration.
|
||||
log = "<![CDATA[" + log.replace("]]>", "") + "]]>";
|
||||
}
|
||||
outputStream.write(log
|
||||
.replace("log4j:Event", "log4j_Event")
|
||||
.replace("log4j:Message", "log4j_Message")
|
||||
.replace("log4j:Throwable", "log4j_Throwable")
|
||||
.getBytes());
|
||||
outputStream.flush();
|
||||
} catch (IOException ignore) { // won't happen
|
||||
throw new Error(ignore);
|
||||
}
|
||||
else
|
||||
printlnImpl(content, Level.guessLevel(content));
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
return null;
|
||||
}
|
||||
printlnImpl(content, Level.guessLevel(content));
|
||||
return null;
|
||||
}
|
||||
|
||||
class Log4jHandlerImpl extends DefaultHandler {
|
||||
|
||||
private final SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
|
||||
|
||||
String date = "", thread = "", logger = "";
|
||||
@@ -168,7 +98,7 @@ public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedE
|
||||
date = df.format(d);
|
||||
try {
|
||||
l = Level.valueOf(attributes.getValue("level"));
|
||||
} catch(IllegalArgumentException e) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
l = Level.INFO;
|
||||
}
|
||||
thread = attributes.getValue("thread");
|
||||
@@ -197,7 +127,8 @@ public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedE
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
String line = new String(ch, start, length);
|
||||
if (line.trim().isEmpty()) return;
|
||||
if (line.trim().isEmpty())
|
||||
return;
|
||||
if (readingMessage)
|
||||
message.append(line).append(C.LINE_SEPARATOR);
|
||||
else
|
||||
@@ -208,7 +139,7 @@ public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedE
|
||||
printlnImpl(message, l);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void printlnImpl(String message, Level l) {
|
||||
for (Pair<String, String> entry : forbiddenTokens)
|
||||
message = message.replace(entry.key, entry.value);
|
||||
|
||||
@@ -88,8 +88,7 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
|
||||
if (jv == null || !jv.isEarlyAccess()) {
|
||||
if (jv != null && jv.getParsedVersion() >= JdkVersion.JAVA_17)
|
||||
res.add("-XX:+UseG1GC");
|
||||
else
|
||||
res.add("-Xincgc");
|
||||
|
||||
res.add("-XX:-UseAdaptiveSizePolicy");
|
||||
res.add("-XX:-OmitStackTraceInFastThrow");
|
||||
|
||||
|
||||
@@ -87,10 +87,10 @@ public final class StrUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean containsOne(List<String> base, List<String> match, Predicate<String> pred) {
|
||||
public static boolean containsOne(Collection<String> base, String... match) {
|
||||
for (String a : base)
|
||||
for (String b : match)
|
||||
if (pred.apply(a) && a.toLowerCase().contains(b.toLowerCase()))
|
||||
if (a.toLowerCase().contains(b.toLowerCase()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.hmcl.util.sys;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.jackhuang.hmcl.api.HMCLApi;
|
||||
import org.jackhuang.hmcl.api.IProcess;
|
||||
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
|
||||
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
|
||||
import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent;
|
||||
import org.jackhuang.hmcl.util.CollectionUtils;
|
||||
import org.jackhuang.hmcl.util.StrUtils;
|
||||
import org.jackhuang.hmcl.util.log.Level;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huang
|
||||
*/
|
||||
public class ExitWaiter extends Thread {
|
||||
|
||||
private final ProcessMonitor monitor;
|
||||
private final IProcess process;
|
||||
private final Runnable callback;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param monitor
|
||||
* @param callback nullable, will be called when process exited.
|
||||
*/
|
||||
public ExitWaiter(ProcessMonitor monitor, Runnable callback) {
|
||||
this.monitor = monitor;
|
||||
this.process = monitor.getProcess();
|
||||
this.callback = callback;
|
||||
|
||||
setName("exit-waitor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int exitCode = process.getRawProcess().waitFor();
|
||||
monitor.errorThread.join();
|
||||
monitor.inputThread.join();
|
||||
|
||||
Collection<String> errorLines = CollectionUtils.filter(process.getStdOutLines(), str -> Level.isError(Level.guessLevel(str)));
|
||||
|
||||
// LaunchWrapper will terminate the application with exit code 0, though this is error state.
|
||||
if (exitCode != 0 || StrUtils.containsOne(errorLines, "Unable to launch"))
|
||||
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(monitor, process));
|
||||
else if (exitCode != 0 && StrUtils.containsOne(errorLines,
|
||||
"Could not create the Java Virtual Machine.",
|
||||
"Error occurred during initialization of VM",
|
||||
"A fatal exception has occurred. Program will exit.",
|
||||
"Unable to launch"))
|
||||
HMCLApi.EVENT_BUS.fireChannel(new JVMLaunchFailedEvent(monitor, process));
|
||||
else
|
||||
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStoppedEvent(this, process));
|
||||
|
||||
if (callback != null)
|
||||
callback.run();
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,8 @@ public class Java {
|
||||
try {
|
||||
queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\");
|
||||
queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\");
|
||||
queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JRE\\");
|
||||
queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JDK\\");
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
HMCLog.err("Faield to query java", ex);
|
||||
}
|
||||
|
||||
@@ -17,19 +17,11 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.util.sys;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import org.jackhuang.hmcl.api.HMCLApi;
|
||||
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
|
||||
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
|
||||
import org.jackhuang.hmcl.api.event.process.JavaProcessStartingEvent;
|
||||
import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent;
|
||||
import org.jackhuang.hmcl.util.StrUtils;
|
||||
import org.jackhuang.hmcl.api.HMCLog;
|
||||
import org.jackhuang.hmcl.util.log.Level;
|
||||
import org.jackhuang.hmcl.api.IProcess;
|
||||
import org.jackhuang.hmcl.api.event.SimpleEvent;
|
||||
import org.jackhuang.hmcl.api.func.Consumer;
|
||||
|
||||
/**
|
||||
@@ -43,6 +35,7 @@ public class ProcessMonitor {
|
||||
private final CountDownLatch latch = new CountDownLatch(2);
|
||||
ProcessThread inputThread;
|
||||
ProcessThread errorThread;
|
||||
ExitWaiter waitorThread;
|
||||
WaitForThread waitForThread;
|
||||
private final IProcess p;
|
||||
|
||||
@@ -50,9 +43,7 @@ public class ProcessMonitor {
|
||||
this.p = p;
|
||||
inputThread = new ProcessThread(this, false);
|
||||
errorThread = new ProcessThread(this, true);
|
||||
inputThread.stopEvent.register(this::threadStopped);
|
||||
inputThread.stopEvent.register(event -> processThreadStopped((ProcessThread) event.getSource()));
|
||||
errorThread.stopEvent.register(this::threadStopped);
|
||||
waitorThread = new ExitWaiter(this, this::processThreadStopped);
|
||||
}
|
||||
|
||||
public IProcess getProcess() {
|
||||
@@ -75,51 +66,14 @@ public class ProcessMonitor {
|
||||
}
|
||||
|
||||
public void start() {
|
||||
hasFired = false;
|
||||
MONITORS.add(this);
|
||||
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStartingEvent(this, p));
|
||||
inputThread.start();
|
||||
errorThread.start();
|
||||
}
|
||||
|
||||
private void threadStopped(SimpleEvent<IProcess> event) {
|
||||
latch.countDown();
|
||||
ProcessThread t = (ProcessThread) event.getSource();
|
||||
int exitCode = Integer.MAX_VALUE;
|
||||
try {
|
||||
exitCode = p.getExitCode();
|
||||
} catch(IllegalThreadStateException e) {
|
||||
HMCLog.err("Failed to get exit code ", e);
|
||||
}
|
||||
if (p.getExitCode() != 0 || StrUtils.containsOne(t.getLines(),
|
||||
Arrays.asList("Unable to launch"), // LaunchWrapper will terminate the application returning exit code 0, but this is an error state.
|
||||
x -> Level.isError(Level.guessLevel(x))))
|
||||
synchronized (this) {
|
||||
if (!hasFired) {
|
||||
hasFired = true;
|
||||
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(ProcessMonitor.this, p));
|
||||
}
|
||||
}
|
||||
if (p.getExitCode() != 0 && StrUtils.containsOne(t.getLines(),
|
||||
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.isError(Level.guessLevel(x))))
|
||||
synchronized (this) {
|
||||
if (!hasFired) {
|
||||
hasFired = true;
|
||||
HMCLApi.EVENT_BUS.fireChannel(new JVMLaunchFailedEvent(ProcessMonitor.this, p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasFired = false;
|
||||
|
||||
private void processThreadStopped(ProcessThread t1) {
|
||||
private void processThreadStopped() {
|
||||
MONITORS.remove(this);
|
||||
errorThread.interrupt();
|
||||
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStoppedEvent(this, p));
|
||||
}
|
||||
|
||||
public static void stopAll() {
|
||||
@@ -127,6 +81,7 @@ public class ProcessMonitor {
|
||||
monitor.getProcess().getRawProcess().destroy();
|
||||
monitor.inputThread.interrupt();
|
||||
monitor.errorThread.interrupt();
|
||||
monitor.waitorThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https://services.gradle.org/distributions/gradle-4.2.1-bin.zip
|
||||
distributionUrl=https://services.gradle.org/distributions/gradle-4.3-bin.zip
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
rootProject.name = 'Hello Minecraft'
|
||||
rootProject.name = 'Hello_Minecraft'
|
||||
|
||||
// Find the directories containing a "build.gradle" file in the root directory
|
||||
// of the project. That is, every directory containing a "build.gradle" will
|
||||
|
||||
Reference in new issue
Block a user