mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-20 07:34:48 +01:00
SPIGOT-6705: Re-print tab completion "Display all" message in console, when another message is being logged
By: DerFrZocker <derrieple@gmail.com>
This commit is contained in:
parent
84d43ef379
commit
d54bcadd91
3 changed files with 85 additions and 13 deletions
|
@ -1,6 +1,6 @@
|
||||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
@@ -53,6 +53,16 @@
|
@@ -53,6 +53,18 @@
|
||||||
import net.minecraft.world.level.storage.Convertable;
|
import net.minecraft.world.level.storage.Convertable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
||||||
+import org.apache.logging.log4j.LogManager;
|
+import org.apache.logging.log4j.LogManager;
|
||||||
+import org.apache.logging.log4j.io.IoBuilder;
|
+import org.apache.logging.log4j.io.IoBuilder;
|
||||||
+import org.bukkit.command.CommandSender;
|
+import org.bukkit.command.CommandSender;
|
||||||
|
+import org.bukkit.craftbukkit.util.TerminalCompletionHandler;
|
||||||
|
+import org.bukkit.craftbukkit.util.TerminalConsoleWriterThread;
|
||||||
+import org.bukkit.event.server.ServerCommandEvent;
|
+import org.bukkit.event.server.ServerCommandEvent;
|
||||||
+import org.bukkit.event.server.RemoteServerCommandEvent;
|
+import org.bukkit.event.server.RemoteServerCommandEvent;
|
||||||
+// CraftBukkit end
|
+// CraftBukkit end
|
||||||
|
@ -17,7 +19,7 @@
|
||||||
public class DedicatedServer extends MinecraftServer implements IMinecraftServer {
|
public class DedicatedServer extends MinecraftServer implements IMinecraftServer {
|
||||||
|
|
||||||
static final Logger LOGGER = LogUtils.getLogger();
|
static final Logger LOGGER = LogUtils.getLogger();
|
||||||
@@ -61,7 +71,7 @@
|
@@ -61,7 +73,7 @@
|
||||||
private final List<ServerCommand> consoleInput = Collections.synchronizedList(Lists.newArrayList());
|
private final List<ServerCommand> consoleInput = Collections.synchronizedList(Lists.newArrayList());
|
||||||
@Nullable
|
@Nullable
|
||||||
private RemoteStatusListener queryThreadGs4;
|
private RemoteStatusListener queryThreadGs4;
|
||||||
|
@ -26,7 +28,7 @@
|
||||||
@Nullable
|
@Nullable
|
||||||
private RemoteControlListener rconThread;
|
private RemoteControlListener rconThread;
|
||||||
public DedicatedServerSettings settings;
|
public DedicatedServerSettings settings;
|
||||||
@@ -70,10 +80,12 @@
|
@@ -70,10 +82,12 @@
|
||||||
@Nullable
|
@Nullable
|
||||||
private final TextFilter textFilterClient;
|
private final TextFilter textFilterClient;
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@
|
||||||
this.textFilterClient = TextFilter.createFromConfig(dedicatedserversettings.getProperties().textFilteringConfig);
|
this.textFilterClient = TextFilter.createFromConfig(dedicatedserversettings.getProperties().textFilteringConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,13 +93,44 @@
|
@@ -81,13 +95,44 @@
|
||||||
public boolean initServer() throws IOException {
|
public boolean initServer() throws IOException {
|
||||||
Thread thread = new Thread("Server console handler") {
|
Thread thread = new Thread("Server console handler") {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -90,7 +92,7 @@
|
||||||
}
|
}
|
||||||
} catch (IOException ioexception) {
|
} catch (IOException ioexception) {
|
||||||
DedicatedServer.LOGGER.error("Exception handling console input", ioexception);
|
DedicatedServer.LOGGER.error("Exception handling console input", ioexception);
|
||||||
@@ -96,6 +139,27 @@
|
@@ -96,6 +141,29 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,7 +111,9 @@
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start();
|
+ TerminalConsoleWriterThread writerThread = new TerminalConsoleWriterThread(System.out, this.reader);
|
||||||
|
+ this.reader.setCompletionHandler(new TerminalCompletionHandler(writerThread, this.reader.getCompletionHandler()));
|
||||||
|
+ writerThread.start();
|
||||||
+
|
+
|
||||||
+ System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream());
|
+ System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream());
|
||||||
+ System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream());
|
+ System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream());
|
||||||
|
@ -118,7 +122,7 @@
|
||||||
thread.setDaemon(true);
|
thread.setDaemon(true);
|
||||||
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(DedicatedServer.LOGGER));
|
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(DedicatedServer.LOGGER));
|
||||||
thread.start();
|
thread.start();
|
||||||
@@ -120,7 +184,7 @@
|
@@ -120,7 +188,7 @@
|
||||||
this.setMotd(dedicatedserverproperties.motd);
|
this.setMotd(dedicatedserverproperties.motd);
|
||||||
super.setPlayerIdleTimeout((Integer) dedicatedserverproperties.playerIdleTimeout.get());
|
super.setPlayerIdleTimeout((Integer) dedicatedserverproperties.playerIdleTimeout.get());
|
||||||
this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist);
|
this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist);
|
||||||
|
@ -127,7 +131,7 @@
|
||||||
DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode);
|
DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode);
|
||||||
InetAddress inetaddress = null;
|
InetAddress inetaddress = null;
|
||||||
|
|
||||||
@@ -144,6 +208,12 @@
|
@@ -144,6 +212,12 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +144,7 @@
|
||||||
if (!this.usesAuthentication()) {
|
if (!this.usesAuthentication()) {
|
||||||
DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
|
DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
|
||||||
DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware.");
|
DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware.");
|
||||||
@@ -158,19 +228,19 @@
|
@@ -158,19 +232,19 @@
|
||||||
if (!NameReferencingFileConverter.serverReadyAfterUserconversion(this)) {
|
if (!NameReferencingFileConverter.serverReadyAfterUserconversion(this)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -163,7 +167,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dedicatedserverproperties.enableQuery) {
|
if (dedicatedserverproperties.enableQuery) {
|
||||||
@@ -296,6 +366,7 @@
|
@@ -296,6 +370,7 @@
|
||||||
this.queryThreadGs4.stop();
|
this.queryThreadGs4.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +175,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -317,7 +388,15 @@
|
@@ -317,7 +392,15 @@
|
||||||
while (!this.consoleInput.isEmpty()) {
|
while (!this.consoleInput.isEmpty()) {
|
||||||
ServerCommand servercommand = (ServerCommand) this.consoleInput.remove(0);
|
ServerCommand servercommand = (ServerCommand) this.consoleInput.remove(0);
|
||||||
|
|
||||||
|
@ -188,7 +192,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -544,16 +623,52 @@
|
@@ -544,16 +627,52 @@
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPluginNames() {
|
public String getPluginNames() {
|
||||||
|
@ -245,7 +249,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeUsingWhiteList(boolean flag) {
|
public void storeUsingWhiteList(boolean flag) {
|
||||||
@@ -604,4 +719,15 @@
|
@@ -604,4 +723,15 @@
|
||||||
public Optional<MinecraftServer.ServerResourcePackInfo> getServerResourcePack() {
|
public Optional<MinecraftServer.ServerResourcePackInfo> getServerResourcePack() {
|
||||||
return this.settings.getProperties().serverResourcePackInfo;
|
return this.settings.getProperties().serverResourcePackInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.bukkit.craftbukkit.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import jline.console.ConsoleReader;
|
||||||
|
import jline.console.completer.CompletionHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPIGOT-6705: Make sure we print the display line again on tab completion, so that the user does not get stuck on it
|
||||||
|
* e.g. The user needs to press y / n to continue
|
||||||
|
*/
|
||||||
|
public class TerminalCompletionHandler implements CompletionHandler {
|
||||||
|
|
||||||
|
private final TerminalConsoleWriterThread writerThread;
|
||||||
|
private final CompletionHandler delegate;
|
||||||
|
|
||||||
|
public TerminalCompletionHandler(TerminalConsoleWriterThread writerThread, CompletionHandler delegate) {
|
||||||
|
this.writerThread = writerThread;
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean complete(ConsoleReader reader, List<CharSequence> candidates, int position) throws IOException {
|
||||||
|
// First check normal list, so that we do not unnecessarily create a new HashSet if the not distinct list is already lower
|
||||||
|
if (candidates.size() <= reader.getAutoprintThreshold()) {
|
||||||
|
return delegate.complete(reader, candidates, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<CharSequence> distinct = new HashSet<>(candidates);
|
||||||
|
if (distinct.size() <= reader.getAutoprintThreshold()) {
|
||||||
|
return delegate.complete(reader, candidates, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
writerThread.setCompletion(distinct.size());
|
||||||
|
|
||||||
|
// FIXME: Potential concurrency issue, when terminal writer prints the display message before the delegate does it
|
||||||
|
// resulting in two display message being present, until a new message gets logged or the user presses y / n
|
||||||
|
// But the probability of this happening are probably lower than the effort needed to fix this
|
||||||
|
// And seeing the display message at all should be a higher priority than seeing it two times in rare cases.
|
||||||
|
boolean result = delegate.complete(reader, candidates, position);
|
||||||
|
|
||||||
|
writerThread.setCompletion(-1);
|
||||||
|
// draw line to prevent concurrency issue,
|
||||||
|
// where terminal write would print the display message between delegate#complete finished and the completion set back to -1
|
||||||
|
// Resulting in the display message being present even after pressing y / n
|
||||||
|
reader.drawLine();
|
||||||
|
reader.flush();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,16 +3,21 @@ package org.bukkit.craftbukkit.util;
|
||||||
import com.mojang.logging.LogQueues;
|
import com.mojang.logging.LogQueues;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import jline.console.ConsoleReader;
|
import jline.console.ConsoleReader;
|
||||||
|
import jline.console.completer.CandidateListCompletionHandler;
|
||||||
import org.bukkit.craftbukkit.Main;
|
import org.bukkit.craftbukkit.Main;
|
||||||
import org.fusesource.jansi.Ansi;
|
import org.fusesource.jansi.Ansi;
|
||||||
import org.fusesource.jansi.Ansi.Erase;
|
import org.fusesource.jansi.Ansi.Erase;
|
||||||
|
|
||||||
public class TerminalConsoleWriterThread extends Thread {
|
public class TerminalConsoleWriterThread extends Thread {
|
||||||
|
private final ResourceBundle bundle = ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName(), Locale.getDefault());
|
||||||
private final ConsoleReader reader;
|
private final ConsoleReader reader;
|
||||||
private final OutputStream output;
|
private final OutputStream output;
|
||||||
|
private volatile int completion = -1;
|
||||||
|
|
||||||
public TerminalConsoleWriterThread(OutputStream output, ConsoleReader reader) {
|
public TerminalConsoleWriterThread(OutputStream output, ConsoleReader reader) {
|
||||||
super("TerminalConsoleWriter");
|
super("TerminalConsoleWriter");
|
||||||
|
@ -45,6 +50,12 @@ public class TerminalConsoleWriterThread extends Thread {
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
reader.getCursorBuffer().clear();
|
reader.getCursorBuffer().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (completion > -1) {
|
||||||
|
// SPIGOT-6705: Make sure we print the display line again on tab completion, so that the user does not get stuck on it
|
||||||
|
reader.print(String.format(bundle.getString("DISPLAY_CANDIDATES"), completion));
|
||||||
|
}
|
||||||
|
|
||||||
reader.flush();
|
reader.flush();
|
||||||
} else {
|
} else {
|
||||||
output.write(message.getBytes());
|
output.write(message.getBytes());
|
||||||
|
@ -55,4 +66,8 @@ public class TerminalConsoleWriterThread extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setCompletion(int completion) {
|
||||||
|
this.completion = completion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue