Search in sources :

Example 11 with CommandSourceStack

use of net.minecraft.commands.CommandSourceStack in project SpongeCommon by SpongePowered.

the class SpongeCommandDispatcher method parseNodes.

private ParseResults<CommandSourceStack> parseNodes(// Sponge: used in permission checks
final boolean isRoot, // Sponge: needed for handling what we do with defaults.
final boolean isSuggestion, final CommandNode<CommandSourceStack> node, final SpongeStringReader originalReader, final SpongeCommandContextBuilder contextSoFar) {
    final CommandSourceStack source = contextSoFar.getSource();
    // Sponge Start
    Map<CommandNode<CommandSourceStack>, CommandSyntaxException> errors = null;
    List<ParseResults<CommandSourceStack>> potentials = null;
    // Sponge End
    final int cursor = originalReader.getCursor();
    // Sponge Start: get relevant nodes if we're completing
    final Collection<? extends CommandNode<CommandSourceStack>> nodes;
    if (isSuggestion && node instanceof SpongeNode) {
        nodes = ((SpongeNode) node).getRelevantNodesForSuggestions(originalReader);
    } else if (originalReader.canRead()) {
        nodes = node.getRelevantNodes(originalReader);
    } else {
        // Reader cannot read anymore so ONLY nodes with parsers that do not read can be processed
        nodes = node.getChildren().stream().filter(n -> n instanceof SpongeArgumentCommandNode && (((SpongeArgumentCommandNode<?>) n).getParser().doesNotRead())).collect(Collectors.toList());
    }
    for (final CommandNode<CommandSourceStack> child : nodes) {
        final boolean doesNotRead = child instanceof SpongeArgumentCommandNode && ((SpongeArgumentCommandNode<?>) child).getParser().doesNotRead();
        // if (!child.canUse(source)) {
        if (!SpongeNodePermissionCache.canUse(isRoot, this, child, source)) {
            // Sponge End
            continue;
        }
        // Sponge Start
        final SpongeCommandContextBuilder context = contextSoFar.copy();
        final SpongeStringReader reader = new SpongeStringReader(originalReader);
        // Sponge End
        try {
            try {
                child.parse(reader, context);
            } catch (final RuntimeException ex) {
                throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException().createWithContext(reader, ex.getMessage());
            }
            // Sponge Start: if we didn't consume anything we don't want Brig to complain at us.
            if (reader.getCursor() == cursor) {
                // of suggestions.
                if (isSuggestion && !reader.canRead()) {
                    throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherExpectedArgumentSeparator().createWithContext(reader);
                }
                reader.unskipWhitespace();
            } else if (reader.canRead()) {
                // Sponge End
                if (reader.peek() != CommandDispatcher.ARGUMENT_SEPARATOR_CHAR) {
                    throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherExpectedArgumentSeparator().createWithContext(reader);
                }
            }
        } catch (final CommandSyntaxException ex) {
            if (errors == null) {
                errors = new LinkedHashMap<>();
            }
            errors.put(child, ex);
            reader.setCursor(cursor);
            continue;
        }
        context.withCommand(child.getCommand());
        // must let it do so.
        if (this.shouldContinueTraversing(reader, child)) {
            // if (reader.canRead(child.getRedirect() == null ? 2 : 1)) {
            // Sponge End
            reader.skip();
            // Sponge Start: redirect is now in a local variable as we use it a fair bit
            final CommandNode<CommandSourceStack> redirect = child.getRedirect();
            if (redirect != null) {
                // If we've redirected to the root node, we may need to head back to our command
                // manager - so we should check to see if that's going to actually be the case.
                final boolean redirectingToRoot = redirect == this.getRoot();
                final SpongeCommandContextBuilder childContext = new SpongeCommandContextBuilder(this, source, child.getRedirect(), reader.getCursor());
                // For a redirect, we want to ensure all of our currently parsed information is available.
                context.applySpongeElementsTo(childContext, false);
                ParseResults<CommandSourceStack> parse = null;
                if (redirectingToRoot) {
                    // check to see if we can get an element
                    final ArgumentReader.Immutable snapshot = reader.immutable();
                    try {
                        final String commandToAttempt = reader.peekString();
                        final int offset = reader.cursor();
                        if (redirect.getChild(commandToAttempt) == null) {
                            // The redirect fails, so we intercept here, and reroute to our command
                            // manager with the rest of the string and the new context.
                            reader.parseString();
                            final boolean hasMore = reader.canRead();
                            reader.skipWhitespace();
                            final Optional<CommandMapping> optionalMapping = this.commandManager.commandMapping(commandToAttempt);
                            if (optionalMapping.isPresent()) {
                                final CommandMapping mapping = optionalMapping.get();
                                final String remaining = reader.remaining();
                                childContext.withCommand(commandContext -> {
                                    final SpongeCommandContext spongeContext = (SpongeCommandContext) commandContext;
                                    try {
                                        return mapping.registrar().process(spongeContext.cause(), mapping, commandToAttempt, remaining).result();
                                    } catch (final CommandException e) {
                                        throw new SpongeCommandSyntaxException(e, spongeContext);
                                    }
                                });
                                childContext.withNode(new DummyCommandNode(childContext.getCommand()), StringRange.between(offset, reader.totalLength()));
                                childContext.setNonBrigCommand(hasMore ? new String[] { commandToAttempt, remaining } : new String[] { commandToAttempt });
                                reader.setCursor(reader.totalLength());
                                parse = new ParseResults<>(childContext, reader, Collections.emptyMap());
                            } else {
                                // We'll just let this parser fail as normal.
                                reader.setState(snapshot);
                            }
                        }
                    } catch (final ArgumentParseException ignored) {
                        // ignore it, it'll handle it later.
                        reader.setState(snapshot);
                    }
                }
                if (parse == null) {
                    parse = this.parseNodes(redirect instanceof RootCommandNode, isSuggestion, child.getRedirect(), reader, childContext);
                }
                // It worked out, so let's apply it back. We clear and reapply, it's simpler than comparing and conditional adding.
                childContext.applySpongeElementsTo(context, true);
                // Sponge End
                context.withChild(parse.getContext());
                final ParseResults<CommandSourceStack> parse2 = new ParseResults<>(context, parse.getReader(), parse.getExceptions());
                if (doesNotRead && potentials != null) {
                    // If this is a optional or default parameter we only add the redirect as a potential option
                    potentials.add(parse2);
                    continue;
                }
                return parse2;
            } else {
                final ParseResults<CommandSourceStack> parse = this.parseNodes(false, isSuggestion, child, reader, context);
                if (potentials == null) {
                    potentials = new ArrayList<>(1);
                }
                potentials.add(parse);
            }
        } else {
            if (potentials == null) {
                potentials = new ArrayList<>(1);
            }
            potentials.add(new ParseResults<>(context, reader, Collections.emptyMap()));
        }
    }
    if (potentials != null) {
        if (potentials.size() > 1) {
            potentials.sort((a, b) -> {
                if (!a.getReader().canRead() && b.getReader().canRead()) {
                    return -1;
                }
                if (a.getReader().canRead() && !b.getReader().canRead()) {
                    return 1;
                }
                if (a.getExceptions().isEmpty() && !b.getExceptions().isEmpty()) {
                    return -1;
                }
                if (!a.getExceptions().isEmpty() && b.getExceptions().isEmpty()) {
                    return 1;
                }
                // If we get here both potentials parsed everything and there was no exception
                // BUT if parsing stopped at a non-terminal node this will cause an error later
                // see at the end of #execute() where !foundCommand
                // Instead we attempt to sort commands before that happens
                final Command<CommandSourceStack> aCommand = SpongeCommandDispatcher.getCommand(a.getContext());
                final Command<CommandSourceStack> bCommand = SpongeCommandDispatcher.getCommand(b.getContext());
                if (aCommand == null && bCommand != null) {
                    return 1;
                } else if (aCommand != null && bCommand == null) {
                    return -1;
                }
                return 0;
            });
        }
        return potentials.get(0);
    }
    return new ParseResults<>(contextSoFar, originalReader, errors == null ? Collections.emptyMap() : errors);
}
Also used : LiteralCommandNode(com.mojang.brigadier.tree.LiteralCommandNode) CommandDispatcher(com.mojang.brigadier.CommandDispatcher) EventContextKeys(org.spongepowered.api.event.EventContextKeys) CommandSourceStack(net.minecraft.commands.CommandSourceStack) Command(com.mojang.brigadier.Command) CommandContextBuilder(com.mojang.brigadier.context.CommandContextBuilder) CompletableFuture(java.util.concurrent.CompletableFuture) SpongeAdventure(org.spongepowered.common.adventure.SpongeAdventure) RedirectModifier(com.mojang.brigadier.RedirectModifier) SuggestionContext(com.mojang.brigadier.context.SuggestionContext) SpongeCommandContextBuilder(org.spongepowered.common.command.brigadier.context.SpongeCommandContextBuilder) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) CommandSourceStackBridge(org.spongepowered.common.bridge.commands.CommandSourceStackBridge) Map(java.util.Map) DummyCommandNode(org.spongepowered.common.command.brigadier.tree.DummyCommandNode) StringReader(com.mojang.brigadier.StringReader) SpongeRootCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeRootCommandNode) CauseStackManager(org.spongepowered.api.event.CauseStackManager) SuggestionsBuilder(com.mojang.brigadier.suggestion.SuggestionsBuilder) RootCommandNode(com.mojang.brigadier.tree.RootCommandNode) SpongeCommandSyntaxException(org.spongepowered.common.command.exception.SpongeCommandSyntaxException) Suggestions(com.mojang.brigadier.suggestion.Suggestions) CommandContext(com.mojang.brigadier.context.CommandContext) CommandUtil(org.spongepowered.common.util.CommandUtil) Collection(java.util.Collection) ArgumentReader(org.spongepowered.api.command.parameter.ArgumentReader) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) Collectors(java.util.stream.Collectors) CommandMapping(org.spongepowered.api.command.manager.CommandMapping) AmbiguityConsumer(com.mojang.brigadier.AmbiguityConsumer) List(java.util.List) SpongeStringReader(org.spongepowered.common.command.brigadier.SpongeStringReader) ArgumentParseException(org.spongepowered.api.command.exception.ArgumentParseException) SpongeCommandContext(org.spongepowered.common.command.brigadier.context.SpongeCommandContext) ParseResults(com.mojang.brigadier.ParseResults) SpongeArgumentCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode) CommandNode(com.mojang.brigadier.tree.CommandNode) Optional(java.util.Optional) ResultConsumer(com.mojang.brigadier.ResultConsumer) CommandSyntaxException(com.mojang.brigadier.exceptions.CommandSyntaxException) CommandManager(org.spongepowered.api.command.manager.CommandManager) SpongeNode(org.spongepowered.common.command.brigadier.tree.SpongeNode) Collections(java.util.Collections) StringRange(com.mojang.brigadier.context.StringRange) CommandException(org.spongepowered.api.command.exception.CommandException) SpongeCommandManager(org.spongepowered.common.command.manager.SpongeCommandManager) DummyCommandNode(org.spongepowered.common.command.brigadier.tree.DummyCommandNode) LiteralCommandNode(com.mojang.brigadier.tree.LiteralCommandNode) DummyCommandNode(org.spongepowered.common.command.brigadier.tree.DummyCommandNode) SpongeRootCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeRootCommandNode) RootCommandNode(com.mojang.brigadier.tree.RootCommandNode) SpongeArgumentCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode) CommandNode(com.mojang.brigadier.tree.CommandNode) SpongeRootCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeRootCommandNode) RootCommandNode(com.mojang.brigadier.tree.RootCommandNode) ArgumentParseException(org.spongepowered.api.command.exception.ArgumentParseException) CommandSourceStack(net.minecraft.commands.CommandSourceStack) SpongeCommandContextBuilder(org.spongepowered.common.command.brigadier.context.SpongeCommandContextBuilder) LinkedHashMap(java.util.LinkedHashMap) SpongeStringReader(org.spongepowered.common.command.brigadier.SpongeStringReader) CommandMapping(org.spongepowered.api.command.manager.CommandMapping) SpongeNode(org.spongepowered.common.command.brigadier.tree.SpongeNode) SpongeCommandSyntaxException(org.spongepowered.common.command.exception.SpongeCommandSyntaxException) CommandSyntaxException(com.mojang.brigadier.exceptions.CommandSyntaxException) SpongeArgumentCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode) ArgumentReader(org.spongepowered.api.command.parameter.ArgumentReader) CommandException(org.spongepowered.api.command.exception.CommandException) SpongeCommandSyntaxException(org.spongepowered.common.command.exception.SpongeCommandSyntaxException) ParseResults(com.mojang.brigadier.ParseResults) SpongeCommandContext(org.spongepowered.common.command.brigadier.context.SpongeCommandContext)

Example 12 with CommandSourceStack

use of net.minecraft.commands.CommandSourceStack in project SpongeCommon by SpongePowered.

the class SpongeCommandDispatcher method execute.

@Override
public int execute(final ParseResults<CommandSourceStack> parse) throws CommandSyntaxException {
    if (parse.getReader().canRead()) {
        // TODO plugin exception handling here
        if (parse.getExceptions().size() == 1) {
            throw parse.getExceptions().values().iterator().next();
        } else if (parse.getContext().getRange().isEmpty()) {
            throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parse.getReader());
        } else {
            throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(parse.getReader());
        // throw new SimpleCommandExceptionType(new LiteralMessage("Too many arguments")).createWithContext(parse.getReader());
        }
    }
    int result = 0;
    int successfulForks = 0;
    boolean forked = false;
    boolean foundCommand = false;
    final String command = parse.getReader().getString();
    final CommandContext<CommandSourceStack> original = parse.getContext().build(command);
    List<CommandContext<CommandSourceStack>> contexts = Collections.singletonList(original);
    ArrayList<CommandContext<CommandSourceStack>> next = null;
    while (contexts != null) {
        final int size = contexts.size();
        for (int i = 0; i < size; i++) {
            final CommandContext<CommandSourceStack> context = contexts.get(i);
            final CommandContext<CommandSourceStack> child = context.getChild();
            if (child != null) {
                forked |= context.isForked();
                if (child.hasNodes()) {
                    // Sponge Start
                    // 
                    // Basically, no we haven't Mojang. Getting here is no guarantee that a
                    // command executes. I imagine what's happened is that this was originally
                    // recursive and called itself, by doing so, setting this true made sense
                    // while the child method handled whether something worked out or not, but
                    // design reasons would mean that wouldn't work.
                    // 
                    // It's not obvious what this is really meant to achieve, because by setting
                    // this true here, context.onCommandComplete(...) may never be called.
                    // 
                    // We want a command to run, that's only in the else if down below.
                    // 
                    // foundCommand = true
                    // Sponge End
                    final RedirectModifier<CommandSourceStack> modifier = context.getRedirectModifier();
                    if (modifier == null) {
                        if (next == null) {
                            next = new ArrayList<>(1);
                        }
                        next.add(child.copyFor(context.getSource()));
                    } else {
                        try {
                            final Collection<CommandSourceStack> results = modifier.apply(context);
                            if (!results.isEmpty()) {
                                if (next == null) {
                                    next = new ArrayList<>(results.size());
                                }
                                for (final CommandSourceStack source : results) {
                                    next.add(child.copyFor(source));
                                }
                            }
                        } catch (final CommandSyntaxException ex) {
                            // Sponge Start: They probably meant to do this here - the consumer is notified at this point.
                            foundCommand = true;
                            // Soonge End
                            this.resultConsumer.onCommandComplete(context, false, 0);
                            if (!forked) {
                                throw ex;
                            }
                        }
                    }
                }
            } else if (context.getCommand() != null) {
                foundCommand = true;
                try {
                    final int value = context.getCommand().run(context);
                    result += value;
                    this.resultConsumer.onCommandComplete(context, true, value);
                    successfulForks++;
                } catch (final CommandSyntaxException ex) {
                    this.resultConsumer.onCommandComplete(context, false, 0);
                    if (!forked) {
                        throw ex;
                    }
                }
            }
        }
        contexts = next;
        next = null;
    }
    if (!foundCommand) {
        this.resultConsumer.onCommandComplete(original, false, 0);
        throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parse.getReader());
    }
    return forked ? successfulForks : result;
}
Also used : CommandContext(com.mojang.brigadier.context.CommandContext) SpongeCommandContext(org.spongepowered.common.command.brigadier.context.SpongeCommandContext) CommandSourceStack(net.minecraft.commands.CommandSourceStack) SpongeCommandSyntaxException(org.spongepowered.common.command.exception.SpongeCommandSyntaxException) CommandSyntaxException(com.mojang.brigadier.exceptions.CommandSyntaxException)

Example 13 with CommandSourceStack

use of net.minecraft.commands.CommandSourceStack in project SpongeCommon by SpongePowered.

the class SpongeArgumentCommandNode method parse.

@Override
public final void parse(final StringReader reader, final CommandContextBuilder<CommandSourceStack> contextBuilder) throws CommandSyntaxException {
    final int start = reader.getCursor();
    final SpongeCommandContextBuilder builder = (SpongeCommandContextBuilder) contextBuilder;
    final T result = this.parser.parse(this.key, builder, (SpongeStringReader) reader, this.modifier);
    if (result != null) {
        builder.putEntry(this.key, result);
        final ParsedArgument<CommandSourceStack, T> parsed = new ParsedArgument<>(start, reader.getCursor(), result);
        builder.withArgumentInternal(this.getName(), parsed, false);
        builder.withNode(this, parsed.getRange());
    } else if (this.parser.doesNotRead()) {
        // Assume this is a null "optional" parser and add the node as read so that we dont end up with an empty context
        builder.withNode(this, StringRange.at(start));
    }
}
Also used : ParsedArgument(com.mojang.brigadier.context.ParsedArgument) CommandSourceStack(net.minecraft.commands.CommandSourceStack) SpongeCommandContextBuilder(org.spongepowered.common.command.brigadier.context.SpongeCommandContextBuilder)

Example 14 with CommandSourceStack

use of net.minecraft.commands.CommandSourceStack in project SpongeCommon by SpongePowered.

the class SpongeParameterTranslator method createAndAttachNode.

private Collection<? extends CommandNode<CommandSourceStack>> createAndAttachNode(final Collection<? extends CommandNode<CommandSourceStack>> parents, final List<Parameter> children, @Nullable final SpongeCommandExecutorWrapper executorWrapper, final boolean shouldTerminate, final boolean allowSubcommands) {
    final Set<CommandNode<CommandSourceStack>> nodesToAttachTo = new HashSet<>(parents);
    final ListIterator<Parameter> parameterIterator = children.listIterator();
    while (parameterIterator.hasNext()) {
        final Parameter parameter = parameterIterator.next();
        final boolean hasNext = parameterIterator.hasNext();
        if (parameter instanceof Parameter.Subcommand) {
            final Parameter.Subcommand subcommands = ((Parameter.Subcommand) parameter);
            if (!allowSubcommands) {
                throw new IllegalStateException("Subcommands are not allowed for this element (subcommands were " + String.join(", ", subcommands.aliases() + ")!"));
            }
            if (hasNext) {
                // this is a failure condition because there cannot be a parameter after a subcommand.
                throw new IllegalStateException("A parameter cannot be placed after a subcommand parameter!");
            }
            // If the child is a subcommand, get the subcommand and attach it. At this point,
            // we're done with the chain and we break out.
            final Collection<LiteralCommandNode<CommandSourceStack>> nodes = this.createCommandTree(subcommands.command(), subcommands.aliases());
            for (final LiteralCommandNode<CommandSourceStack> node : nodes) {
                nodesToAttachTo.forEach(x -> x.addChild(node));
            }
            // No further attaching should be done in this scenario
            return Collections.emptyList();
        } else {
            final boolean isOptional;
            final boolean isTerminal;
            final Collection<CommandNode<CommandSourceStack>> parametersToAttachTo;
            if (parameter instanceof SpongeMultiParameter) {
                isOptional = parameter.isOptional();
                isTerminal = !hasNext || parameter.isTerminal();
                // In these cases, we delegate to the parameter, which may return here.
                if (parameter instanceof SpongeFirstOfParameter) {
                    // take each parameter in turn and evaluate it, returns the terminal nodes of each block
                    parametersToAttachTo = new ArrayList<>();
                    for (final Parameter p : ((SpongeFirstOfParameter) parameter).childParameters()) {
                        final Collection<? extends CommandNode<CommandSourceStack>> branchNodesToAttachTo = this.createAndAttachNode(nodesToAttachTo, Collections.singletonList(p), executorWrapper, isTerminal, allowSubcommands);
                        parametersToAttachTo.addAll(branchNodesToAttachTo);
                    }
                } else {
                    // not so fancy stuff, it's a sequence, returns the terminal nodes of the block
                    parametersToAttachTo = new ArrayList<>(this.createAndAttachNode(nodesToAttachTo, ((SpongeMultiParameter) parameter).childParameters(), executorWrapper, isTerminal, allowSubcommands));
                }
            } else {
                // We have a Parameter.Value
                parametersToAttachTo = new ArrayList<>();
                final SpongeParameterValue<?> valueParameter = (SpongeParameterValue<?>) parameter;
                final boolean isConsumeAll = valueParameter.willConsumeAllRemaining();
                if (isConsumeAll && hasNext) {
                    // this should not happen.
                    throw new IllegalStateException("A parameter that consumes all must be at the end of a parameter chain.");
                }
                isOptional = valueParameter.isOptional();
                isTerminal = (shouldTerminate && !hasNext) || valueParameter.isTerminal();
                // Process the next element if it exists
                StringBuilder suffix = null;
                final Set<String> names = nodesToAttachTo.stream().flatMap(x -> x.getChildren().stream()).map(CommandNode::getName).collect(Collectors.toSet());
                String key = valueParameter.key().key();
                while (names.contains(key)) {
                    if (suffix == null) {
                        suffix = new StringBuilder(String.valueOf(names.size()));
                    } else {
                        suffix.append("_").append(names.size());
                    }
                    // prevents duplication
                    key = key + suffix;
                }
                final SpongeArgumentCommandNodeBuilder<?> thisNode = SpongeParameterTranslator.createArgumentNodeBuilders(valueParameter, suffix == null ? null : suffix.toString());
                if (isTerminal) {
                    thisNode.executes(executorWrapper);
                }
                // Apply the node to the parent.
                final CommandNode<CommandSourceStack> builtNode = thisNode.build();
                if (isConsumeAll) {
                    // the built child will return to the previous node, which will allow this to be called again.
                    builtNode.addChild(thisNode.redirect(builtNode).build());
                }
                parametersToAttachTo.add(builtNode);
                // Make sure the nodes we need to attach to have the nodes we need to
                nodesToAttachTo.forEach(x -> x.addChild(builtNode));
            }
            // If this is not optional, then we clear the "toAttachTo" list because we do not want to skip the parameter.
            if (!isOptional) {
                nodesToAttachTo.clear();
            }
            nodesToAttachTo.addAll(parametersToAttachTo);
        }
    }
    // If we should make any terminal parameters actually terminal, we do that now.
    if (shouldTerminate) {
        for (final CommandNode<CommandSourceStack> node : nodesToAttachTo) {
            // These are therefore terminal.
            if (node instanceof SpongeNode) {
                // they should be, but just in case
                ((SpongeNode) node).forceExecutor(executorWrapper);
            }
        }
    }
    return nodesToAttachTo;
}
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) CommandSourceStack(net.minecraft.commands.CommandSourceStack) LiteralCommandNode(com.mojang.brigadier.tree.LiteralCommandNode) SpongeFlagLiteralCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeFlagLiteralCommandNode) SpongeLiteralCommandNode(org.spongepowered.common.command.brigadier.tree.SpongeLiteralCommandNode) SpongeNode(org.spongepowered.common.command.brigadier.tree.SpongeNode) HashSet(java.util.HashSet) SpongeParameterValue(org.spongepowered.common.command.parameter.SpongeParameterValue) SpongeMultiParameter(org.spongepowered.common.command.parameter.multi.SpongeMultiParameter) Parameter(org.spongepowered.api.command.parameter.Parameter) SpongeMultiParameter(org.spongepowered.common.command.parameter.multi.SpongeMultiParameter) SpongeFirstOfParameter(org.spongepowered.common.command.parameter.multi.SpongeFirstOfParameter) SpongeFirstOfParameter(org.spongepowered.common.command.parameter.multi.SpongeFirstOfParameter)

Example 15 with CommandSourceStack

use of net.minecraft.commands.CommandSourceStack 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)

Aggregations

CommandSourceStack (net.minecraft.commands.CommandSourceStack)23 CommandNode (com.mojang.brigadier.tree.CommandNode)6 ArrayList (java.util.ArrayList)6 CommandSyntaxException (com.mojang.brigadier.exceptions.CommandSyntaxException)5 LiteralCommandNode (com.mojang.brigadier.tree.LiteralCommandNode)5 Map (java.util.Map)5 TextComponent (net.minecraft.network.chat.TextComponent)5 Suggestions (com.mojang.brigadier.suggestion.Suggestions)4 HashMap (java.util.HashMap)4 List (java.util.List)4 ServerLevel (net.minecraft.server.level.ServerLevel)4 ResultConsumer (com.mojang.brigadier.ResultConsumer)3 StringReader (com.mojang.brigadier.StringReader)3 CommandContext (com.mojang.brigadier.context.CommandContext)3 Collectors (java.util.stream.Collectors)3 CommandSource (net.minecraft.commands.CommandSource)3 Component (net.minecraft.network.chat.Component)3 Vec2 (net.minecraft.world.phys.Vec2)3 CauseStackManager (org.spongepowered.api.event.CauseStackManager)3 EventContextKeys (org.spongepowered.api.event.EventContextKeys)3