From 08b2b8926d89a1bc04d40caadf26bfb8d9c26f7f Mon Sep 17 00:00:00 2001 From: willkroboth <46540330+willkroboth@users.noreply.github.com> Date: Mon, 23 Dec 2024 11:43:38 -0500 Subject: [PATCH] Cache Bukkit Command when wrapping CommandNodes Resolves https://github.com/PaperMC/Paper/issues/11378 by "restoring" the Spigot behavior where VanillaCommandNodes are only created once. Before this commit, BukkitBrigForwardingMap would create a new VanillaCommandWrapper each time a CommandNode was requested via the Bukkit CommandMap. This meant that calls to `Command#setPermission` would not persist between retrievals from the map. This allows command frameworks that insert CommandNodes directly into the Brigadier dispatcher to change the permission String of the VanillaCommandNodes created for their commands, rather than it always being the default `"minecraft.commands."`. --- .../com/mojang/brigadier/tree/CommandNode.java.patch | 3 ++- .../command/brigadier/bukkit/BukkitBrigForwardingMap.java | 8 +++++--- .../paper/command/brigadier/bukkit/BukkitCommandNode.java | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch b/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch index bb97c0d52c..f744f00edd 100644 --- a/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch +++ b/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch @@ -1,6 +1,6 @@ --- a/com/mojang/brigadier/tree/CommandNode.java +++ b/com/mojang/brigadier/tree/CommandNode.java -@@ -27,11 +_,21 @@ +@@ -27,11 +_,22 @@ private final Map> children = new LinkedHashMap<>(); private final Map> literals = new LinkedHashMap<>(); private final Map> arguments = new LinkedHashMap<>(); @@ -13,6 +13,7 @@ + public CommandNode clientNode; // Paper - Brigadier API + public CommandNode unwrappedCached = null; // Paper - Brigadier Command API + public CommandNode wrappedCached = null; // Paper - Brigadier Command API ++ public org.bukkit.command.Command wrappedBukkitCommandCached = null; // Paper - Brigadier Command API + // CraftBukkit start + public void removeCommand(String name) { + this.children.remove(name); diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java index 5eef7ae519..4512985b2e 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java @@ -83,11 +83,13 @@ public class BukkitBrigForwardingMap extends HashMap { return null; } - if (node instanceof BukkitCommandNode bukkitCommandNode) { - return bukkitCommandNode.getBukkitCommand(); + if (node.wrappedBukkitCommandCached != null) { + return node.wrappedBukkitCommandCached; } - return PaperBrigadier.wrapNode(node); + Command bukkitCommand = PaperBrigadier.wrapNode(node); + node.wrappedBukkitCommandCached = bukkitCommand; + return bukkitCommand; } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java index 1814cd072a..853ee7a6e3 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java @@ -43,6 +43,7 @@ public class BukkitCommandNode extends LiteralCommandNode { null, null, false ); this.command = command; + this.wrappedBukkitCommandCached = command; } public static BukkitCommandNode of(String name, Command command) {