Fix cmd permission levels for command blocks

This commit is contained in:
Jake Potrebic
2022-01-24 15:32:02 -08:00
parent 4bb84c46ac
commit b0579722db
4 changed files with 60 additions and 35 deletions

View File

@@ -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) { 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)); 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; return this.textName;
} }
@@ -58,17 +58,36 @@
return this.permissionLevel >= level; 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 + // CraftBukkit start
+ public boolean hasPermission(int i, String bukkitPermission) { + public boolean hasPermission(int i, String bukkitPermission) {
+ // World is null when loading functions + // Paper start - Fix permission levels for command blocks
+ return ((this.getLevel() == null || !this.getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || this.getBukkitSender().hasPermission(bukkitPermission); + 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 + // CraftBukkit end
+ +
public Vec3 getPosition() { public Vec3 getPosition() {
return this.worldPosition; return this.worldPosition;
} }
@@ -302,21 +341,26 @@ @@ -302,21 +360,26 @@
while (iterator.hasNext()) { while (iterator.hasNext()) {
ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ServerPlayer entityplayer = (ServerPlayer) iterator.next();
@@ -98,7 +117,7 @@
} }
} }
@@ -400,4 +444,10 @@ @@ -400,4 +463,10 @@
public boolean isSilent() { public boolean isSilent() {
return this.silent; return this.silent;
} }

View File

@@ -1,9 +1,10 @@
--- a/net/minecraft/commands/Commands.java --- a/net/minecraft/commands/Commands.java
+++ b/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 net.minecraft.world.level.GameRules;
import org.slf4j.Logger; import org.slf4j.Logger;
+
+// CraftBukkit start +// CraftBukkit start
+import com.google.common.base.Joiner; +import com.google.common.base.Joiner;
+import java.util.Collection; +import java.util.Collection;
@@ -11,10 +12,9 @@
+import org.bukkit.event.player.PlayerCommandSendEvent; +import org.bukkit.event.player.PlayerCommandSendEvent;
+import org.bukkit.event.server.ServerCommandEvent; +import org.bukkit.event.server.ServerCommandEvent;
+// CraftBukkit end +// CraftBukkit end
+
public class Commands { public class Commands {
private static final ThreadLocal<ExecutionContext<CommandSourceStack>> CURRENT_EXECUTION_CONTEXT = new ThreadLocal();
@@ -151,6 +159,7 @@ @@ -151,6 +159,7 @@
private final com.mojang.brigadier.CommandDispatcher<CommandSourceStack> dispatcher = new com.mojang.brigadier.CommandDispatcher(); private final com.mojang.brigadier.CommandDispatcher<CommandSourceStack> dispatcher = new com.mojang.brigadier.CommandDispatcher();
@@ -23,28 +23,26 @@
AdvancementCommands.register(this.dispatcher); AdvancementCommands.register(this.dispatcher);
AttributeCommand.register(this.dispatcher, commandRegistryAccess); AttributeCommand.register(this.dispatcher, commandRegistryAccess);
ExecuteCommand.register(this.dispatcher, commandRegistryAccess); ExecuteCommand.register(this.dispatcher, commandRegistryAccess);
@@ -250,8 +259,20 @@ @@ -252,6 +261,18 @@
if (environment.includeIntegrated) {
PublishCommand.register(this.dispatcher); PublishCommand.register(this.dispatcher);
+ } }
+
+ // Paper start - Vanilla command permission fixes + // Paper start - Vanilla command permission fixes
+ for (final CommandNode<CommandSourceStack> node : this.dispatcher.getRoot().getChildren()) { + for (final CommandNode<CommandSourceStack> node : this.dispatcher.getRoot().getChildren()) {
+ if (node.getRequirement() == com.mojang.brigadier.builder.ArgumentBuilder.<CommandSourceStack>defaultRequirement()) { + if (node.getRequirement() == com.mojang.brigadier.builder.ArgumentBuilder.<CommandSourceStack>defaultRequirement()) {
+ node.requirement = stack -> stack.source == CommandSource.NULL || stack.getBukkitSender().hasPermission(org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(node)); + node.requirement = stack -> stack.source == CommandSource.NULL || stack.getBukkitSender().hasPermission(org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(node));
+ } + }
} + }
+ // Paper end - Vanilla command permission fixes + // Paper end - Vanilla command permission fixes
+ // CraftBukkit start + // CraftBukkit start
+ } + }
+
+ public Commands() { + public Commands() {
+ // CraftBukkkit end + // CraftBukkkit end
this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer()); this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer());
} }
@@ -262,30 +283,78 @@ @@ -262,30 +283,69 @@
return new ParseResults(commandcontextbuilder1, parseResults.getReader(), parseResults.getExceptions()); return new ParseResults(commandcontextbuilder1, parseResults.getReader(), parseResults.getExceptions());
} }
@@ -68,16 +66,7 @@
+ String[] args = command.split(" "); + String[] args = command.split(" ");
+ if (args.length == 0) return; // Paper - empty commands shall not be dispatched + if (args.length == 0) return; // Paper - empty commands shall not be dispatched
+ +
+ String cmd = args[0]; + // Paper - Fix permission levels for command blocks
+ 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;
+ }
+ +
+ // Handle vanilla commands; + // Handle vanilla commands;
+ if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) { + if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) {
@@ -132,7 +121,7 @@
StackTraceElement[] astacktraceelement = exception.getStackTrace(); StackTraceElement[] astacktraceelement = exception.getStackTrace();
for (int i = 0; i < Math.min(astacktraceelement.length, 3); ++i) { 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) { if (SharedConstants.IS_RUNNING_IN_IDE) {
commandlistenerwrapper.sendFailure(Component.literal(Util.describeError(exception))); commandlistenerwrapper.sendFailure(Component.literal(Util.describeError(exception)));
@@ -141,7 +130,7 @@
} }
} finally { } finally {
Profiler.get().pop(); Profiler.get().pop();
@@ -307,18 +376,22 @@ @@ -307,18 +367,22 @@
} }
@Nullable @Nullable
@@ -170,7 +159,7 @@
}); });
if (i > 10) { if (i > 10) {
@@ -333,8 +406,18 @@ @@ -333,8 +397,18 @@
} }
ichatmutablecomponent.append((Component) Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC)); ichatmutablecomponent.append((Component) Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC));
@@ -190,7 +179,7 @@
return null; return null;
} }
@@ -368,7 +451,7 @@ @@ -368,7 +442,7 @@
executioncontext1.close(); executioncontext1.close();
} finally { } finally {
@@ -199,7 +188,7 @@
} }
} else { } else {
callback.accept(executioncontext); callback.accept(executioncontext);
@@ -377,22 +460,89 @@ @@ -377,22 +451,89 @@
} }
public void sendCommands(ServerPlayer player) { public void sendCommands(ServerPlayer player) {
@@ -294,7 +283,7 @@
argumentbuilder.requires((icompletionprovider) -> { argumentbuilder.requires((icompletionprovider) -> {
return true; return true;
@@ -415,12 +565,12 @@ @@ -415,12 +556,12 @@
argumentbuilder.redirect((CommandNode) resultNodes.get(argumentbuilder.getRedirect())); argumentbuilder.redirect((CommandNode) resultNodes.get(argumentbuilder.getRedirect()));
} }
@@ -309,7 +298,7 @@
} }
} }
} }
@@ -481,7 +631,7 @@ @@ -481,7 +622,7 @@
} }
private <T> HolderLookup.RegistryLookup.Delegate<T> createLookup(final HolderLookup.RegistryLookup<T> original) { private <T> HolderLookup.RegistryLookup.Delegate<T> createLookup(final HolderLookup.RegistryLookup<T> original) {

View File

@@ -1,6 +1,14 @@
--- a/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java --- a/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java
+++ b/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() { public boolean isValid() {
return !MinecartCommandBlock.this.isRemoved(); return !MinecartCommandBlock.this.isRemoved();
} }

View File

@@ -15,3 +15,12 @@
public void setCommand(String command) { public void setCommand(String command) {
super.setCommand(command); super.setCommand(command);
CommandBlockEntity.this.setChanged(); 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