Added event when a command is executed from Velocity (#984)

* feat: added event for command invocation

This event is called when a command invocation attempt on the proxy occurs

* Fix javadoc issue
This commit is contained in:
Joo200 2024-03-05 16:11:17 +01:00 committed by GitHub
parent c34dafe2a2
commit 8891faa52c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 124 additions and 3 deletions

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2020-2021 Velocity Contributors
*
* The Velocity API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the api top-level directory.
*/
package com.velocitypowered.api.command;
/**
* The result of a command invocation attempt.
*/
public enum CommandResult {
/**
* The command was successfully executed by the proxy.
*/
EXECUTED,
/**
* The command was forwarded to the backend server.
* The command may be successfully executed or not
*/
FORWARDED,
/**
* The provided command input contained syntax errors.
*/
SYNTAX_ERROR,
/**
* An unexpected exception occurred while executing the command in the proxy.
*/
EXCEPTION
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (C) 2020-2023 Velocity Contributors
*
* The Velocity API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the api top-level directory.
*/
package com.velocitypowered.api.event.command;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.command.CommandResult;
import com.velocitypowered.api.command.CommandSource;
import org.jetbrains.annotations.NotNull;
/**
* This event is fired when velocity executed a command. This event is called after the event
* is handled.
*
* <p>Commands can be cancelled or forwarded to backend servers in {@link CommandExecuteEvent}.
* This will prevent firing this event.</p>
*
* @since 3.3.0
*/
public final class PostCommandInvocationEvent {
private final CommandSource commandSource;
private final String command;
private final CommandResult result;
/**
* Constructs a PostCommandInvocationEvent.
*
* @param commandSource the source executing the command
* @param command the command being executed without first slash
* @param result the result of this command
*/
public PostCommandInvocationEvent(
final @NotNull CommandSource commandSource,
final @NotNull String command,
final @NotNull CommandResult result
) {
this.commandSource = Preconditions.checkNotNull(commandSource, "commandSource");
this.command = Preconditions.checkNotNull(command, "command");
this.result = Preconditions.checkNotNull(result, "result");
}
/**
* Get the source of this executed command.
*
* @return the source
*/
public @NotNull CommandSource getCommandSource() {
return commandSource;
}
/**
* Gets the original command line executed without the first slash.
*
* @return the original command
* @see CommandExecuteEvent#getCommand()
*/
public @NotNull String getCommand() {
return command;
}
/**
* Returns the result of the command execution.
*
* @return the execution result
*/
public @NotNull CommandResult getResult() {
return result;
}
@Override
public String toString() {
return "PostCommandInvocationEvent{"
+ "commandSource=" + commandSource
+ ", command=" + command
+ '}';
}
}

View File

@ -31,9 +31,10 @@ import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.Command;
import com.velocitypowered.api.command.CommandManager;
import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.command.CommandResult;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.command.CommandExecuteEvent;
import com.velocitypowered.api.event.command.CommandExecuteEvent.CommandResult;
import com.velocitypowered.api.event.command.PostCommandInvocationEvent;
import com.velocitypowered.proxy.command.registrar.BrigadierCommandRegistrar;
import com.velocitypowered.proxy.command.registrar.CommandRegistrar;
import com.velocitypowered.proxy.command.registrar.RawCommandRegistrar;
@ -220,23 +221,30 @@ public class VelocityCommandManager implements CommandManager {
Preconditions.checkNotNull(cmdLine, "cmdLine");
final String normalizedInput = VelocityCommands.normalizeInput(cmdLine, true);
CommandResult result = CommandResult.EXCEPTION;
try {
// The parse can fail if the requirement predicates throw
final ParseResults<CommandSource> parse = this.parse(normalizedInput, source);
return dispatcher.execute(parse) != BrigadierCommand.FORWARD;
boolean executed = dispatcher.execute(parse) != BrigadierCommand.FORWARD;
result = executed ? CommandResult.EXECUTED : CommandResult.FORWARDED;
return executed;
} catch (final CommandSyntaxException e) {
boolean isSyntaxError = !e.getType().equals(
CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand());
if (isSyntaxError) {
source.sendMessage(Component.text(e.getMessage(), NamedTextColor.RED));
result = com.velocitypowered.api.command.CommandResult.SYNTAX_ERROR;
// This is, of course, a lie, but the API will need to change...
return true;
} else {
result = CommandResult.FORWARDED;
return false;
}
} catch (final Throwable e) {
// Ugly, ugly swallowing of everything Throwable, because plugins are naughty.
throw new RuntimeException("Unable to invoke command " + cmdLine + " for " + source, e);
} finally {
eventManager.fireAndForget(new PostCommandInvocationEvent(source, cmdLine, result));
}
}
@ -246,7 +254,7 @@ public class VelocityCommandManager implements CommandManager {
Preconditions.checkNotNull(cmdLine, "cmdLine");
return callCommandEvent(source, cmdLine).thenApplyAsync(event -> {
CommandResult commandResult = event.getResult();
CommandExecuteEvent.CommandResult commandResult = event.getResult();
if (commandResult.isForwardToServer() || !commandResult.isAllowed()) {
return false;
}