diff --git a/fabric/src/main/java/me/lucko/luckperms/fabric/FabricCommandExecutor.java b/fabric/src/main/java/me/lucko/luckperms/fabric/FabricCommandExecutor.java index 8086bc3f6..3fcead276 100644 --- a/fabric/src/main/java/me/lucko/luckperms/fabric/FabricCommandExecutor.java +++ b/fabric/src/main/java/me/lucko/luckperms/fabric/FabricCommandExecutor.java @@ -26,7 +26,9 @@ package me.lucko.luckperms.fabric; import com.mojang.brigadier.Command; +import com.mojang.brigadier.StringReader; import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; @@ -35,12 +37,16 @@ import com.mojang.brigadier.tree.LiteralCommandNode; import me.lucko.luckperms.common.command.CommandManager; import me.lucko.luckperms.common.command.utils.ArgumentTokenizer; +import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.sender.Sender; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.minecraft.command.argument.EntityArgumentType; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; import java.util.List; +import java.util.ListIterator; import java.util.concurrent.CompletableFuture; import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; @@ -77,10 +83,11 @@ public class FabricCommandExecutor extends CommandManager implements Command ctx) { - Sender wrapped = this.plugin.getSenderFactory().wrap(ctx.getSource()); + ServerCommandSource source = ctx.getSource(); + Sender wrapped = this.plugin.getSenderFactory().wrap(source); int start = ctx.getRange().getStart(); - List arguments = ArgumentTokenizer.EXECUTE.tokenizeInput(ctx.getInput().substring(start)); + List arguments = resolveSelectors(source, ArgumentTokenizer.EXECUTE.tokenizeInput(ctx.getInput().substring(start))); String label = arguments.remove(0); if (label.startsWith("/")) { @@ -93,14 +100,15 @@ public class FabricCommandExecutor extends CommandManager implements Command getSuggestions(CommandContext ctx, SuggestionsBuilder builder) { - Sender wrapped = this.plugin.getSenderFactory().wrap(ctx.getSource()); + ServerCommandSource source = ctx.getSource(); + Sender wrapped = this.plugin.getSenderFactory().wrap(source); int idx = builder.getStart(); String buffer = ctx.getInput().substring(idx); idx += buffer.length(); - List arguments = ArgumentTokenizer.TAB_COMPLETE.tokenizeInput(buffer); + List arguments = resolveSelectors(source, ArgumentTokenizer.TAB_COMPLETE.tokenizeInput(buffer)); if (!arguments.isEmpty()) { idx -= arguments.get(arguments.size() - 1).length(); } @@ -115,4 +123,42 @@ public class FabricCommandExecutor extends CommandManager implements Command resolveSelectors(ServerCommandSource source, List args) { + if (!this.plugin.getConfiguration().get(ConfigKeys.RESOLVE_COMMAND_SELECTORS)) { + return args; + } + + // usage of @ selectors requires at least level 2 permission + ServerCommandSource atAllowedSource = source.hasPermissionLevel(2) ? source : source.withLevel(2); + for (ListIterator it = args.listIterator(); it.hasNext(); ) { + String arg = it.next(); + if (arg.isEmpty() || arg.charAt(0) != '@') { + continue; + } + + List matchedPlayers; + try { + matchedPlayers = EntityArgumentType.entities().parse(new StringReader(arg)).getPlayers(atAllowedSource); + } catch (CommandSyntaxException e) { + this.plugin.getLogger().warn("Error parsing selector '" + arg + "' for " + source + " executing " + args, e); + continue; + } + + if (matchedPlayers.isEmpty()) { + continue; + } + + if (matchedPlayers.size() > 1) { + this.plugin.getLogger().warn("Error parsing selector '" + arg + "' for " + source + " executing " + args + + ": ambiguous result (more than one player matched) - " + matchedPlayers); + continue; + } + + ServerPlayerEntity player = matchedPlayers.get(0); + it.set(player.getUuidAsString()); + } + + return args; + } + }