diff --git a/build.gradle b/build.gradle index d2e20e2..59f6af0 100644 --- a/build.gradle +++ b/build.gradle @@ -71,7 +71,7 @@ repositories { dependencies { compileOnly sourceSets.java17compat.output - include "com.viaversion:viaversion:4.7.0-1.20-pre4-SNAPSHOT" + include "com.viaversion:viaversion:4.7.0-1.20-pre5-SNAPSHOT" include("com.viaversion:viabackwards-common:4.7.0-1.20-pre3-SNAPSHOT") { exclude group: "com.viaversion", module: "viaversion" exclude group: "io.netty", module: "netty-all" diff --git a/src/main/java/net/raphimc/viaproxy/cli/ConsoleHandler.java b/src/main/java/net/raphimc/viaproxy/cli/ConsoleHandler.java index 83fb0f4..b235b23 100644 --- a/src/main/java/net/raphimc/viaproxy/cli/ConsoleHandler.java +++ b/src/main/java/net/raphimc/viaproxy/cli/ConsoleHandler.java @@ -19,13 +19,15 @@ package net.raphimc.viaproxy.cli; import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.connection.UserConnectionImpl; +import net.lenni0451.classtransform.utils.log.Logger; import net.raphimc.viaprotocolhack.commands.UserCommandSender; import net.raphimc.viaproxy.plugins.PluginManager; import net.raphimc.viaproxy.plugins.events.ConsoleCommandEvent; import net.raphimc.viaproxy.util.ArrayHelper; +import java.io.BufferedReader; +import java.io.InputStreamReader; import java.util.Arrays; -import java.util.Scanner; public class ConsoleHandler { @@ -34,32 +36,40 @@ public class ConsoleHandler { } private static void listen() { - final Scanner scanner = new Scanner(System.in); - while (scanner.hasNextLine()) { - final String line = scanner.nextLine(); - final String[] parts = line.split(" "); - if (parts.length == 0) continue; - final String command = parts[0]; - final ArrayHelper args = new ArrayHelper(Arrays.copyOfRange(parts, 1, parts.length)); + final BufferedReader reader = new BufferedReader(new InputStreamReader(new DelayedStream(System.in, 500))); + try { + String line; + while ((line = reader.readLine()) != null) { + try { + final String[] parts = line.split(" "); + if (parts.length == 0) continue; + final String command = parts[0]; + final ArrayHelper args = new ArrayHelper(Arrays.copyOfRange(parts, 1, parts.length)); - if (command.equalsIgnoreCase("gc")) { - System.gc(); - System.out.println("GC Done"); - } else if (command.equalsIgnoreCase("via")) { - Via.getManager().getCommandHandler().onCommand(new UserCommandSender(new UserConnectionImpl(null, true)), args.getAsArray()); - } else if (command.equalsIgnoreCase("threaddump")) { - System.out.println("Thread Dump:"); - for (Thread thread : Thread.getAllStackTraces().keySet()) { - System.out.println("Thread: " + thread.getName() + " | State: " + thread.getState()); - for (StackTraceElement element : thread.getStackTrace()) System.out.println(" " + element.toString()); + if (command.equalsIgnoreCase("gc")) { + System.gc(); + System.out.println("GC Done"); + } else if (command.equalsIgnoreCase("via")) { + Via.getManager().getCommandHandler().onCommand(new UserCommandSender(new UserConnectionImpl(null, true)), args.getAsArray()); + } else if (command.equalsIgnoreCase("threaddump")) { + System.out.println("Thread Dump:"); + for (Thread thread : Thread.getAllStackTraces().keySet()) { + System.out.println("Thread: " + thread.getName() + " | State: " + thread.getState()); + for (StackTraceElement element : thread.getStackTrace()) System.out.println(" " + element.toString()); + } + } else { + if (PluginManager.EVENT_MANAGER.call(new ConsoleCommandEvent(command, args.getAsArray())).isCancelled()) continue; + System.out.println("Invalid Command!"); + System.out.println(" via | Run a viaversion command"); + System.out.println(" gc | Run the garbage collector"); + System.out.println(" threaddump | Print the stacktrace of all running threads"); + } + } catch (Throwable e) { + Logger.LOGGER.error("Error while handling console input", e); } - } else { - if (PluginManager.EVENT_MANAGER.call(new ConsoleCommandEvent(command, args.getAsArray())).isCancelled()) continue; - System.out.println("Invalid Command!"); - System.out.println(" via | Run a viaversion command"); - System.out.println(" gc | Run the garbage collector"); - System.out.println(" threaddump | Print the stacktrace of all running threads"); } + } catch (Throwable e) { + Logger.LOGGER.error("Error while reading console input", e); } } diff --git a/src/main/java/net/raphimc/viaproxy/cli/DelayedStream.java b/src/main/java/net/raphimc/viaproxy/cli/DelayedStream.java new file mode 100644 index 0000000..a7d1386 --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/cli/DelayedStream.java @@ -0,0 +1,94 @@ +/* + * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy + * Copyright (C) 2023 RK_01/RaphiMC and contributors + * + * 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 . + */ +package net.raphimc.viaproxy.cli; + +import java.io.IOException; +import java.io.InputStream; + +public class DelayedStream extends InputStream { + + private final InputStream parent; + private final long sleepDelay; + + public DelayedStream(final InputStream parent, final long sleepDelay) { + this.parent = parent; + this.sleepDelay = sleepDelay; + } + + public InputStream getParent() { + return this.parent; + } + + public long getSleepDelay() { + return this.sleepDelay; + } + + public void waitForInput() throws IOException { + while (this.available() <= 0) { + try { + Thread.sleep(this.sleepDelay); + } catch (InterruptedException e) { + throw new IOException("Interrupted", e); + } + } + } + + @Override + public int read() throws IOException { + this.waitForInput(); + return this.parent.read(); + } + + @Override + public int read(byte[] b) throws IOException { + this.waitForInput(); + return this.parent.read(b); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + this.waitForInput(); + return this.parent.read(b, off, len); + } + + @Override + public int available() throws IOException { + return this.parent.available(); + } + + @Override + public void close() throws IOException { + this.parent.close(); + } + + @Override + public synchronized void mark(int readlimit) { + this.parent.mark(readlimit); + } + + @Override + public synchronized void reset() throws IOException { + this.parent.reset(); + } + + @Override + public boolean markSupported() { + return this.parent.markSupported(); + } + +}