From de2af506f35c415345189814a08f867a70f76a4b Mon Sep 17 00:00:00 2001 From: Minecrell Date: Fri, 9 Jun 2017 19:05:12 +0200 Subject: [PATCH] Improve console implementation Rewrite console improvements (console colors, tab completion, persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. New features: - Support console colors for Vanilla commands - Add console colors for warnings and errors - Server can now be turned off safely using CTRL + C. JLine catches the signal and the implementation shuts down the server cleanly. - Support console colors and persistent input line when running in IntelliJ IDEA Other changes: - Update JLine to 3.3.1 (from 2.12.1) - Server starts 1-2 seconds faster thanks to optimizations in Log4j configuration --- .gitignore | 4 +- ...-option-to-prevent-player-names-fro.patch} | 0 ...orkaround-for-jansi-bug-with-Windows.patch | 29 - ...oleAppender-for-console-improvements.patch | 614 ++++++++++++++++++ pom.xml | 5 + 5 files changed, 622 insertions(+), 30 deletions(-) rename Spigot-Server-Patches/{0212-Add-configuration-option-to-prevent-player-names-fro.patch => 0211-Add-configuration-option-to-prevent-player-names-fro.patch} (100%) delete mode 100644 Spigot-Server-Patches/0211-Workaround-for-jansi-bug-with-Windows.patch create mode 100644 Spigot-Server-Patches/0212-Use-TerminalConsoleAppender-for-console-improvements.patch diff --git a/.gitignore b/.gitignore index 321af62064..a8596ddd67 100644 --- a/.gitignore +++ b/.gitignore @@ -42,11 +42,13 @@ work/test-server *.ipr *.iws .idea/ +out/ # Linux temp files *~ # other stuff +run/ Paper-Server Paper-API @@ -55,4 +57,4 @@ PaperSpigot-API Paperclip.jar paperclip.jar paperclip-*.jar -paperclip.properties \ No newline at end of file +paperclip.properties diff --git a/Spigot-Server-Patches/0212-Add-configuration-option-to-prevent-player-names-fro.patch b/Spigot-Server-Patches/0211-Add-configuration-option-to-prevent-player-names-fro.patch similarity index 100% rename from Spigot-Server-Patches/0212-Add-configuration-option-to-prevent-player-names-fro.patch rename to Spigot-Server-Patches/0211-Add-configuration-option-to-prevent-player-names-fro.patch diff --git a/Spigot-Server-Patches/0211-Workaround-for-jansi-bug-with-Windows.patch b/Spigot-Server-Patches/0211-Workaround-for-jansi-bug-with-Windows.patch deleted file mode 100644 index 2fd2250eea..0000000000 --- a/Spigot-Server-Patches/0211-Workaround-for-jansi-bug-with-Windows.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 6e358e579628685730d344c55695e30694525cc0 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 17 May 2017 17:45:19 -0500 -Subject: [PATCH] Workaround for jansi bug with Windows - -When jansi attempts to extract its natives, by default it tries to extract a specific version -using the loading class's implementation version. Normally this works completely fine -however when on Windows certain characters such as - and : can trigger special behaviour. - -Furthermore this behaviour only occurs in specific combinations due to the parsing done by jansi. -For example test-test works fine, but test-test-test does not! In order to avoid this all together but -still keep our versions the same as they were, we set the override property to the essentially garbage version -Paper. This version is only used when extracting the libraries to their temp folder. - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 1cbcc3dfa..98e27fa25 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -182,6 +182,7 @@ public class Main { - } - - if (useJline) { -+ System.setProperty( "library.jansi.version", "Paper" ); // Paper - set jansi library version to avoid crash - AnsiConsole.systemInstall(); - } else { - // This ensures the terminal literal will always match the jline implementation --- -2.13.0.windows.1 - diff --git a/Spigot-Server-Patches/0212-Use-TerminalConsoleAppender-for-console-improvements.patch b/Spigot-Server-Patches/0212-Use-TerminalConsoleAppender-for-console-improvements.patch new file mode 100644 index 0000000000..5b28c22118 --- /dev/null +++ b/Spigot-Server-Patches/0212-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -0,0 +1,614 @@ +From 3d69c48006f75e45b053b2d626a1829f71d1a7d6 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Fri, 9 Jun 2017 19:03:43 +0200 +Subject: [PATCH] Use TerminalConsoleAppender for console improvements + +Rewrite console improvements (console colors, tab completion, +persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. + +New features: + - Support console colors for Vanilla commands + - Add console colors for warnings and errors + - Server can now be turned off safely using CTRL + C. JLine catches + the signal and the implementation shuts down the server cleanly. + - Support console colors and persistent input line when running in + IntelliJ IDEA + +Other changes: + - Update JLine to 3.3.1 (from 2.12.1) + - Server starts 1-2 seconds faster thanks to optimizations in Log4j + configuration + +diff --git a/pom.xml b/pom.xml +index b2aa10ff..0ae2c9c6 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -47,12 +47,6 @@ + compile + + +- jline +- jline +- 2.12.1 +- compile +- +- + org.xerial + sqlite-jdbc + 3.18.0 +@@ -69,6 +63,38 @@ + trove4j + 3.0.3 + ++ ++ ++ net.minecrell ++ terminalconsoleappender ++ 1.0.0-SNAPSHOT ++ ++ ++ org.jline ++ jline-terminal-jna ++ 3.3.1 ++ runtime ++ ++ ++ net.java.dev.jna ++ jna ++ 4.4.0 ++ runtime ++ ++ ++ ++ ++ org.apache.logging.log4j ++ log4j-core ++ 2.8.1 ++ runtime ++ ++ + + + junit +@@ -216,10 +242,18 @@ + + META-INF/services/java.sql.Driver + ++ + + + + ++ ++ ++ com.github.edwgiz ++ maven-shade-plugin.log4j2-cachefile-transformer ++ 2.8.1 ++ ++ + + + org.apache.maven.plugins +diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java +new file mode 100644 +index 00000000..24f30efb +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java +@@ -0,0 +1,13 @@ ++package com.destroystokyo.paper.console; ++ ++import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; ++ ++public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { ++ ++ @Override ++ public void sendRawMessage(String message) { ++ // Print message with colors ++ System.out.println(message); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalHandler.java b/src/main/java/com/destroystokyo/paper/console/TerminalHandler.java +new file mode 100644 +index 00000000..dcd31fbc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/console/TerminalHandler.java +@@ -0,0 +1,53 @@ ++package com.destroystokyo.paper.console; ++ ++import net.minecraft.server.DedicatedServer; ++import net.minecrell.terminalconsole.TerminalConsoleAppender; ++import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; ++import org.jline.reader.LineReader; ++import org.jline.reader.LineReaderBuilder; ++import org.jline.reader.UserInterruptException; ++import org.jline.terminal.Terminal; ++ ++public class TerminalHandler { ++ ++ private TerminalHandler() { ++ } ++ ++ public static boolean handleCommands(DedicatedServer server) { ++ final Terminal terminal = TerminalConsoleAppender.getTerminal(); ++ if (terminal == null) { ++ return false; ++ } ++ ++ LineReader reader = LineReaderBuilder.builder() ++ .appName("Paper") ++ .terminal(terminal) ++ .completer(new ConsoleCommandCompleter(server)) ++ .build(); ++ reader.unsetOpt(LineReader.Option.INSERT_TAB); ++ ++ TerminalConsoleAppender.setReader(reader); ++ ++ try { ++ String line; ++ while (!server.isStopped() && server.isRunning()) { ++ line = reader.readLine("> "); ++ if (line == null) { ++ break; ++ } ++ ++ line = line.trim(); ++ if (!line.isEmpty()) { ++ server.issueCommand(line, server); ++ } ++ } ++ } catch (UserInterruptException e) { ++ server.safeShutdown(); ++ } finally { ++ TerminalConsoleAppender.setReader(null); ++ } ++ ++ return true; ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java +index 2feeb855..db9ace0c 100644 +--- a/src/main/java/net/minecraft/server/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/DedicatedServer.java +@@ -73,7 +73,10 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + if (!org.bukkit.craftbukkit.Main.useConsole) { + return; + } +- jline.console.ConsoleReader bufferedreader = reader; ++ // Paper start - Use TerminalConsoleAppender implementation ++ if (com.destroystokyo.paper.console.TerminalHandler.handleCommands(DedicatedServer.this)) return; ++ BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); ++ // Paper end + // CraftBukkit end + + String s; +@@ -81,11 +84,17 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + try { + // CraftBukkit start - JLine disabling compatibility + while (!isStopped() && isRunning()) { ++ // Paper start - code is not used for jline ++ /* + if (org.bukkit.craftbukkit.Main.useJline) { + s = bufferedreader.readLine(">", null); + } else { + s = bufferedreader.readLine(); + } ++ */ ++ s = bufferedreader.readLine(); ++ // Paper end ++ + if (s != null && s.trim().length() > 0) { // Trim to filter lines which are just spaces + issueCommand(s, DedicatedServer.this); + } +@@ -113,8 +122,6 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + } + } + +- new Thread(new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader)).start(); +- + System.setOut(new PrintStream(new LoggerOutputStream(logger, Level.INFO), true)); + System.setErr(new PrintStream(new LoggerOutputStream(logger, Level.WARN), true)); + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index d84f59da..8ca8fdce 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -41,7 +41,6 @@ import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + // CraftBukkit start +-import jline.console.ConsoleReader; + import joptsimple.OptionSet; + import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.CraftServer; +@@ -114,7 +113,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs + public OptionSet options; + public org.bukkit.command.ConsoleCommandSender console; + public org.bukkit.command.RemoteConsoleCommandSender remoteConsole; +- public ConsoleReader reader; ++ //public ConsoleReader reader; // Paper + public static int currentTick = 0; // Paper - Further improve tick loop + public final Thread primaryThread; + public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); +@@ -140,7 +139,9 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs + this.dataConverterManager = dataconvertermanager; + // CraftBukkit start + this.options = options; ++ // Paper start - Handled by TerminalConsoleAppender + // Try to see if we're actually running in a terminal, disable jline if not ++ /* + if (System.console() == null && System.getProperty("jline.terminal") == null) { + System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); + Main.useJline = false; +@@ -161,6 +162,8 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs + LOGGER.warn((String) null, ex); + } + } ++ */ ++ // Paper end + Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this)); + + this.serverThread = primaryThread = new Thread(this, "Server thread"); // Moved from main +@@ -700,7 +703,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs + } finally { + // CraftBukkit start - Restore terminal to original settings + try { +- reader.getTerminal().restore(); ++ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender + } catch (Exception ignored) { + } + // CraftBukkit end +@@ -1226,7 +1229,8 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs + } + + public void sendMessage(IChatBaseComponent ichatbasecomponent) { +- MinecraftServer.LOGGER.info(ichatbasecomponent.toPlainText()); ++ // Paper - Log message with colors ++ MinecraftServer.LOGGER.info(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(ichatbasecomponent, net.minecraft.server.EnumChatFormat.WHITE)); + } + + public boolean a(int i, String s) { +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 0c328782..ed0a749e 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -76,8 +76,7 @@ public abstract class PlayerList { + + public PlayerList(MinecraftServer minecraftserver) { + this.cserver = minecraftserver.server = new CraftServer(minecraftserver, this); +- minecraftserver.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); +- minecraftserver.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(minecraftserver.server)); ++ minecraftserver.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper + // CraftBukkit end + + this.k = new GameProfileBanList(PlayerList.a); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 463f5890..df6a75b0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -127,7 +127,6 @@ import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; + import io.netty.handler.codec.base64.Base64; +-import jline.console.ConsoleReader; + import org.apache.commons.lang.StringUtils; + import org.bukkit.NamespacedKey; + import org.bukkit.craftbukkit.util.CraftNamespacedKey; +@@ -1088,9 +1087,13 @@ public final class CraftServer implements Server { + return logger; + } + ++ // Paper start - JLine update ++ /* + public ConsoleReader getReader() { + return console.reader; + } ++ */ ++ // Paper end + + @Override + public PluginCommand getPluginCommand(String name) { +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 1cbcc3df..c3b2413a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -14,7 +14,7 @@ import java.util.logging.Logger; + import joptsimple.OptionParser; + import joptsimple.OptionSet; + import net.minecraft.server.MinecraftServer; +-import org.fusesource.jansi.AnsiConsole; ++import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper + + public class Main { + public static boolean useJline = true; +@@ -170,6 +170,8 @@ public class Main { + } + + try { ++ // Paper start - Handled by TerminalConsoleAppender ++ /* + // This trick bypasses Maven Shade's clever rewriting of our getProperty call when using String literals + String jline_UnsupportedTerminal = new String(new char[] {'j','l','i','n','e','.','U','n','s','u','p','p','o','r','t','e','d','T','e','r','m','i','n','a','l'}); + String jline_terminal = new String(new char[] {'j','l','i','n','e','.','t','e','r','m','i','n','a','l'}); +@@ -187,10 +189,18 @@ public class Main { + // This ensures the terminal literal will always match the jline implementation + System.setProperty(jline.TerminalFactory.JLINE_TERMINAL, jline.UnsupportedTerminal.class.getName()); + } ++ */ + ++ if (options.has("nojline")) { ++ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); ++ useJline = false; ++ } ++ // Paper end + + if (options.has("noconsole")) { + useConsole = false; ++ useJline = false; // Paper ++ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper + } + + if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java +deleted file mode 100644 +index 26a2fb89..00000000 +--- a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java ++++ /dev/null +@@ -1,74 +0,0 @@ +-package org.bukkit.craftbukkit.command; +- +-import java.util.EnumMap; +-import java.util.Map; +- +-import org.fusesource.jansi.Ansi; +-import org.fusesource.jansi.Ansi.Attribute; +-import jline.Terminal; +- +-import org.bukkit.Bukkit; +-import org.bukkit.ChatColor; +-import org.bukkit.command.ConsoleCommandSender; +-import org.bukkit.craftbukkit.CraftServer; +- +-public class ColouredConsoleSender extends CraftConsoleCommandSender { +- private final Terminal terminal; +- private final Map replacements = new EnumMap(ChatColor.class); +- private final ChatColor[] colors = ChatColor.values(); +- +- protected ColouredConsoleSender() { +- super(); +- this.terminal = ((CraftServer) getServer()).getReader().getTerminal(); +- +- replacements.put(ChatColor.BLACK, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.BLACK).boldOff().toString()); +- replacements.put(ChatColor.DARK_BLUE, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.BLUE).boldOff().toString()); +- replacements.put(ChatColor.DARK_GREEN, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.GREEN).boldOff().toString()); +- replacements.put(ChatColor.DARK_AQUA, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.CYAN).boldOff().toString()); +- replacements.put(ChatColor.DARK_RED, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.RED).boldOff().toString()); +- replacements.put(ChatColor.DARK_PURPLE, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.MAGENTA).boldOff().toString()); +- replacements.put(ChatColor.GOLD, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.YELLOW).boldOff().toString()); +- replacements.put(ChatColor.GRAY, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.WHITE).boldOff().toString()); +- replacements.put(ChatColor.DARK_GRAY, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.BLACK).bold().toString()); +- replacements.put(ChatColor.BLUE, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.BLUE).bold().toString()); +- replacements.put(ChatColor.GREEN, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.GREEN).bold().toString()); +- replacements.put(ChatColor.AQUA, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.CYAN).bold().toString()); +- replacements.put(ChatColor.RED, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.RED).bold().toString()); +- replacements.put(ChatColor.LIGHT_PURPLE, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.MAGENTA).bold().toString()); +- replacements.put(ChatColor.YELLOW, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.YELLOW).bold().toString()); +- replacements.put(ChatColor.WHITE, Ansi.ansi().a(Attribute.RESET).fg(Ansi.Color.WHITE).bold().toString()); +- replacements.put(ChatColor.MAGIC, Ansi.ansi().a(Attribute.BLINK_SLOW).toString()); +- replacements.put(ChatColor.BOLD, Ansi.ansi().a(Attribute.UNDERLINE_DOUBLE).toString()); +- replacements.put(ChatColor.STRIKETHROUGH, Ansi.ansi().a(Attribute.STRIKETHROUGH_ON).toString()); +- replacements.put(ChatColor.UNDERLINE, Ansi.ansi().a(Attribute.UNDERLINE).toString()); +- replacements.put(ChatColor.ITALIC, Ansi.ansi().a(Attribute.ITALIC).toString()); +- replacements.put(ChatColor.RESET, Ansi.ansi().a(Attribute.RESET).toString()); +- } +- +- @Override +- public void sendMessage(String message) { +- if (terminal.isAnsiSupported()) { +- if (!conversationTracker.isConversingModaly()) { +- String result = message; +- for (ChatColor color : colors) { +- if (replacements.containsKey(color)) { +- result = result.replaceAll("(?i)" + color.toString(), replacements.get(color)); +- } else { +- result = result.replaceAll("(?i)" + color.toString(), ""); +- } +- } +- System.out.println(result + Ansi.ansi().reset().toString()); +- } +- } else { +- super.sendMessage(message); +- } +- } +- +- public static ConsoleCommandSender getInstance() { +- if (Bukkit.getConsoleSender() != null) { +- return Bukkit.getConsoleSender(); +- } else { +- return new ColouredConsoleSender(); +- } +- } +-} +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index 33e8ea02..1e3aae3b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -8,17 +8,27 @@ import java.util.logging.Level; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.util.Waitable; + +-import jline.console.completer.Completer; ++// Paper start - JLine update ++import net.minecraft.server.DedicatedServer; // Paper ++import org.jline.reader.Candidate; ++import org.jline.reader.Completer; ++import org.jline.reader.LineReader; ++import org.jline.reader.ParsedLine; ++// Paper end + import org.bukkit.event.server.TabCompleteEvent; + + public class ConsoleCommandCompleter implements Completer { +- private final CraftServer server; ++ private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer + +- public ConsoleCommandCompleter(CraftServer server) { ++ public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer + this.server = server; + } + +- public int complete(final String buffer, final int cursor, final List candidates) { ++ // Paper start - Change method signature for JLine update ++ public void complete(LineReader reader, ParsedLine line, List candidates) { ++ final CraftServer server = this.server.server; ++ final String buffer = line.line(); ++ // Paper end + Waitable> waitable = new Waitable>() { + @Override + protected List evaluate() { +@@ -30,25 +40,37 @@ public class ConsoleCommandCompleter implements Completer { + return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); + } + }; +- this.server.getServer().processQueue.add(waitable); ++ server.getServer().processQueue.add(waitable); // Paper - Remove "this." + try { + List offers = waitable.get(); + if (offers == null) { +- return cursor; ++ return; // Paper - Method returns void + } +- candidates.addAll(offers); + ++ // Paper start - JLine update ++ for (String completion : offers) { ++ if (completion.isEmpty()) { ++ continue; ++ } ++ ++ candidates.add(new Candidate(completion)); ++ } ++ // Paper end ++ ++ // Paper start - JLine handles cursor now ++ /* + final int lastSpace = buffer.lastIndexOf(' '); + if (lastSpace == -1) { + return cursor - buffer.length(); + } else { + return cursor - (buffer.length() - lastSpace - 1); + } ++ */ ++ // Paper end + } catch (ExecutionException e) { +- this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); ++ server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); // Paper - Remove "this." + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } +- return cursor; + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index ae3481ba..6a38025e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -18,7 +18,7 @@ public class ServerShutdownThread extends Thread { + ex.printStackTrace(); + } finally { + try { +- server.reader.getTerminal().restore(); ++ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender + } catch (Exception e) { + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java +deleted file mode 100644 +index b6409711..00000000 +--- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java ++++ /dev/null +@@ -1,54 +0,0 @@ +-package org.bukkit.craftbukkit.util; +- +-import java.io.IOException; +-import java.io.OutputStream; +-import java.util.logging.Level; +-import java.util.logging.Logger; +-import jline.console.ConsoleReader; +-import com.mojang.util.QueueLogAppender; +-import org.bukkit.craftbukkit.Main; +-import org.fusesource.jansi.Ansi; +-import org.fusesource.jansi.Ansi.Erase; +- +-public class TerminalConsoleWriterThread implements Runnable { +- final private ConsoleReader reader; +- final private OutputStream output; +- +- public TerminalConsoleWriterThread(OutputStream output, ConsoleReader reader) { +- this.output = output; +- this.reader = reader; +- } +- +- public void run() { +- String message; +- +- // Using name from log4j config in vanilla jar +- while (true) { +- message = QueueLogAppender.getNextLogEvent("TerminalConsole"); +- if (message == null) { +- continue; +- } +- +- try { +- if (Main.useJline) { +- reader.print(Ansi.ansi().eraseLine(Erase.ALL).toString() + ConsoleReader.RESET_LINE); +- reader.flush(); +- output.write(message.getBytes()); +- output.flush(); +- +- try { +- reader.drawLine(); +- } catch (Throwable ex) { +- reader.getCursorBuffer().clear(); +- } +- reader.flush(); +- } else { +- output.write(message.getBytes()); +- output.flush(); +- } +- } catch (IOException ex) { +- Logger.getLogger(TerminalConsoleWriterThread.class.getName()).log(Level.SEVERE, null, ex); +- } +- } +- } +-} +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 5cee8f00..f248d05f 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -1,12 +1,12 @@ + +- ++ + + +- +- +- ++ ++ ++ + +- ++ + + + +-- +2.13.1 + diff --git a/pom.xml b/pom.xml index 90d310c38a..d428c63b80 100644 --- a/pom.xml +++ b/pom.xml @@ -40,6 +40,11 @@ aikar http://ci.emc.gs/nexus/content/groups/aikar/ + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots +