Merge branch 'release/5.2.12'

This commit is contained in:
Gravita 2022-05-31 17:21:29 +07:00
commit 1e40ef94e4
11 changed files with 147 additions and 35 deletions

View file

@ -0,0 +1,43 @@
package pro.gravit.launchserver.command.basic;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.command.Command;
public class DebugCommand extends Command {
private transient Logger logger = LogManager.getLogger();
public DebugCommand(LaunchServer server) {
super(server);
}
@Override
public String getArgsDescription() {
return "[true/false]";
}
@Override
public String getUsageDescription() {
return "Enable log level TRACE in LaunchServer";
}
@Override
public void invoke(String... args) throws Exception {
verifyArgs(args, 1);
boolean value = Boolean.parseBoolean(args[0]);
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig("pro.gravit");
loggerConfig.setLevel(value ? Level.TRACE : Level.DEBUG);
ctx.updateLoggers();
if(value) {
logger.info("Log level TRACE enabled");
} else {
logger.info("Log level TRACE disabled");
}
}
}

View file

@ -1,17 +1,13 @@
package pro.gravit.launchserver.command.handler; package pro.gravit.launchserver.command.handler;
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.command.basic.BuildCommand; import pro.gravit.launchserver.command.basic.*;
import pro.gravit.launchserver.command.basic.RestartCommand;
import pro.gravit.launchserver.command.basic.StopCommand;
import pro.gravit.launchserver.command.basic.VersionCommand;
import pro.gravit.launchserver.command.hash.*; import pro.gravit.launchserver.command.hash.*;
import pro.gravit.launchserver.command.modules.LoadModuleCommand; import pro.gravit.launchserver.command.modules.LoadModuleCommand;
import pro.gravit.launchserver.command.modules.ModulesCommand; import pro.gravit.launchserver.command.modules.ModulesCommand;
import pro.gravit.launchserver.command.service.*; import pro.gravit.launchserver.command.service.*;
import pro.gravit.utils.command.BaseCommandCategory; import pro.gravit.utils.command.BaseCommandCategory;
import pro.gravit.utils.command.basic.ClearCommand; import pro.gravit.utils.command.basic.ClearCommand;
import pro.gravit.utils.command.basic.DebugCommand;
import pro.gravit.utils.command.basic.GCCommand; import pro.gravit.utils.command.basic.GCCommand;
import pro.gravit.utils.command.basic.HelpCommand; import pro.gravit.utils.command.basic.HelpCommand;
@ -25,7 +21,7 @@ public static void registerCommands(pro.gravit.utils.command.CommandHandler hand
basic.registerCommand("build", new BuildCommand(server)); basic.registerCommand("build", new BuildCommand(server));
basic.registerCommand("stop", new StopCommand(server)); basic.registerCommand("stop", new StopCommand(server));
basic.registerCommand("restart", new RestartCommand(server)); basic.registerCommand("restart", new RestartCommand(server));
basic.registerCommand("debug", new DebugCommand()); basic.registerCommand("debug", new DebugCommand(server));
basic.registerCommand("clear", new ClearCommand(handler)); basic.registerCommand("clear", new ClearCommand(handler));
basic.registerCommand("gc", new GCCommand()); basic.registerCommand("gc", new GCCommand());
basic.registerCommand("loadModule", new LoadModuleCommand(server)); basic.registerCommand("loadModule", new LoadModuleCommand(server));

View file

@ -98,20 +98,24 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
optionals.add(optionalOther); optionals.add(optionalOther);
} }
Optional<MakeProfileOptionLog4j> logFile = findOption(options, MakeProfileOptionLog4j.class); Optional<MakeProfileOptionLog4j> logFile = findOption(options, MakeProfileOptionLog4j.class);
if(logFile.isPresent()) { if (logFile.isPresent()) {
var log4jOption = logFile.get(); var log4jOption = logFile.get();
if(log4jOption.logFile != null) { if (log4jOption.logFile != null) {
jvmArgs.add("-Dlog4j.configurationFile=".concat(logFile.get().logFile)); jvmArgs.add("-Dlog4j.configurationFile=".concat(logFile.get().logFile));
} else if(log4jOption.affected) { } else if (log4jOption.affected) {
if(version.compareTo(ClientProfile.Version.MC117) >= 0 && version.compareTo(ClientProfile.Version.MC118) < 0) { if (version.compareTo(ClientProfile.Version.MC117) >= 0 && version.compareTo(ClientProfile.Version.MC118) < 0) {
jvmArgs.add("-Dlog4j2.formatMsgNoLookups=true"); jvmArgs.add("-Dlog4j2.formatMsgNoLookups=true");
} }
} }
} }
if (version.compareTo(ClientProfile.Version.MC117) >= 0) { if (version.compareTo(ClientProfile.Version.MC117) >= 0 && version.compareTo(ClientProfile.Version.MC118) < 0) {
builder.setMinJavaVersion(16); builder.setMinJavaVersion(16);
builder.setRecommendJavaVersion(16); builder.setRecommendJavaVersion(16);
} }
if (version.compareTo(ClientProfile.Version.MC118) >= 0) {
builder.setMinJavaVersion(17);
builder.setRecommendJavaVersion(17);
}
jvmArgs.add("-Dfml.ignorePatchDiscrepancies=true"); jvmArgs.add("-Dfml.ignorePatchDiscrepancies=true");
jvmArgs.add("-Dfml.ignoreInvalidMinecraftCertificates=true"); jvmArgs.add("-Dfml.ignoreInvalidMinecraftCertificates=true");
builder.setJvmArgs(jvmArgs); builder.setJvmArgs(jvmArgs);
@ -168,20 +172,20 @@ public static String getMainClassByVersion(ClientProfile.Version version, MakePr
} }
private static boolean isAffectedLog4jVersion(String version) { private static boolean isAffectedLog4jVersion(String version) {
if(version == null) { if (version == null) {
return true; return true;
} }
String[] split = version.split("\\."); String[] split = version.split("\\.");
if(split.length < 2) return true; if (split.length < 2) return true;
if(!split[0].equals("2")) return false; if (!split[0].equals("2")) return false;
return Integer.parseInt(split[1]) < 15; return Integer.parseInt(split[1]) < 15;
} }
private static String getLog4jVersion(Path dir) throws IOException { private static String getLog4jVersion(Path dir) throws IOException {
Path log4jCore = dir.resolve("org/apache/logging/log4j/log4j-core"); Path log4jCore = dir.resolve("org/apache/logging/log4j/log4j-core");
if(Files.exists(log4jCore)) { if (Files.exists(log4jCore)) {
Path target = Files.list(log4jCore).findFirst().orElse(null); Path target = Files.list(log4jCore).findFirst().orElse(null);
if(target != null) { if (target != null) {
return target.getFileName().toString(); return target.getFileName().toString();
} }
} }
@ -192,9 +196,8 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP
List<MakeProfileOption> options = new ArrayList<>(2); List<MakeProfileOption> options = new ArrayList<>(2);
if (Files.exists(dir.resolve("forge.jar"))) { if (Files.exists(dir.resolve("forge.jar"))) {
options.add(new MakeProfileOptionForge()); options.add(new MakeProfileOptionForge());
} } else if (Files.exists(dir.resolve("libraries/net/minecraftforge/forge"))) {
else if (Files.exists(dir.resolve("libraries/net/minecraftforge/forge"))) { if (version.compareTo(ClientProfile.Version.MC1122) > 0) {
if(version.compareTo(ClientProfile.Version.MC1122) > 0) {
options.add(new MakeProfileOptionForge(dir)); options.add(new MakeProfileOptionForge(dir));
} else { } else {
options.add(new MakeProfileOptionForge()); options.add(new MakeProfileOptionForge());
@ -205,10 +208,10 @@ else if (Files.exists(dir.resolve("libraries/net/minecraftforge/forge"))) {
} }
{ {
String log4jVersion = getLog4jVersion(dir); String log4jVersion = getLog4jVersion(dir);
if(log4jVersion != null) { if (log4jVersion != null) {
boolean affected = isAffectedLog4jVersion(log4jVersion); boolean affected = isAffectedLog4jVersion(log4jVersion);
if(Files.exists(dir.resolve("log4j2_custom.xml"))) { if (Files.exists(dir.resolve("log4j2_custom.xml"))) {
options.add(new MakeProfileOptionLog4j(affected, "log4j2_custom.xml")); options.add(new MakeProfileOptionLog4j(affected, "log4j2_custom.xml"));
} else { } else {
options.add(new MakeProfileOptionLog4j(affected, null)); options.add(new MakeProfileOptionLog4j(affected, null));

View file

@ -173,31 +173,71 @@ public void registerClient(Channel channel) {
channels.add(channel); channels.add(channel);
} }
public static String getIPFromContext(ChannelHandlerContext ctx) {
var handler = ctx.pipeline().get(WebSocketFrameHandler.class);
if(handler == null || handler.context == null || handler.context.ip == null) {
return IOHelper.getIP(ctx.channel().remoteAddress());
}
return handler.context.ip;
}
public static String getIPFromChannel(Channel channel) {
var handler = channel.pipeline().get(WebSocketFrameHandler.class);
if(handler == null || handler.context == null || handler.context.ip == null) {
return IOHelper.getIP(channel.remoteAddress());
}
return handler.context.ip;
}
public void sendObject(ChannelHandlerContext ctx, Object obj) { public void sendObject(ChannelHandlerContext ctx, Object obj) {
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)), ctx.voidPromise()); String msg = gson.toJson(obj, WebSocketEvent.class);
if(logger.isTraceEnabled()) {
logger.trace("Send to {}: {}", getIPFromContext(ctx), msg);
}
ctx.writeAndFlush(new TextWebSocketFrame(msg), ctx.voidPromise());
} }
public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) { public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)), ctx.voidPromise()); String msg = gson.toJson(obj, type);
if(logger.isTraceEnabled()) {
logger.trace("Send to {}: {}", getIPFromContext(ctx), msg);
}
ctx.writeAndFlush(new TextWebSocketFrame(msg), ctx.voidPromise());
} }
public void sendObject(Channel channel, Object obj) { public void sendObject(Channel channel, Object obj) {
channel.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)), channel.voidPromise()); String msg = gson.toJson(obj, WebSocketEvent.class);
if(logger.isTraceEnabled()) {
logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg);
}
channel.writeAndFlush(new TextWebSocketFrame(msg), channel.voidPromise());
} }
public void sendObject(Channel channel, Object obj, Type type) { public void sendObject(Channel channel, Object obj, Type type) {
channel.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)), channel.voidPromise()); String msg = gson.toJson(obj, type);
if(logger.isTraceEnabled()) {
logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg);
}
channel.writeAndFlush(new TextWebSocketFrame(msg), channel.voidPromise());
} }
public void sendObjectAll(Object obj) { public void sendObjectAll(Object obj) {
String msg = gson.toJson(obj, WebSocketEvent.class);
if(logger.isTraceEnabled()) {
logger.trace("Send to all: {}", msg);
}
for (Channel ch : channels) { for (Channel ch : channels) {
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)), ch.voidPromise()); ch.writeAndFlush(new TextWebSocketFrame(msg), ch.voidPromise());
} }
} }
public void sendObjectAll(Object obj, Type type) { public void sendObjectAll(Object obj, Type type) {
String msg = gson.toJson(obj, type);
if(logger.isTraceEnabled()) {
logger.trace("Send to all: {}", msg);
}
for (Channel ch : channels) { for (Channel ch : channels) {
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)), ch.voidPromise()); ch.writeAndFlush(new TextWebSocketFrame(msg), ch.voidPromise());
} }
} }
@ -208,7 +248,11 @@ public void sendObjectToUUID(UUID userUuid, Object obj, Type type) {
if (wsHandler == null) continue; if (wsHandler == null) continue;
Client client = wsHandler.getClient(); Client client = wsHandler.getClient();
if (client == null || !userUuid.equals(client.uuid)) continue; if (client == null || !userUuid.equals(client.uuid)) continue;
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)), ch.voidPromise()); String msg = gson.toJson(obj, type);
if(logger.isTraceEnabled()) {
logger.trace("Send to {}({}): {}", getIPFromChannel(ch), userUuid, msg);
}
ch.writeAndFlush(new TextWebSocketFrame(msg), ch.voidPromise());
} }
} }
@ -272,15 +316,28 @@ public boolean kickByIP(String ip, boolean isClose) {
} }
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) { public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) {
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class))).addListener(ChannelFutureListener.CLOSE); String msg = gson.toJson(obj, WebSocketEvent.class);
if(logger.isTraceEnabled()) {
logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg);
}
ctx.writeAndFlush(new TextWebSocketFrame(msg)).addListener(ChannelFutureListener.CLOSE);
} }
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type) { public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type) {
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type))).addListener(ChannelFutureListener.CLOSE); String msg = gson.toJson(obj, type);
if(logger.isTraceEnabled()) {
logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg);
}
ctx.writeAndFlush(new TextWebSocketFrame(msg)).addListener(ChannelFutureListener.CLOSE);
} }
@Deprecated
public void sendEvent(EventResult obj) { public void sendEvent(EventResult obj) {
channels.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj)), ChannelMatchers.all(), true); String msg = gson.toJson(obj, WebSocketEvent.class);
if(logger.isTraceEnabled()) {
logger.trace("Send event: {}", msg);
}
channels.writeAndFlush(new TextWebSocketFrame(msg), ChannelMatchers.all(), true);
} }
public static class WebSocketRequestContext { public static class WebSocketRequestContext {

View file

@ -64,6 +64,9 @@ protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
logger.error("WebSocket frame handler hook error", ex); logger.error("WebSocket frame handler hook error", ex);
} }
if (frame instanceof TextWebSocketFrame) { if (frame instanceof TextWebSocketFrame) {
if(logger.isTraceEnabled()) {
logger.trace("Message from {}: {}", context.ip == null ? IOHelper.getIP(ctx.channel().remoteAddress()) : context.ip, ((TextWebSocketFrame) frame).text());
}
try { try {
service.process(ctx, (TextWebSocketFrame) frame, client, context.ip); service.process(ctx, (TextWebSocketFrame) frame, client, context.ip);
} catch (Throwable ex) { } catch (Throwable ex) {

View file

@ -6,7 +6,7 @@ public final class Version implements Comparable<Version> {
public static final int MAJOR = 5; public static final int MAJOR = 5;
public static final int MINOR = 2; public static final int MINOR = 2;
public static final int PATCH = 11; public static final int PATCH = 12;
public static final int BUILD = 1; public static final int BUILD = 1;
public static final Version.Type RELEASE = Type.STABLE; public static final Version.Type RELEASE = Type.STABLE;
public final int major; public final int major;

View file

@ -77,6 +77,9 @@ public void complete(LineReader reader, ParsedLine line, List<Candidate> candida
}); });
} else { } else {
Command target = findCommand(line.words().get(0)); Command target = findCommand(line.words().get(0));
if(target == null) {
return;
}
List<String> words = line.words(); List<String> words = line.words();
List<Candidate> candidates1 = target.complete(words.subList(1, words.size()), line.wordIndex() - 1, completeWord); List<Candidate> candidates1 = target.complete(words.subList(1, words.size()), line.wordIndex() - 1, completeWord);
candidates.addAll(candidates1); candidates.addAll(candidates1);

View file

@ -156,7 +156,9 @@ public void run(String... args) throws Throwable {
LogHelper.info("ServerWrapper: LaunchServer address: %s. Title: %s", config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown"); LogHelper.info("ServerWrapper: LaunchServer address: %s. Title: %s", config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown");
LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name); LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
String[] real_args; String[] real_args;
if (args.length > 0) { if(config.args != null && config.args.size() > 0) {
real_args = config.args.toArray(new String[0]);
} else if (args.length > 0) {
real_args = new String[args.length - 1]; real_args = new String[args.length - 1];
System.arraycopy(args, 1, real_args, 0, args.length - 1); System.arraycopy(args, 1, real_args, 0, args.length - 1);
} else real_args = args; } else real_args = args;

View file

@ -134,5 +134,10 @@ public void run() throws Exception {
writer.append(ServerWrapper.class.getName()); writer.append(ServerWrapper.class.getName());
writer.append("\n"); writer.append("\n");
} }
if(JVMHelper.OS_TYPE != JVMHelper.OS.MUSTDIE) {
if(!startScript.toFile().setExecutable(true)) {
LogHelper.error("Failed to set executable %s", startScript);
}
}
} }
} }

View file

@ -5,7 +5,7 @@
id 'org.openjfx.javafxplugin' version '0.0.10' apply false id 'org.openjfx.javafxplugin' version '0.0.10' apply false
} }
group = 'pro.gravit.launcher' group = 'pro.gravit.launcher'
version = '5.2.11' version = '5.2.12'
apply from: 'props.gradle' apply from: 'props.gradle'

@ -1 +1 @@
Subproject commit 56ad1f1d6a9d72e17f8283b077a9b4b53bfc5eb0 Subproject commit 48dad65be0f613fa1a6ae544ec892592d537bcc1