InvocationInfo API (#1467)

* Invocation Source API

Allows proxies to detect if a command is executed from an unsigned/signed/api source.

This is useful because it allows commands executed from the player manually or by clicking on a chat message to be controlled.

* Update api significantly to improve api coverage

* javadoc

* javadoc

* Update api/src/main/java/com/velocitypowered/api/event/command/CommandExecuteEvent.java

Co-authored-by: powercas_gamer <cas@mizule.dev>

* Update api/src/main/java/com/velocitypowered/api/event/command/CommandExecuteEvent.java

Co-authored-by: powercas_gamer <cas@mizule.dev>

* Fix rename

---------

Co-authored-by: powercas_gamer <cas@mizule.dev>
This commit is contained in:
Owen
2024-12-04 12:36:45 -05:00
committed by GitHub
parent be5f0ace26
commit 965db127a9
8 changed files with 120 additions and 8 deletions

View File

@@ -218,13 +218,14 @@ public class VelocityCommandManager implements CommandManager {
*
* @param source the source to execute the command for
* @param cmdLine the command to execute
* @param invocationInfo the invocation info
* @return the {@link CompletableFuture} of the event
*/
public CompletableFuture<CommandExecuteEvent> callCommandEvent(final CommandSource source,
final String cmdLine) {
final String cmdLine, final CommandExecuteEvent.InvocationInfo invocationInfo) {
Preconditions.checkNotNull(source, "source");
Preconditions.checkNotNull(cmdLine, "cmdLine");
return eventManager.fire(new CommandExecuteEvent(source, cmdLine));
return eventManager.fire(new CommandExecuteEvent(source, cmdLine, invocationInfo));
}
private boolean executeImmediately0(final CommandSource source, final ParseResults<CommandSource> parsed) {
@@ -266,7 +267,12 @@ public class VelocityCommandManager implements CommandManager {
Preconditions.checkNotNull(source, "source");
Preconditions.checkNotNull(cmdLine, "cmdLine");
return callCommandEvent(source, cmdLine).thenComposeAsync(event -> {
CommandExecuteEvent.InvocationInfo invocationInfo = new CommandExecuteEvent.InvocationInfo(
CommandExecuteEvent.SignedState.UNSUPPORTED,
CommandExecuteEvent.Source.API
);
return callCommandEvent(source, cmdLine, invocationInfo).thenComposeAsync(event -> {
CommandExecuteEvent.CommandResult commandResult = event.getResult();
if (commandResult.isForwardToServer() || !commandResult.isAllowed()) {
return CompletableFuture.completedFuture(false);

View File

@@ -56,8 +56,10 @@ public interface CommandHandler<T extends MinecraftPacket> {
default void queueCommandResult(VelocityServer server, ConnectedPlayer player,
BiFunction<CommandExecuteEvent, LastSeenMessages, CompletableFuture<MinecraftPacket>> futurePacketCreator,
String message, Instant timestamp, @Nullable LastSeenMessages lastSeenMessages) {
CompletableFuture<CommandExecuteEvent> eventFuture = server.getCommandManager().callCommandEvent(player, message);
String message, Instant timestamp, @Nullable LastSeenMessages lastSeenMessages,
CommandExecuteEvent.InvocationInfo invocationInfo) {
CompletableFuture<CommandExecuteEvent> eventFuture = server.getCommandManager().callCommandEvent(player, message,
invocationInfo);
player.getChatQueue().queuePacket(
newLastSeenMessages -> eventFuture
.thenComposeAsync(event -> futurePacketCreator.apply(event, newLastSeenMessages))

View File

@@ -111,6 +111,6 @@ public class KeyedCommandHandler implements CommandHandler<KeyedPlayerCommandPac
}
return null;
});
}, packet.getCommand(), packet.getTimestamp(), null);
}, packet.getCommand(), packet.getTimestamp(), null, new CommandExecuteEvent.InvocationInfo(CommandExecuteEvent.SignedState.UNSUPPORTED, CommandExecuteEvent.Source.PLAYER));
}
}

View File

@@ -62,6 +62,6 @@ public class LegacyCommandHandler implements CommandHandler<LegacyChatPacket> {
}
return null;
});
}, command, Instant.now(), null);
}, command, Instant.now(), null, new CommandExecuteEvent.InvocationInfo(CommandExecuteEvent.SignedState.UNSUPPORTED, CommandExecuteEvent.Source.PLAYER));
}
}

View File

@@ -117,6 +117,7 @@ public class SessionCommandHandler implements CommandHandler<SessionPlayerComman
}
return forwardCommand(fixedPacket, commandToRun);
});
}, packet.command, packet.timeStamp, packet.lastSeenMessages);
}, packet.command, packet.timeStamp, packet.lastSeenMessages,
new CommandExecuteEvent.InvocationInfo(packet.getEventSignedState(), CommandExecuteEvent.Source.PLAYER));
}
}

View File

@@ -18,6 +18,7 @@
package com.velocitypowered.proxy.protocol.packet.chat.session;
import com.google.common.collect.Lists;
import com.velocitypowered.api.event.command.CommandExecuteEvent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
@@ -68,6 +69,10 @@ public class SessionPlayerCommandPacket implements MinecraftPacket {
return !argumentSignatures.isEmpty();
}
public CommandExecuteEvent.SignedState getEventSignedState() {
return !this.argumentSignatures.isEmpty() ? CommandExecuteEvent.SignedState.SIGNED_WITH_ARGS : CommandExecuteEvent.SignedState.SIGNED_WITHOUT_ARGS;
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this);

View File

@@ -17,6 +17,7 @@
package com.velocitypowered.proxy.protocol.packet.chat.session;
import com.velocitypowered.api.event.command.CommandExecuteEvent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.chat.LastSeenMessages;
@@ -44,6 +45,11 @@ public class UnsignedPlayerCommandPacket extends SessionPlayerCommandPacket {
return false;
}
@Override
public CommandExecuteEvent.SignedState getEventSignedState() {
return CommandExecuteEvent.SignedState.UNSIGNED;
}
@Override
public String toString() {
return "UnsignedPlayerCommandPacket{" +