diff --git a/api/src/main/java/com/velocitypowered/api/command/CommandManager.java b/api/src/main/java/com/velocitypowered/api/command/CommandManager.java index ce3452e40..af200cb74 100644 --- a/api/src/main/java/com/velocitypowered/api/command/CommandManager.java +++ b/api/src/main/java/com/velocitypowered/api/command/CommandManager.java @@ -1,5 +1,7 @@ package com.velocitypowered.api.command; +import java.util.concurrent.CompletableFuture; + /** * Represents an interface to register a command executor with the proxy. */ @@ -34,8 +36,8 @@ public interface CommandManager { void unregister(String alias); /** - * Attempts to execute a command from the specified {@code cmdLine}. - * CommandExecuteEvent will not called + * Calls CommandExecuteEvent and attempts to execute a command from the specified {@code cmdLine} + * sync. * * @param source the command's source * @param cmdLine the command to run @@ -44,12 +46,32 @@ public interface CommandManager { boolean execute(CommandSource source, String cmdLine); /** - * Attempts to execute a command from the specified {@code cmdLine}. + * Attempts to execute a command from the specified {@code cmdLine} sync + * without calling CommandExecuteEvent. * * @param source the command's source * @param cmdLine the command to run - * @param callEvent will CommandExecuteEvent called or not * @return true if the command was found and executed, false if it was not */ - boolean execute(CommandSource source, String cmdLine, boolean callEvent); + boolean executeImmediately(CommandSource source, String cmdLine); + + /** + * Calls CommandExecuteEvent and attempts to execute a command from the specified {@code cmdLine} + * async. + * + * @param source the command's source + * @param cmdLine the command to run + * @return A future that will be completed with the result of the command execution + */ + CompletableFuture executeAsync(CommandSource source, String cmdLine); + + /** + * Attempts to execute a command from the specified {@code cmdLine} async + * without calling CommandExecuteEvent. + * + * @param source the command's source + * @param cmdLine the command to run + * @return A future that will be completed with the result of the command execution + */ + CompletableFuture executeImmediatelyAsync(CommandSource source, String cmdLine); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java index 93caa314b..3a8a53201 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java @@ -7,9 +7,9 @@ import com.velocitypowered.api.command.Command; import com.velocitypowered.api.command.CommandManager; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.RawCommand; -import com.velocitypowered.api.event.EventManager; import com.velocitypowered.api.event.command.CommandExecuteEvent; import com.velocitypowered.api.event.command.CommandExecuteEvent.CommandResult; +import com.velocitypowered.proxy.plugin.VelocityEventManager; import java.util.Arrays; import java.util.HashMap; @@ -22,9 +22,9 @@ import java.util.concurrent.CompletableFuture; public class VelocityCommandManager implements CommandManager { private final Map commands = new HashMap<>(); - private final EventManager eventManager; + private final VelocityEventManager eventManager; - public VelocityCommandManager(EventManager eventManager) { + public VelocityCommandManager(VelocityEventManager eventManager) { this.eventManager = eventManager; } @@ -74,22 +74,21 @@ public class VelocityCommandManager implements CommandManager { Preconditions.checkNotNull(source, "invoker"); Preconditions.checkNotNull(cmdLine, "cmdLine"); - return execute(source, cmdLine, false); + CommandExecuteEvent event = callCommandEvent(source, cmdLine).join(); + CommandResult commandResult = event.getResult(); + if (commandResult.isForwardToServer() || !commandResult.isAllowed()) { + return false; + } + cmdLine = commandResult.getCommand().orElse(event.getCommand()); + + return executeImmediately(source, cmdLine); } @Override - public boolean execute(CommandSource source, String cmdLine, boolean callEvent) { + public boolean executeImmediately(CommandSource source, String cmdLine) { Preconditions.checkNotNull(source, "invoker"); Preconditions.checkNotNull(cmdLine, "cmdLine"); - if (callEvent) { - CommandExecuteEvent event = callCommandEvent(source, cmdLine).join(); - CommandResult commandResult = event.getResult(); - if (commandResult.isForwardToServer() || !commandResult.isAllowed()) { - return false; - } - cmdLine = commandResult.getCommand().orElse(event.getCommand()); - } String alias = cmdLine; String args = ""; int firstSpace = cmdLine.indexOf(' '); @@ -113,6 +112,38 @@ public class VelocityCommandManager implements CommandManager { } } + + @Override + public CompletableFuture executeAsync(CommandSource source, String cmdLine) { + CompletableFuture result = new CompletableFuture<>(); + callCommandEvent(source, cmdLine).thenAccept(event -> { + CommandResult commandResult = event.getResult(); + if (commandResult.isForwardToServer() || !commandResult.isAllowed()) { + result.complete(false); + } + String command = commandResult.getCommand().orElse(event.getCommand()); + try { + result.complete(executeImmediately(source, command)); + } catch (Exception e) { + result.completeExceptionally(e); + } + }); + return result; + } + + @Override + public CompletableFuture executeImmediatelyAsync(CommandSource source, String cmdLine) { + CompletableFuture result = new CompletableFuture<>(); + eventManager.getService().execute(() -> { + try { + result.complete(executeImmediately(source, cmdLine)); + } catch (Exception e) { + result.completeExceptionally(e); + } + }); + return result; + } + public boolean hasCommand(String command) { return commands.containsKey(command); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index 4864bcf22..e8b747bac 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -136,7 +136,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { } if (commandResult.isAllowed()) { try { - if (!server.getCommandManager().execute(player, command)) { + if (!server.getCommandManager().executeImmediately(player, command)) { smc.write(Chat.createServerbound(command)); } } catch (Exception e) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/console/VelocityConsole.java b/proxy/src/main/java/com/velocitypowered/proxy/console/VelocityConsole.java index 0123db3e1..1ccc0c101 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/console/VelocityConsole.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/console/VelocityConsole.java @@ -8,6 +8,8 @@ import com.velocitypowered.api.permission.Tristate; import com.velocitypowered.api.proxy.ConsoleCommandSource; import com.velocitypowered.proxy.VelocityServer; import java.util.List; +import java.util.concurrent.CompletableFuture; + import net.kyori.text.Component; import net.kyori.text.TextComponent; import net.kyori.text.format.TextColor; @@ -91,7 +93,7 @@ public final class VelocityConsole extends SimpleTerminalConsole implements Cons @Override protected void runCommand(String command) { try { - if (!this.server.getCommandManager().execute(this, command, true)) { + if (!this.server.getCommandManager().execute(this, command)) { sendMessage(TextComponent.of("Command not found.", TextColor.RED)); } } catch (Exception e) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityEventManager.java b/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityEventManager.java index 2ef08dade..87b0097b6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityEventManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityEventManager.java @@ -185,6 +185,10 @@ public class VelocityEventManager implements EventManager { fireEvent(new ProxyShutdownEvent()); } + public ExecutorService getService() { + return service; + } + private static class VelocityMethodScanner implements MethodScanner { @Override