Skip to content

Commit

Permalink
Add ability to get the executed Command.Parameterized from the Comman…
Browse files Browse the repository at this point in the history
…dContext
  • Loading branch information
dualspiral committed Sep 7, 2020
1 parent 25f5e1f commit c6ffa7e
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 28 deletions.
2 changes: 1 addition & 1 deletion SpongeAPI
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,7 @@ public LiteralCommandNode<CommandSource> buildWithAlias(final String primaryAlia
if (this.executor == null) {
return (LiteralCommandNode<CommandSource>) SpongeParameterTranslator.createCommandTreeWithSubcommandsOnly(primary, this.subcommands);
} else {
return (LiteralCommandNode<CommandSource>) SpongeParameterTranslator.createCommandTree(
primary,
this.flags,
this.parameters,
this.subcommands,
this
);
return (LiteralCommandNode<CommandSource>) SpongeParameterTranslator.createCommandTree(primary, this);
}
}

Expand All @@ -187,7 +181,7 @@ public Collection<LiteralCommandNode<CommandSource>> buildWithAliases(final Iter
final LiteralArgumentBuilder<CommandSource> secondary = LiteralArgumentBuilder.literal(iterable.next());
secondary.executes(built.getCommand());
secondary.requires(built.getRequirement());
nodes.add(new SpongeLiteralCommandNode(secondary.redirect(built)));
nodes.add(new SpongeLiteralCommandNode(secondary.redirect(built), this));
}

return nodes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import net.minecraft.command.CommandSource;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.command.CommandExecutor;
import org.spongepowered.api.command.parameter.Parameter;
import org.spongepowered.api.command.parameter.managed.Flag;
import org.spongepowered.api.command.parameter.managed.ValueCompleter;
Expand Down Expand Up @@ -72,28 +71,25 @@ public static CommandNode<CommandSource> createCommandTreeWithSubcommandsOnly(
@SuppressWarnings({"unchecked"})
public static CommandNode<CommandSource> createCommandTree(
@NonNull final ArgumentBuilder<CommandSource, ?> rootNode,
@NonNull final List<Flag> flags,
@NonNull final List<Parameter> parameters,
@NonNull final List<Parameter.Subcommand> subcommands,
@NonNull final CommandExecutor executor) {
@NonNull final SpongeParameterizedCommand command) {

final SpongeCommandExecutorWrapper executorWrapper = new SpongeCommandExecutorWrapper(executor);
final ListIterator<Parameter> parameterListIterator = parameters.listIterator();
final SpongeCommandExecutorWrapper executorWrapper = new SpongeCommandExecutorWrapper(command);
final ListIterator<Parameter> parameterListIterator = command.parameters().listIterator();

// If we have no parameters, or they are all optional, all literals will get an executor.
final boolean isTerminal = SpongeParameterTranslator.createNode(
parameterListIterator, executorWrapper, rootNode::then, null, new ArrayList<>(), true);
if (isTerminal) {
rootNode.executes(executorWrapper);
}
SpongeParameterTranslator.createSubcommands(rootNode, subcommands);
SpongeParameterTranslator.createSubcommands(rootNode, command.subcommands());
final CommandNode<CommandSource> builtNode;
if (rootNode instanceof LiteralArgumentBuilder) {
builtNode = new SpongeLiteralCommandNode((LiteralArgumentBuilder<CommandSource>) rootNode);
builtNode = new SpongeLiteralCommandNode((LiteralArgumentBuilder<CommandSource>) rootNode, command);
} else {
builtNode = rootNode.build();
}
SpongeParameterTranslator.createFlags(flags, builtNode, isTerminal ? executorWrapper : null);
SpongeParameterTranslator.createFlags(command.flags(), builtNode, isTerminal ? executorWrapper : null);
return builtNode;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import net.kyori.adventure.text.Component;
import net.minecraft.command.CommandSource;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.command.CommandCause;
import org.spongepowered.api.command.parameter.Parameter;
import org.spongepowered.api.command.parameter.managed.Flag;
Expand All @@ -48,13 +49,12 @@
import java.util.NoSuchElementException;
import java.util.Optional;

import javax.annotation.Nullable;

public final class SpongeCommandContext extends CommandContext<CommandSource> implements org.spongepowered.api.command.parameter.CommandContext {

private final Map<Parameter.Key<?>, Collection<?>> argumentMap;
private final Object2IntOpenHashMap<String> flagMap;
private final Map<String, ParsedArgument<CommandSource, ?>> brigArguments;
private final org.spongepowered.api.command.Command.@Nullable Parameterized targetCommand;

public SpongeCommandContext(
final CommandSource source,
Expand All @@ -68,7 +68,8 @@ public SpongeCommandContext(
final StringRange range,
@Nullable final CommandContext<CommandSource> child,
@Nullable final RedirectModifier<CommandSource> modifier,
final boolean forks) {
final boolean forks,
final org.spongepowered.api.command.Command.@Nullable Parameterized currentTargetCommand) {
super(source,
input,
brigArguments,
Expand All @@ -82,6 +83,13 @@ public SpongeCommandContext(
this.brigArguments = brigArguments;
this.argumentMap = arguments;
this.flagMap = flags.clone();
this.targetCommand = currentTargetCommand;
}

@Override
@NonNull
public Optional<org.spongepowered.api.command.Command.Parameterized> getExecutedCommand() {
return Optional.ofNullable(this.targetCommand);
}

@Override
Expand Down Expand Up @@ -169,7 +177,8 @@ public CommandContext<CommandSource> copyFor(final CommandSource source) {
this.getRange(),
this.getChild(),
this.getRedirectModifier(),
this.isForked());
this.isForked(),
this.targetCommand);
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public final class SpongeCommandContextBuilder extends CommandContextBuilder<Com
private RedirectModifier<CommandSource> modifier;
private boolean forks;
private Deque<SpongeCommandContextBuilderTransaction> transaction = null;
private org.spongepowered.api.command.Command.Parameterized currentTargetCommand = null;

public SpongeCommandContextBuilder(
final CommandDispatcher<CommandSource> dispatcher,
Expand All @@ -89,6 +90,7 @@ public SpongeCommandContextBuilder(final SpongeCommandContextBuilder original, f

this.modifier = original.modifier;
this.forks = original.forks;
this.currentTargetCommand = original.currentTargetCommand;
this.withChild(original.getChild());
this.withCommand(original.getCommand());
original.getArguments().forEach(this::withArgument);
Expand All @@ -107,6 +109,7 @@ public void applySpongeElementsTo(final SpongeCommandContextBuilder builder, fin
}
this.flagMap.object2IntEntrySet().fastForEach(x -> builder.flagMap.put(x.getKey(), x.getIntValue()));
this.arguments.forEach((key, values) -> builder.arguments.computeIfAbsent(key, k -> new ArrayList<>()).addAll((Collection) values));
this.currentTargetCommand = builder.currentTargetCommand;
}

@Override
Expand Down Expand Up @@ -264,13 +267,23 @@ public CommandContextBuilder<CommandSource> withCommand(final Command<CommandSou
return super.withCommand(command);
}

@Override
public SpongeCommandContextBuilder copy() {
if (this.transaction != null && !this.transaction.isEmpty()) {
return this.transaction.peek().getCopyBuilder().copy();
}
return new SpongeCommandContextBuilder(this);
}

@Override
@NonNull
public Optional<org.spongepowered.api.command.Command.Parameterized> getExecutedCommand() {
if (this.transaction != null && !this.transaction.isEmpty()) {
return this.transaction.peek().getCopyBuilder().getExecutedCommand();
}
return Optional.ofNullable(this.currentTargetCommand);
}

@Override
@NonNull
public CommandCause getCause() {
Expand Down Expand Up @@ -344,7 +357,7 @@ public <T> Collection<? extends T> getAll(final Parameter.@NonNull Key<T> key) {
}

@Override
public void sendMessage(final Component message) {
public void sendMessage(@NonNull final Component message) {
this.getCause().sendMessage(message);
}

Expand Down Expand Up @@ -382,6 +395,14 @@ public <T> void putEntry(final Parameter.@NonNull Key<T> key, @NonNull final T o
}
}

public void setCurrentTargetCommand(final org.spongepowered.api.command.Command.Parameterized command) {
if (this.transaction != null && !this.transaction.isEmpty()) {
this.transaction.peek().setCurrentTargetCommand(command);
} else {
this.currentTargetCommand = command;
}
}

@Override
@NonNull
public Transaction startTransaction() {
Expand Down Expand Up @@ -417,7 +438,8 @@ public SpongeCommandContext build(@NonNull final String input) {
this.getRange(),
child == null ? null : child.build(input),
this.modifier,
this.forks);
this.forks,
this.currentTargetCommand);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
public final class SpongeCommandContextBuilderTransaction implements CommandContext.Builder.Transaction {

private static final LinkedList<SpongeCommandContextBuilderTransaction> TRANSACTION_POOL = new LinkedList<>();

public static SpongeCommandContextBuilderTransaction getTransactionFromPool(final SpongeCommandContextBuilder builder) {
SpongeCommandContextBuilderTransaction chosenTransaction = null;
for (final SpongeCommandContextBuilderTransaction transaction : TRANSACTION_POOL) {
Expand Down Expand Up @@ -73,6 +74,7 @@ public static SpongeCommandContextBuilderTransaction getTransactionFromPool(fina
private final LinkedList<Tuple<Parameter.@NonNull Key<?>, ?>> putEntryCapture = new LinkedList<>();
private final LinkedList<CommandContextBuilder<CommandSource>> withChildCapture = new LinkedList<>();
private final LinkedList<Command<CommandSource>> withCommandCapture = new LinkedList<>();
private org.spongepowered.api.command.Command.Parameterized currentTargetCommandCapture = null;

private boolean isActive = false;

Expand Down Expand Up @@ -158,6 +160,10 @@ public SpongeCommandContextBuilder getCopyBuilder() {
return this.copyBuilder;
}

public void setCurrentTargetCommand(final org.spongepowered.api.command.Command.Parameterized command) {
this.currentTargetCommandCapture = command;
}

public boolean isActive() {
if (this.isActive) {
if (this.builder.get() != null) {
Expand All @@ -178,6 +184,9 @@ public void commit() {
this.withCommandCapture.forEach(builderRef::withCommand);
this.putEntryCapture.forEach(x -> this.putEntryAbusingGenerics(builderRef, x.getFirst(), x.getSecond()));
this.flagCapture.forEach(builderRef::addFlagInvocation);
if (this.currentTargetCommandCapture != null) {
builderRef.setCurrentTargetCommand(this.currentTargetCommandCapture);
}
}

// we're clearing anyway!
Expand All @@ -192,6 +201,7 @@ public void rollback() {
this.withChildCapture.clear();
this.putEntryCapture.clear();
this.flagCapture.clear();
this.currentTargetCommandCapture = null;
this.copyBuilder = null;
this.builder = null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import com.mojang.brigadier.tree.ArgumentCommandNode;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import net.minecraft.command.CommandSource;
import net.minecraft.command.ISuggestionProvider;
import org.checkerframework.checker.nullness.qual.Nullable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,40 @@
*/
package org.spongepowered.common.command.brigadier.tree;

import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.minecraft.command.CommandSource;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.command.Command;
import org.spongepowered.common.command.brigadier.context.SpongeCommandContextBuilder;

import java.util.Collection;

public class SpongeLiteralCommandNode extends LiteralCommandNode<CommandSource> implements SpongeNode {

// used so we can have insertion order.
private final UnsortedNodeHolder nodeHolder = new UnsortedNodeHolder();
private final Command.@Nullable Parameterized subcommandIfApplicable;

public SpongeLiteralCommandNode(final LiteralArgumentBuilder<CommandSource> argumentBuilder) {
this(argumentBuilder, null);
}

public SpongeLiteralCommandNode(
final LiteralArgumentBuilder<CommandSource> argumentBuilder,
final Command.@Nullable Parameterized associatedSubcommand) {
super(argumentBuilder.getLiteral(),
argumentBuilder.getCommand(),
argumentBuilder.getRequirement(),
argumentBuilder.getRedirect(),
argumentBuilder.getRedirectModifier(),
argumentBuilder.isFork());
argumentBuilder.getArguments().forEach(this::addChild);
this.subcommandIfApplicable = associatedSubcommand;
}

@Override
Expand All @@ -57,4 +71,11 @@ public final Collection<CommandNode<CommandSource>> getChildrenForSuggestions()
return this.nodeHolder.getChildrenForSuggestions();
}

@Override
public void parse(final StringReader reader, final CommandContextBuilder<CommandSource> contextBuilder) throws CommandSyntaxException {
super.parse(reader, contextBuilder);
if (this.subcommandIfApplicable != null && contextBuilder instanceof SpongeCommandContextBuilder) {
((SpongeCommandContextBuilder) contextBuilder).setCurrentTargetCommand(this.subcommandIfApplicable);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ private CommandResult rootCommand(final CommandContext context) {
final PluginContainer apiPlugin = Launcher.getInstance().getApiPlugin();
final PluginContainer minecraftPlugin = Launcher.getInstance().getMinecraftPlugin();

context.getCause().sendMessage(TextComponent.builder().append(
context.sendMessage(TextComponent.builder().append(
TextComponent.of("SpongePowered", NamedTextColor.YELLOW, TextDecoration.BOLD).append(TextComponent.space()),
TextComponent.of("Plugin Platform (running on Minecraft " + minecraftPlugin.getMetadata().getVersion() + ")"),
TextComponent.newline(),
Expand All @@ -189,6 +189,25 @@ private CommandResult rootCommand(final CommandContext context) {
TextComponent.of(platformPlugin.getMetadata().getName().get() + ": " + platformPlugin.getMetadata().getVersion())
).build()
);

final Optional<Command.Parameterized> parameterized = context.getExecutedCommand();
if (parameterized.isPresent()) {
final String subcommands = parameterized.get()
.subcommands()
.stream()
.filter(x -> x.getCommand().canExecute(context.getCause()))
.flatMap(x -> x.getAliases().stream())
.collect(Collectors.joining(", "));
if (!subcommands.isEmpty()) {
context.sendMessage(TextComponent.builder().append(
TextComponent.newline(),
TextComponent.of("Available subcommands:"),
TextComponent.newline(),
TextComponent.of(subcommands)).build()
);
}
}

return CommandResult.success();
}

Expand Down

0 comments on commit c6ffa7e

Please sign in to comment.