Resolve command entity selectors on Fabric (#3363)

This commit is contained in:
Emily 2022-04-24 05:44:24 -03:00 committed by GitHub
parent b3cdf67c4f
commit e0ee2c3b5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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<Ser
@Override
public int run(CommandContext<ServerCommandSource> 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<String> arguments = ArgumentTokenizer.EXECUTE.tokenizeInput(ctx.getInput().substring(start));
List<String> 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<Ser
@Override
public CompletableFuture<Suggestions> getSuggestions(CommandContext<ServerCommandSource> 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<String> arguments = ArgumentTokenizer.TAB_COMPLETE.tokenizeInput(buffer);
List<String> 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<Ser
return builder.buildFuture();
}
private List<String> resolveSelectors(ServerCommandSource source, List<String> 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<String> it = args.listIterator(); it.hasNext(); ) {
String arg = it.next();
if (arg.isEmpty() || arg.charAt(0) != '@') {
continue;
}
List<ServerPlayerEntity> 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;
}
}