diff --git a/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch b/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch index 766f7556b1..31a1359323 100644 --- a/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch +++ b/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch @@ -20,7 +20,7 @@ public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String name, Component displayName, MinecraftServer server, @Nullable Entity entity) { this(output, pos, rot, world, level, name, displayName, server, entity, false, CommandResultCallback.EMPTY, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(server)); -@@ -169,11 +172,47 @@ +@@ -169,11 +172,66 @@ return this.textName; } @@ -58,17 +58,36 @@ return this.permissionLevel >= level; } ++ // Paper start - Fix permission levels for command blocks ++ private boolean forceRespectPermissionLevel() { ++ return this.source == CommandSource.NULL || (this.source instanceof final net.minecraft.world.level.BaseCommandBlock commandBlock && commandBlock.getLevel().paperConfig().commandBlocks.forceFollowPermLevel); ++ } ++ // Paper end - Fix permission levels for command blocks ++ + // CraftBukkit start + public boolean hasPermission(int i, String bukkitPermission) { -+ // World is null when loading functions -+ return ((this.getLevel() == null || !this.getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || this.getBukkitSender().hasPermission(bukkitPermission); ++ // Paper start - Fix permission levels for command blocks ++ final java.util.function.BooleanSupplier hasBukkitPerm = () -> this.source == CommandSource.NULL /*treat NULL as having all bukkit perms*/ || this.getBukkitSender().hasPermission(bukkitPermission); // lazily check bukkit perms to the benefit of custom permission setups ++ // if the server is null, we must check the vanilla perm level system ++ // if ignoreVanillaPermissions is true, we can skip vanilla perms and just run the bukkit perm check ++ //noinspection ConstantValue ++ if (this.getServer() == null || !this.getServer().server.ignoreVanillaPermissions) { // server & level are null for command function loading ++ final boolean hasPermLevel = this.permissionLevel >= i; ++ if (this.forceRespectPermissionLevel()) { // NULL CommandSource and command blocks (if setting is enabled) should always pass the vanilla perm check ++ return hasPermLevel && hasBukkitPerm.getAsBoolean(); ++ } else { // otherwise check vanilla perm first then bukkit perm, matching upstream behavior ++ return hasPermLevel || hasBukkitPerm.getAsBoolean(); ++ } ++ } ++ return hasBukkitPerm.getAsBoolean(); ++ // Paper end - Fix permission levels for command blocks + } + // CraftBukkit end + public Vec3 getPosition() { return this.worldPosition; } -@@ -302,21 +341,26 @@ +@@ -302,21 +360,26 @@ while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); @@ -98,7 +117,7 @@ } } -@@ -400,4 +444,10 @@ +@@ -400,4 +463,10 @@ public boolean isSilent() { return this.silent; } 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 4b356d81aa..a21b89d8de 100644 --- a/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch +++ b/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch @@ -1,9 +1,10 @@ --- a/net/minecraft/commands/Commands.java +++ b/net/minecraft/commands/Commands.java -@@ -139,6 +139,14 @@ +@@ -138,6 +138,14 @@ + import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.level.GameRules; import org.slf4j.Logger; - ++ +// CraftBukkit start +import com.google.common.base.Joiner; +import java.util.Collection; @@ -11,10 +12,9 @@ +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,28 +23,26 @@ AdvancementCommands.register(this.dispatcher); AttributeCommand.register(this.dispatcher, commandRegistryAccess); ExecuteCommand.register(this.dispatcher, commandRegistryAccess); -@@ -250,8 +259,20 @@ - - if (environment.includeIntegrated) { +@@ -252,6 +261,18 @@ 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 +283,78 @@ +@@ -262,30 +283,69 @@ return new ParseResults(commandcontextbuilder1, parseResults.getReader(), parseResults.getExceptions()); } @@ -68,16 +66,7 @@ + String[] args = command.split(" "); + if (args.length == 0) return; // Paper - empty commands shall not be dispatched + -+ String cmd = args[0]; -+ if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); -+ if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length()); -+ -+ // Block disallowed commands -+ if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op") -+ || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip") -+ || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) { -+ return; -+ } ++ // Paper - Fix permission levels for command blocks + + // Handle vanilla commands; + if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) { @@ -132,7 +121,7 @@ StackTraceElement[] astacktraceelement = exception.getStackTrace(); for (int i = 0; i < Math.min(astacktraceelement.length, 3); ++i) { -@@ -298,7 +367,7 @@ +@@ -298,7 +358,7 @@ })); if (SharedConstants.IS_RUNNING_IN_IDE) { commandlistenerwrapper.sendFailure(Component.literal(Util.describeError(exception))); @@ -141,7 +130,7 @@ } } finally { Profiler.get().pop(); -@@ -307,18 +376,22 @@ +@@ -307,18 +367,22 @@ } @Nullable @@ -170,7 +159,7 @@ }); if (i > 10) { -@@ -333,8 +406,18 @@ +@@ -333,8 +397,18 @@ } ichatmutablecomponent.append((Component) Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC)); @@ -190,7 +179,7 @@ return null; } -@@ -368,7 +451,7 @@ +@@ -368,7 +442,7 @@ executioncontext1.close(); } finally { @@ -199,7 +188,7 @@ } } else { callback.accept(executioncontext); -@@ -377,22 +460,89 @@ +@@ -377,22 +451,89 @@ } public void sendCommands(ServerPlayer player) { @@ -294,7 +283,7 @@ argumentbuilder.requires((icompletionprovider) -> { return true; -@@ -415,12 +565,12 @@ +@@ -415,12 +556,12 @@ argumentbuilder.redirect((CommandNode) resultNodes.get(argumentbuilder.getRedirect())); } @@ -309,7 +298,7 @@ } } } -@@ -481,7 +631,7 @@ +@@ -481,7 +622,7 @@ } private HolderLookup.RegistryLookup.Delegate createLookup(final HolderLookup.RegistryLookup original) { diff --git a/paper-server/patches/sources/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch index 10b864315b..7c789e80ad 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch @@ -1,6 +1,14 @@ --- a/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java +++ b/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java -@@ -135,5 +135,12 @@ +@@ -128,12 +128,19 @@ + + @Override + public CommandSourceStack createCommandSourceStack() { +- return new CommandSourceStack(this, MinecartCommandBlock.this.position(), MinecartCommandBlock.this.getRotationVector(), this.getLevel(), 2, this.getName().getString(), MinecartCommandBlock.this.getDisplayName(), this.getLevel().getServer(), MinecartCommandBlock.this); ++ return new CommandSourceStack(this, MinecartCommandBlock.this.position(), MinecartCommandBlock.this.getRotationVector(), this.getLevel(), this.getLevel().paperConfig().commandBlocks.permissionsLevel, this.getName().getString(), MinecartCommandBlock.this.getDisplayName(), this.getLevel().getServer(), MinecartCommandBlock.this); // Paper - configurable command block perm level + } + + @Override public boolean isValid() { return !MinecartCommandBlock.this.isRemoved(); } diff --git a/paper-server/patches/sources/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch b/paper-server/patches/sources/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch index 2c1ebabd28..49a6bff68c 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch @@ -15,3 +15,12 @@ public void setCommand(String command) { super.setCommand(command); CommandBlockEntity.this.setChanged(); +@@ -51,7 +58,7 @@ + public CommandSourceStack createCommandSourceStack() { + Direction enumdirection = (Direction) CommandBlockEntity.this.getBlockState().getValue(CommandBlock.FACING); + +- return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), 2, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null); ++ return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), this.getLevel().paperConfig().commandBlocks.permissionsLevel, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null); // Paper - configurable command block perm level + } + + @Override