Search in sources :

Example 6 with CommandNode

use of com.mojang.brigadier.tree.CommandNode in project SpongeCommon by SpongePowered.

the class SpongeParameterTranslator method createCommandTree.

@SuppressWarnings({ "unchecked", "rawtypes" })
public Collection<LiteralCommandNode<CommandSourceStack>> createCommandTree(final Command.Parameterized command, final Collection<String> aliases) {
    if (aliases.isEmpty()) {
        throw new IllegalArgumentException("Aliases must not be empty.");
    }
    // create the first literal.
    final Collection<String> sortedAliases = aliases.stream().sorted().collect(Collectors.toList());
    final Iterator<String> aliasIterator = sortedAliases.iterator();
    final String baseAlias = aliasIterator.next();
    final SpongeCommandExecutorWrapper executor = command.executor().map(SpongeCommandExecutorWrapper::new).orElse(null);
    // Create the defining characteristics of the node.
    final LiteralArgumentBuilder<CommandSourceStack> basicNode = LiteralArgumentBuilder.literal(baseAlias);
    basicNode.requires((Predicate) command.executionRequirements());
    if (command.isTerminal() && executor != null) {
        basicNode.executes(executor);
    }
    final SpongeLiteralCommandNode commandNode = new SpongeLiteralCommandNode(basicNode);
    if (executor != null) {
        this.createAndAttachNode(Collections.singleton(commandNode), command.parameters(), executor, true, true);
    }
    for (final Parameter.Subcommand subcommand : command.subcommands()) {
        final Collection<LiteralCommandNode<CommandSourceStack>> builtSubcommand = this.createCommandTree(subcommand.command(), subcommand.aliases());
        builtSubcommand.forEach(commandNode::addChild);
    }
    this.createFlags(commandNode, command.flags(), executor);
    final List<LiteralCommandNode<CommandSourceStack>> allCommandNodes = new ArrayList<>();
    allCommandNodes.add(commandNode);
    final Collection<CommandNode<CommandSourceStack>> children = commandNode.getChildren();
    while (aliasIterator.hasNext()) {
        final LiteralArgumentBuilder<CommandSourceStack> redirectedNode = LiteralArgumentBuilder.literal(aliasIterator.next());
        redirectedNode.executes(commandNode.getCommand());
        redirectedNode.requires(commandNode.getRequirement());
        // merged, the above can be substituted in here.
        for (final CommandNode<CommandSourceStack> child : children) {
            redirectedNode.then(child);
        }
        allCommandNodes.add(new SpongeLiteralCommandNode(redirectedNode));
    }
    return Collections.unmodifiableCollection(allCommandNodes);
}
Also used : LiteralCommandNode(com.mojang.brigadier.tree.LiteralCommandNode) SpongeFlagLiteralCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeFlagLiteralCommandNode) SpongeLiteralCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeLiteralCommandNode) CommandNode(com.mojang.brigadier.tree.CommandNode) ArrayList(java.util.ArrayList) CommandSourceStack(net.minecraft.commands.CommandSourceStack) SpongeCommandExecutorWrapper(org.spongepowered.common.command.brigadier.tree.SpongeCommandExecutorWrapper) LiteralCommandNode(com.mojang.brigadier.tree.LiteralCommandNode) SpongeFlagLiteralCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeFlagLiteralCommandNode) SpongeLiteralCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeLiteralCommandNode) SpongeLiteralCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeLiteralCommandNode) Parameter(org.spongepowered.api.command.parameter.Parameter) SpongeMultiParameter(org.spongepowered.common.command.parameter.multi.SpongeMultiParameter) SpongeFirstOfParameter(org.spongepowered.common.command.parameter.multi.SpongeFirstOfParameter)

Example 7 with CommandNode

use of com.mojang.brigadier.tree.CommandNode in project SpongeCommon by SpongePowered.

the class CommandsMixin method impl$testPermissionAndPreventRecalculationWhenSendingNodes.

@Redirect(method = "fillUsableCommands", at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/tree/CommandNode;canUse(Ljava/lang/Object;)Z", remap = false))
private boolean impl$testPermissionAndPreventRecalculationWhenSendingNodes(final CommandNode<CommandSourceStack> commandNode, final Object source, final CommandNode<CommandSourceStack> rootCommandNode, final CommandNode<SharedSuggestionProvider> rootSuggestion, final CommandSourceStack sourceButTyped, final Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> commandNodeToSuggestionNode) {
    final ServerPlayer e = (ServerPlayer) sourceButTyped.getEntity();
    final Map<CommandNode<CommandSourceStack>, List<CommandNode<SharedSuggestionProvider>>> playerNodes = this.impl$playerNodeCache.get(e);
    final List<CommandNode<SharedSuggestionProvider>> existingNodes = playerNodes.get(commandNode);
    if (existingNodes != null) {
        if (!existingNodes.isEmpty()) {
            boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion);
            for (final CommandNode<SharedSuggestionProvider> node : existingNodes) {
                // Because we don't control the client, we have to work around it here.
                if (hasCustomSuggestionsAlready && node instanceof ArgumentCommandNode) {
                    final ArgumentCommandNode<SharedSuggestionProvider, ?> argNode = (ArgumentCommandNode<SharedSuggestionProvider, ?>) node;
                    if (argNode.getCustomSuggestions() != null) {
                        // Rebuild the node without the custom suggestions.
                        rootSuggestion.addChild(this.impl$cloneArgumentCommandNodeWithoutSuggestions(argNode));
                        continue;
                    }
                } else if (node instanceof ArgumentCommandNode && ((ArgumentCommandNode<?, ?>) node).getCustomSuggestions() != null) {
                    // no more custom suggestions
                    hasCustomSuggestionsAlready = true;
                }
                rootSuggestion.addChild(node);
            }
        }
        // If empty, we have a node won't resolve (even if not complex), so we ignore it.
        return false;
    // If we have already processed this node and it appears in the suggestion node list, prevent a potentially costly
    // canUse check as we know we can already use it.
    } else if (!commandNodeToSuggestionNode.containsKey(commandNode) && !SpongeNodePermissionCache.canUse(rootCommandNode instanceof RootCommandNode, this.impl$commandManager.getDispatcher(), commandNode, sourceButTyped)) {
        playerNodes.put(commandNode, Collections.emptyList());
        return false;
    }
    if (commandNode instanceof SpongeArgumentCommandNode && ((SpongeArgumentCommandNode<?>) commandNode).isComplex()) {
        final boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion);
        final CommandNode<SharedSuggestionProvider> finalCommandNode = ((SpongeArgumentCommandNode<?>) commandNode).getComplexSuggestions(rootSuggestion, commandNodeToSuggestionNode, playerNodes, !hasCustomSuggestionsAlready);
        if (!this.impl$getChildrenFromNode(commandNode).isEmpty()) {
            this.shadow$fillUsableCommands(commandNode, finalCommandNode, sourceButTyped, commandNodeToSuggestionNode);
        }
        return false;
    }
    // Normal node, handle it normally. We don't add to the playerNodeCache - the commandNodeToSuggestionNode map handles this.
    return true;
}
Also used : SpongeArgumentCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode) ArgumentCommandNode(com.mojang.brigadier.tree.ArgumentCommandNode) SpongeArgumentCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode) ArgumentCommandNode(com.mojang.brigadier.tree.ArgumentCommandNode) RootCommandNode(com.mojang.brigadier.tree.RootCommandNode) SpongeArgumentCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode) CommandNode(com.mojang.brigadier.tree.CommandNode) RootCommandNode(com.mojang.brigadier.tree.RootCommandNode) ServerPlayer(net.minecraft.server.level.ServerPlayer) ArrayList(java.util.ArrayList) List(java.util.List) SharedSuggestionProvider(net.minecraft.commands.SharedSuggestionProvider) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 8 with CommandNode

use of com.mojang.brigadier.tree.CommandNode in project SpongeCommon by SpongePowered.

the class CommandsMixin method impl$addNonBrigSuggestions.

@Redirect(method = "sendCommands", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/Commands;fillUsableCommands(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Lnet/minecraft/commands/CommandSourceStack;Ljava/util/Map;)V"))
private void impl$addNonBrigSuggestions(final Commands commands, final CommandNode<CommandSourceStack> p_197052_1_, final CommandNode<SharedSuggestionProvider> p_197052_2_, final CommandSourceStack p_197052_3_, final Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> p_197052_4_, final ServerPlayer playerEntity) {
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        frame.addContext(EventContextKeys.SUBJECT, (Subject) playerEntity);
        final CommandCause sourceToUse = ((CommandSourceStackBridge) p_197052_3_).bridge$withCurrentCause();
        try {
            this.impl$playerNodeCache.put(playerEntity, new IdentityHashMap<>());
            // We use this because the redirects should be a 1:1 mapping (which is what this map is for).
            final IdentityHashMap<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> idMap = new IdentityHashMap<>(p_197052_4_);
            this.shadow$fillUsableCommands(p_197052_1_, p_197052_2_, (CommandSourceStack) sourceToUse, idMap);
        } finally {
            this.impl$playerNodeCache.remove(playerEntity);
        }
        for (final CommandNode<SharedSuggestionProvider> node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) {
            p_197052_2_.addChild(node);
        }
    }
}
Also used : ArgumentCommandNode(com.mojang.brigadier.tree.ArgumentCommandNode) RootCommandNode(com.mojang.brigadier.tree.RootCommandNode) SpongeArgumentCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode) CommandNode(com.mojang.brigadier.tree.CommandNode) CauseStackManager(org.spongepowered.api.event.CauseStackManager) IdentityHashMap(java.util.IdentityHashMap) CommandSourceStackBridge(org.spongepowered.common.bridge.commands.CommandSourceStackBridge) CommandCause(org.spongepowered.api.command.CommandCause) SharedSuggestionProvider(net.minecraft.commands.SharedSuggestionProvider) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Aggregations

CommandNode (com.mojang.brigadier.tree.CommandNode)8 ArrayList (java.util.ArrayList)6 CommandSourceStack (net.minecraft.commands.CommandSourceStack)6 LiteralCommandNode (com.mojang.brigadier.tree.LiteralCommandNode)5 RootCommandNode (com.mojang.brigadier.tree.RootCommandNode)5 SpongeArgumentCommandNode (org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode)5 SpongeNode (org.spongepowered.common.command.brigadier.tree.SpongeNode)4 ArgumentCommandNode (com.mojang.brigadier.tree.ArgumentCommandNode)3 List (java.util.List)3 SharedSuggestionProvider (net.minecraft.commands.SharedSuggestionProvider)3 Redirect (org.spongepowered.asm.mixin.injection.Redirect)3 SpongeFlagLiteralCommandNode (org.spongepowered.common.command.brigadier.tree.SpongeFlagLiteralCommandNode)3 SpongeLiteralCommandNode (org.spongepowered.common.command.brigadier.tree.SpongeLiteralCommandNode)3 CommandSyntaxException (com.mojang.brigadier.exceptions.CommandSyntaxException)2 Suggestions (com.mojang.brigadier.suggestion.Suggestions)2 SuggestionsBuilder (com.mojang.brigadier.suggestion.SuggestionsBuilder)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 Parameter (org.spongepowered.api.command.parameter.Parameter)2 CauseStackManager (org.spongepowered.api.event.CauseStackManager)2 CommandSourceStackBridge (org.spongepowered.common.bridge.commands.CommandSourceStackBridge)2