--- a/net/minecraft/commands/CommandSourceStack.java +++ b/net/minecraft/commands/CommandSourceStack.java @@ -45,7 +_,7 @@ import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; -public class CommandSourceStack implements ExecutionCommandSource, SharedSuggestionProvider { +public class CommandSourceStack implements ExecutionCommandSource, SharedSuggestionProvider, io.papermc.paper.command.brigadier.PaperCommandSourceStack { // Paper - Brigadier API public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(Component.translatable("permissions.requires.player")); public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(Component.translatable("permissions.requires.entity")); public final CommandSource source; @@ -63,6 +_,8 @@ private final Vec2 rotation; private final CommandSigningContext signingContext; private final TaskChainer chatMessageChainer; + public java.util.Map currentCommand = new java.util.concurrent.ConcurrentHashMap<>(); // CraftBukkit // Paper - Thread Safe Vanilla Command permission checking + public boolean bypassSelectorPermissions = false; // Paper - add bypass for selector permissions public CommandSourceStack( CommandSource source, @@ -391,9 +_,44 @@ @Override public boolean hasPermission(int level) { + // CraftBukkit start + // Paper start - Thread Safe Vanilla Command permission checking + com.mojang.brigadier.tree.CommandNode currentCommand = this.currentCommand.get(Thread.currentThread()); + if (currentCommand != null) { + return this.hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); + // Paper end - Thread Safe Vanilla Command permission checking + } + // CraftBukkit end + 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) { + // 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; } @@ -499,20 +_,25 @@ Component component = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) { for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { - if (serverPlayer.commandSource() != this.source && this.server.getPlayerList().isOp(serverPlayer.getGameProfile())) { + if (serverPlayer.commandSource() != this.source && serverPlayer.getBukkitEntity().hasPermission("minecraft.admin.command_feedback")) { // CraftBukkit serverPlayer.sendSystemMessage(component); } } } - if (this.source != this.server && this.server.getGameRules().getBoolean(GameRules.RULE_LOGADMINCOMMANDS)) { + if (this.source != this.server && this.server.getGameRules().getBoolean(GameRules.RULE_LOGADMINCOMMANDS) && !org.spigotmc.SpigotConfig.silentCommandBlocks) { // Spigot this.server.sendSystemMessage(component); } } public void sendFailure(Component message) { + // Paper start - Add UnknownCommandEvent + this.sendFailure(message, true); + } + public void sendFailure(Component message, boolean withStyle) { + // Paper end - Add UnknownCommandEvent if (this.source.acceptsFailure() && !this.silent) { - this.source.sendSystemMessage(Component.empty().append(message).withStyle(ChatFormatting.RED)); + this.source.sendSystemMessage(withStyle ? Component.empty().append(message).withStyle(ChatFormatting.RED) : message); // Paper - Add UnknownCommandEvent } } @@ -598,4 +_,16 @@ public boolean isSilent() { return this.silent; } + + // Paper start + @Override + public CommandSourceStack getHandle() { + return this; + } + // Paper end + // CraftBukkit start + public org.bukkit.command.CommandSender getBukkitSender() { + return this.source.getBukkitSender(this); + } + // CraftBukkit end }