From 6dafeceebd55fc4cee492e3d9febf119fafb769c Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Wed, 25 Aug 2021 13:19:53 -0700 Subject: [PATCH] Vanilla command permission fixes Fixes permission checks for vanilla commands which don't have a requirement, as well as for namespaced vanilla commands. == AT == public-f com.mojang.brigadier.tree.CommandNode requirement --- .../builder/ArgumentBuilder.java.patch | 21 ++++++++++ .../minecraft/commands/Commands.java.patch | 41 +++++++++++-------- .../command/VanillaCommandWrapper.java | 16 +++++++- 3 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 paper-server/patches/sources/com/mojang/brigadier/builder/ArgumentBuilder.java.patch diff --git a/paper-server/patches/sources/com/mojang/brigadier/builder/ArgumentBuilder.java.patch b/paper-server/patches/sources/com/mojang/brigadier/builder/ArgumentBuilder.java.patch new file mode 100644 index 0000000000..16daaa3a3c --- /dev/null +++ b/paper-server/patches/sources/com/mojang/brigadier/builder/ArgumentBuilder.java.patch @@ -0,0 +1,21 @@ +--- a/com/mojang/brigadier/builder/ArgumentBuilder.java ++++ b/com/mojang/brigadier/builder/ArgumentBuilder.java +@@ -14,9 +14,17 @@ + import java.util.function.Predicate; + + public abstract class ArgumentBuilder> { ++ // Paper start - Vanilla command permission fixes ++ private static final Predicate DEFAULT_REQUIREMENT = s -> true; ++ ++ @SuppressWarnings("unchecked") ++ public static Predicate defaultRequirement() { ++ return (Predicate) DEFAULT_REQUIREMENT; ++ } ++ // Paper end - Vanilla command permission fixes + private final RootCommandNode arguments = new RootCommandNode<>(); + private Command command; +- private Predicate requirement = s -> true; ++ private Predicate requirement = defaultRequirement(); // Paper - Vanilla command permission fixes + private CommandNode target; + private RedirectModifier modifier = null; + private boolean forks; diff --git a/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch b/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch index cca3d6f91f..0dc77899fa 100644 --- a/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch +++ b/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch @@ -1,10 +1,9 @@ --- a/net/minecraft/commands/Commands.java +++ b/net/minecraft/commands/Commands.java -@@ -138,6 +138,14 @@ - import net.minecraft.world.flag.FeatureFlags; +@@ -139,6 +139,14 @@ import net.minecraft.world.level.GameRules; import org.slf4j.Logger; -+ + +// CraftBukkit start +import com.google.common.base.Joiner; +import java.util.Collection; @@ -12,9 +11,10 @@ +import org.bukkit.event.player.PlayerCommandSendEvent; +import org.bukkit.event.server.ServerCommandEvent; +// CraftBukkit end - ++ public class Commands { + private static final ThreadLocal> CURRENT_EXECUTION_CONTEXT = new ThreadLocal(); @@ -151,6 +159,7 @@ private final com.mojang.brigadier.CommandDispatcher dispatcher = new com.mojang.brigadier.CommandDispatcher(); @@ -23,19 +23,28 @@ AdvancementCommands.register(this.dispatcher); AttributeCommand.register(this.dispatcher, commandRegistryAccess); ExecuteCommand.register(this.dispatcher, commandRegistryAccess); -@@ -252,6 +261,11 @@ - PublishCommand.register(this.dispatcher); - } +@@ -250,8 +259,20 @@ + if (environment.includeIntegrated) { + PublishCommand.register(this.dispatcher); ++ } ++ ++ // Paper start - Vanilla command permission fixes ++ for (final CommandNode node : this.dispatcher.getRoot().getChildren()) { ++ if (node.getRequirement() == com.mojang.brigadier.builder.ArgumentBuilder.defaultRequirement()) { ++ node.requirement = stack -> stack.source == CommandSource.NULL || stack.getBukkitSender().hasPermission(org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(node)); ++ } + } ++ // Paper end - Vanilla command permission fixes + // CraftBukkit start + } -+ + + public Commands() { + // CraftBukkkit end this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer()); } -@@ -262,30 +276,78 @@ +@@ -262,30 +283,78 @@ return new ParseResults(commandcontextbuilder1, parseResults.getReader(), parseResults.getExceptions()); } @@ -123,7 +132,7 @@ StackTraceElement[] astacktraceelement = exception.getStackTrace(); for (int i = 0; i < Math.min(astacktraceelement.length, 3); ++i) { -@@ -298,7 +360,7 @@ +@@ -298,7 +367,7 @@ })); if (SharedConstants.IS_RUNNING_IN_IDE) { commandlistenerwrapper.sendFailure(Component.literal(Util.describeError(exception))); @@ -132,7 +141,7 @@ } } finally { Profiler.get().pop(); -@@ -307,18 +369,22 @@ +@@ -307,18 +376,22 @@ } @Nullable @@ -161,7 +170,7 @@ }); if (i > 10) { -@@ -333,8 +399,18 @@ +@@ -333,8 +406,18 @@ } ichatmutablecomponent.append((Component) Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC)); @@ -181,7 +190,7 @@ return null; } -@@ -368,7 +444,7 @@ +@@ -368,7 +451,7 @@ executioncontext1.close(); } finally { @@ -190,7 +199,7 @@ } } else { callback.accept(executioncontext); -@@ -377,22 +453,89 @@ +@@ -377,22 +460,89 @@ } public void sendCommands(ServerPlayer player) { @@ -285,7 +294,7 @@ argumentbuilder.requires((icompletionprovider) -> { return true; -@@ -415,12 +558,12 @@ +@@ -415,12 +565,12 @@ argumentbuilder.redirect((CommandNode) resultNodes.get(argumentbuilder.getRedirect())); } @@ -300,7 +309,7 @@ } } } -@@ -481,7 +624,7 @@ +@@ -481,7 +631,7 @@ } private HolderLookup.RegistryLookup.Delegate createLookup(final HolderLookup.RegistryLookup original) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java index 9b453830e4..35b05f9321 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java @@ -91,7 +91,21 @@ public final class VanillaCommandWrapper extends BukkitCommand { } public static String getPermission(CommandNode vanillaCommand) { - return "minecraft.command." + ((vanillaCommand.getRedirect() == null) ? vanillaCommand.getName() : vanillaCommand.getRedirect().getName()); + // Paper start - Vanilla command permission fixes + while (vanillaCommand.getRedirect() != null) { + vanillaCommand = vanillaCommand.getRedirect(); + } + final String commandName = vanillaCommand.getName(); + return "minecraft.command." + stripDefaultNamespace(commandName); + } + + private static String stripDefaultNamespace(final String maybeNamespaced) { + final String prefix = "minecraft:"; + if (maybeNamespaced.startsWith(prefix)) { + return maybeNamespaced.substring(prefix.length()); + } + return maybeNamespaced; + // Paper end - Vanilla command permission fixes } private String toDispatcher(String[] args, String name) {