diff --git a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java b/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java index 3848933b67..0b1af3a8d4 100644 --- a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java +++ b/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java @@ -5,5 +5,10 @@ import com.mojang.brigadier.suggestion.SuggestionProvider; import java.util.function.Predicate; +/** + * Brigadier {@link Command}, {@link SuggestionProvider}, and permission checker for Bukkit {@link Command}s. + * + * @param command source type + */ public interface BukkitBrigadierCommand extends Command, Predicate, SuggestionProvider { } diff --git a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java b/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java index 7bfa71f150..b7e09256a1 100644 --- a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java +++ b/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java @@ -13,18 +13,17 @@ import org.bukkit.event.server.ServerEvent; import org.jetbrains.annotations.NotNull; /** - * Fired anytime the server synchronizes Bukkit CommandMap to Brigadier. + * Fired anytime the server synchronizes Bukkit commands to Brigadier. * - * Allows a plugin to control the Literal and Argument nodes for this command to be - * sent to the client. - * This is done at Plugin Enable time after commands have been registered, but some - * plugins may use reflection to retrigger this rebuild during runtime. + * Allows a plugin to control the command node structure for its commands. + * This is done at Plugin Enable time after commands have been registered, but may also + * run at a later point in the server lifetime due to plugins, a server reload, etc. * * @deprecated Draft API - Subject to change until confirmed solves desired use cases */ @Deprecated @Warning(false) -public class CommandRegisteredEvent extends ServerEvent implements Cancellable { +public class CommandRegisteredEvent extends ServerEvent implements Cancellable { private static final HandlerList handlers = new HandlerList(); private final String commandLabel; @@ -33,6 +32,7 @@ public class CommandRegisteredEvent ext private final RootCommandNode root; private final ArgumentCommandNode defaultArgs; private LiteralCommandNode literal; + private boolean rawCommand = false; private boolean cancelled = false; public CommandRegisteredEvent(String commandLabel, BukkitBrigadierCommand brigadierCommand, Command command, RootCommandNode root, LiteralCommandNode literal, ArgumentCommandNode defaultArgs) { @@ -45,55 +45,99 @@ public class CommandRegisteredEvent ext } /** - * @return The command name being registered + * Gets the command label of the {@link Command} being registered. + * + * @return the command label */ public String getCommandLabel() { - return commandLabel; + return this.commandLabel; } /** - * @return The Bukkit API Brigadier Wrapped Command Object to handle executions and suggestions + * Gets the {@link BukkitBrigadierCommand} for the {@link Command} being registered. This can be used + * as the {@link com.mojang.brigadier.Command command executor} or + * {@link com.mojang.brigadier.suggestion.SuggestionProvider} of a {@link com.mojang.brigadier.tree.CommandNode} + * to delegate to the {@link Command} being registered. + * + * @return the {@link BukkitBrigadierCommand} */ public BukkitBrigadierCommand getBrigadierCommand() { - return brigadierCommand; - } - - public Command getCommand() { - return command; + return this.brigadierCommand; } /** - * @return Gets the root command node being used to register a command to. + * Gets the {@link Command} being registered. + * + * @return the {@link Command} + */ + public Command getCommand() { + return this.command; + } + + /** + * Gets the {@link RootCommandNode} which is being registered to. + * + * @return the {@link RootCommandNode} */ public RootCommandNode getRoot() { - return root; + return this.root; } /** - * Returns the Bukkit API's default handling of Arguments, if you wish to reuse it. - * @return + * Gets the Bukkit APIs default arguments node (greedy string), for if + * you wish to reuse it. + * + * @return default arguments node */ public ArgumentCommandNode getDefaultArgs() { - return defaultArgs; + return this.defaultArgs; } /** - * Returns the Bukkit API's default literal for this command, including the {@link #getDefaultArgs()} as a child already. - * @return + * Gets the {@link LiteralCommandNode} to be registered for the {@link Command}. + * + * @return the {@link LiteralCommandNode} */ public LiteralCommandNode getLiteral() { - return literal; + return this.literal; } /** - * Changes the literal used to register this command. The previous literable is mutable, so this is primarily if - * you want to completely replace the object. - * @param literal + * Sets the {@link LiteralCommandNode} used to register this command. The default literal is mutable, so + * this is primarily if you want to completely replace the object. + * + * @param literal new node */ public void setLiteral(LiteralCommandNode literal) { this.literal = literal; } + /** + * Gets whether this command should is treated as "raw". + * + * @see #setRawCommand(boolean) + * @return whether this command is treated as "raw" + */ + public boolean isRawCommand() { + return this.rawCommand; + } + + /** + * Sets whether this command should be treated as "raw". + * + *

A "raw" command will only use the node provided by this event for + * sending the command tree to the client. For execution purposes, the default + * greedy string execution of a standard Bukkit {@link Command} is used.

+ * + *

On older versions of Paper, this was the default and only behavior of this + * event.

+ * + * @param rawCommand whether this command should be treated as "raw" + */ + public void setRawCommand(final boolean rawCommand) { + this.rawCommand = rawCommand; + } + /** * {@inheritDoc} */ diff --git a/patches/server/Fix-entity-type-tags-suggestions-in-selectors.patch b/patches/server/Fix-entity-type-tags-suggestions-in-selectors.patch index ecd68933eb..9a1e579ca0 100644 --- a/patches/server/Fix-entity-type-tags-suggestions-in-selectors.patch +++ b/patches/server/Fix-entity-type-tags-suggestions-in-selectors.patch @@ -45,7 +45,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + boolean registeredAskServerSuggestionsForTree = false; // Paper - tell clients to ask server for suggestions for EntityArguments while (iterator.hasNext()) { CommandNode commandnode2 = (CommandNode) iterator.next(); - if ( !org.spigotmc.SpigotConfig.sendNamespaced && commandnode2.getName().contains( ":" ) ) continue; // Spigot + // Paper start @@ -0,0 +0,0 @@ public class Commands { if (requiredargumentbuilder.getSuggestionsProvider() != null) { diff --git a/patches/server/Implement-Brigadier-Mojang-API.patch b/patches/server/Implement-Brigadier-Mojang-API.patch index a4f045318f..419529ef47 100644 --- a/patches/server/Implement-Brigadier-Mojang-API.patch +++ b/patches/server/Implement-Brigadier-Mojang-API.patch @@ -21,6 +21,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper start implementation("org.jline:jline-terminal-jansi:3.21.0") implementation("net.minecrell:terminalconsoleappender:1.3.0") +diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java ++++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +@@ -0,0 +0,0 @@ public abstract class CommandNode implements Comparable> { + private final RedirectModifier modifier; + private final boolean forks; + private Command command; ++ public LiteralCommandNode clientNode = null; // Paper + // CraftBukkit start + public void removeCommand(String name) { + this.children.remove(name); diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java @@ -81,6 +93,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); event.getPlayer().getServer().getPluginManager().callEvent(event); +@@ -0,0 +0,0 @@ public class Commands { + + while (iterator.hasNext()) { + CommandNode commandnode2 = (CommandNode) iterator.next(); ++ // Paper start ++ if (commandnode2.clientNode != null) { ++ commandnode2 = commandnode2.clientNode; ++ } ++ // Paper end + if ( !org.spigotmc.SpigotConfig.sendNamespaced && commandnode2.getName().contains( ":" ) ) continue; // Spigot + + if (commandnode2.canUse(source)) { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -139,6 +163,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - Expose Brigadier to Paper-MojangAPI + com.mojang.brigadier.tree.RootCommandNode root = dispatcher.getRoot(); + LiteralCommandNode literal = LiteralArgumentBuilder.literal(label).requires(this).executes(this).build(); ++ LiteralCommandNode defaultNode = literal; + com.mojang.brigadier.tree.ArgumentCommandNode defaultArgs = RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this).build(); + literal.addChild(defaultArgs); + com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent event = new com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<>(label, this, this.command, root, literal, defaultArgs); @@ -146,6 +171,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + literal = event.getLiteral(); ++ if (event.isRawCommand()) { ++ defaultNode.clientNode = literal; ++ literal = defaultNode; ++ } + root.addChild(literal); + return literal; + // Paper end