Commit 050784df authored by Presiareen's avatar Presiareen Committed by GitHub
Browse files

improve server side command line input (#415)



* improve server side command line input

* prevent multiline logs from covering typed commands

* reduce text in console

* resolve conflicts caused by multilanguage
Co-authored-by: default avatarMagix <kobedo11@gmail.com>
parent c930c637
...@@ -64,6 +64,10 @@ dependencies { ...@@ -64,6 +64,10 @@ dependencies {
implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.2.9' implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.2.9'
implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9' implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9'
implementation group: 'org.jline', name: 'jline', version: '3.21.0'
implementation group: 'org.jline', name: 'jline-terminal-jna', version: '3.21.0'
implementation group: 'net.java.dev.jna', name: 'jna', version: '5.10.0'
implementation group: 'io.netty', name: 'netty-all', version: '4.1.71.Final' implementation group: 'io.netty', name: 'netty-all', version: '4.1.71.Final'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.8' implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.8'
......
package emu.grasscutter; package emu.grasscutter;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.InputStreamReader; import java.io.IOError;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Calendar; import java.util.Calendar;
...@@ -13,6 +12,12 @@ import emu.grasscutter.plugin.PluginManager; ...@@ -13,6 +12,12 @@ import emu.grasscutter.plugin.PluginManager;
import emu.grasscutter.plugin.api.ServerHook; import emu.grasscutter.plugin.api.ServerHook;
import emu.grasscutter.scripts.ScriptLoader; import emu.grasscutter.scripts.ScriptLoader;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import org.jline.reader.EndOfFileException;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.UserInterruptException;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.reflections.Reflections; import org.reflections.Reflections;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -30,6 +35,7 @@ import emu.grasscutter.utils.Crypto; ...@@ -30,6 +35,7 @@ import emu.grasscutter.utils.Crypto;
public final class Grasscutter { public final class Grasscutter {
private static final Logger log = (Logger) LoggerFactory.getLogger(Grasscutter.class); private static final Logger log = (Logger) LoggerFactory.getLogger(Grasscutter.class);
private static Config config; private static Config config;
private static LineReader consoleLineReader = null;
private static Language language; private static Language language;
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
...@@ -109,10 +115,11 @@ public final class Grasscutter { ...@@ -109,10 +115,11 @@ public final class Grasscutter {
// Enable all plugins. // Enable all plugins.
pluginManager.enablePlugins(); pluginManager.enablePlugins();
// Open console.
startConsole();
// Hook into shutdown event. // Hook into shutdown event.
Runtime.getRuntime().addShutdownHook(new Thread(Grasscutter::onShutdown)); Runtime.getRuntime().addShutdownHook(new Thread(Grasscutter::onShutdown));
// Open console.
startConsole();
} }
/** /**
...@@ -167,24 +174,41 @@ public final class Grasscutter { ...@@ -167,24 +174,41 @@ public final class Grasscutter {
} }
public static void startConsole() { public static void startConsole() {
String input; // Console should not start in dispatch only mode.
getLogger().info(language.Start_done);
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
while ((input = br.readLine()) != null) {
try {
if (getConfig().RunMode == ServerRunMode.DISPATCH_ONLY) { if (getConfig().RunMode == ServerRunMode.DISPATCH_ONLY) {
getLogger().error(language.Dispatch_mode_not_support_command); getLogger().info(language.Dispatch_mode_not_support_command);
return; return;
} }
getLogger().info(language.Start_done);
String input = null;
boolean isLastInterrupted = false;
while (true) {
try {
input = consoleLineReader.readLine("> ");
} catch (UserInterruptException e) {
if (!isLastInterrupted) {
isLastInterrupted = true;
Grasscutter.getLogger().info("Press Ctrl-C again to shutdown.");
continue;
} else {
Runtime.getRuntime().exit(0);
}
} catch (EndOfFileException e) {
Grasscutter.getLogger().info("EOF detected.");
continue;
} catch (IOError e) {
Grasscutter.getLogger().error("An IO error occurred.", e);
continue;
}
isLastInterrupted = false;
try {
CommandMap.getInstance().invoke(null, input); CommandMap.getInstance().invoke(null, input);
} catch (Exception e) { } catch (Exception e) {
Grasscutter.getLogger().error(language.Command_error, e); Grasscutter.getLogger().error(language.Command_error, e);
} }
} }
} catch (Exception e) {
Grasscutter.getLogger().error(language.Error, e);
}
} }
public static Config getConfig() { public static Config getConfig() {
...@@ -199,6 +223,26 @@ public final class Grasscutter { ...@@ -199,6 +223,26 @@ public final class Grasscutter {
return log; return log;
} }
public static LineReader getConsole() {
if (consoleLineReader == null) {
Terminal terminal = null;
try {
terminal = TerminalBuilder.builder().jna(true).build();
} catch (Exception e) {
try {
// Fallback to a dumb jline terminal.
terminal = TerminalBuilder.builder().dumb(true).build();
} catch (Exception ignored) {
// When dumb is true, build() never throws.
}
}
consoleLineReader = LineReaderBuilder.builder()
.terminal(terminal)
.build();
}
return consoleLineReader;
}
public static Gson getGsonFactory() { public static Gson getGsonFactory() {
return gson; return gson;
} }
......
package emu.grasscutter.utils;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import emu.grasscutter.Grasscutter;
import org.jline.reader.LineReader;
import java.util.Arrays;
public class JlineLogbackAppender extends ConsoleAppender<ILoggingEvent> {
@Override
protected void append(ILoggingEvent eventObject) {
if (!started) {
return;
}
Arrays.stream(
new String(encoder.encode(eventObject)).split("\n")
).forEach(Grasscutter.getConsole()::printAbove);
}
}
<Configuration> <Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="emu.grasscutter.utils.JlineLogbackAppender">
<encoder> <encoder>
<pattern>[%d{HH:mm:ss}] [%highlight(%level)] %msg%n</pattern> <pattern>[%d{HH:mm:ss}] [%highlight(%level)] %msg%n</pattern>
</encoder> </encoder>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment