✨ Initial support for compound arguments
This allows for grouping and mappings of multiple command arguments by using product types.
This commit is contained in:
parent
e033ee88db
commit
94710c5174
22 changed files with 1032 additions and 28 deletions
|
|
@ -212,7 +212,7 @@ public final class CloudBrigadierManager<C, S> {
|
|||
@Nullable
|
||||
@SuppressWarnings("all")
|
||||
private <T, K extends ArgumentParser<?, ?>> Pair<ArgumentType<?>, Boolean> getArgument(
|
||||
@Nonnull final Class<?> valueType,
|
||||
@Nonnull final TypeToken<?> valueType,
|
||||
@Nonnull final TypeToken<T> argumentType,
|
||||
@Nonnull final K argument) {
|
||||
final ArgumentParser<C, ?> commandArgument = (ArgumentParser<C, ?>) argument;
|
||||
|
|
@ -225,9 +225,9 @@ public final class CloudBrigadierManager<C, S> {
|
|||
|
||||
@Nonnull
|
||||
private <T, K extends ArgumentParser<C, T>> Pair<ArgumentType<?>, Boolean> createDefaultMapper(
|
||||
@Nonnull final Class<?> clazz,
|
||||
@Nonnull final TypeToken<?> clazz,
|
||||
@Nonnull final ArgumentParser<C, T> argument) {
|
||||
final Supplier<ArgumentType<?>> argumentTypeSupplier = this.defaultArgumentTypeSuppliers.get(clazz);
|
||||
final Supplier<ArgumentType<?>> argumentTypeSupplier = this.defaultArgumentTypeSuppliers.get(clazz.getRawType());
|
||||
if (argumentTypeSupplier != null) {
|
||||
return new Pair<>(argumentTypeSupplier.get(), true);
|
||||
}
|
||||
|
|
@ -298,12 +298,54 @@ public final class CloudBrigadierManager<C, S> {
|
|||
@Nonnull final BiPredicate<S, CommandPermission> permissionChecker,
|
||||
@Nonnull final com.mojang.brigadier.Command<S> executor,
|
||||
@Nonnull final SuggestionProvider<S> suggestionProvider) {
|
||||
if (root.getValue() instanceof CompoundArgument) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final CompoundArgument<?, C, ?> compoundArgument = (CompoundArgument<?, C, ?>) root.getValue();
|
||||
final Object[] parsers = compoundArgument.getParserTuple().toArray();
|
||||
final Object[] types = compoundArgument.getTypes().toArray();
|
||||
final Object[] names = compoundArgument.getNames().toArray();
|
||||
|
||||
/* Build nodes backwards */
|
||||
final ArgumentBuilder<S, ?>[] argumentBuilders = new ArgumentBuilder[parsers.length];
|
||||
|
||||
for (int i = parsers.length - 1; i >= 0; i--) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final ArgumentParser<C, ?> parser = (ArgumentParser<C, ?>) parsers[i];
|
||||
final Pair<ArgumentType<?>, Boolean> pair = this.getArgument(TypeToken.of((Class<?>) types[i]),
|
||||
TypeToken.of(parser.getClass()),
|
||||
parser);
|
||||
final SuggestionProvider<S> provider = pair.getRight() ? null : suggestionProvider;
|
||||
final ArgumentBuilder<S, ?> fragmentBuilder = RequiredArgumentBuilder
|
||||
.<S, Object>argument((String) names[i], (ArgumentType<Object>) pair.getLeft())
|
||||
.suggests(provider)
|
||||
.requires(sender -> permissionChecker.test(sender,
|
||||
(CommandPermission) root.getNodeMeta()
|
||||
.getOrDefault("permission", Permission.empty())));
|
||||
argumentBuilders[i] = fragmentBuilder;
|
||||
|
||||
if (forceExecutor || (i == parsers.length - 1) && (root.isLeaf() || !root.getValue().isRequired())) {
|
||||
fragmentBuilder.executes(executor);
|
||||
}
|
||||
|
||||
/* Link all previous builder to this one */
|
||||
if ((i + 1) < parsers.length) {
|
||||
fragmentBuilder.then(argumentBuilders[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
for (final CommandTree.Node<CommandArgument<C, ?>> node : root.getChildren()) {
|
||||
argumentBuilders[parsers.length - 1]
|
||||
.then(constructCommandNode(forceExecutor, node, permissionChecker, executor, suggestionProvider));
|
||||
}
|
||||
|
||||
return argumentBuilders[0];
|
||||
}
|
||||
ArgumentBuilder<S, ?> argumentBuilder;
|
||||
if (root.getValue() instanceof StaticArgument) {
|
||||
argumentBuilder = LiteralArgumentBuilder.<S>literal(root.getValue().getName())
|
||||
.requires(sender -> permissionChecker.test(sender, (CommandPermission) root.getNodeMeta()
|
||||
.getOrDefault("permission", Permission.empty())))
|
||||
.getOrDefault("permission",
|
||||
Permission.empty())))
|
||||
.executes(executor);
|
||||
} else {
|
||||
final Pair<ArgumentType<?>, Boolean> pair = this.getArgument(root.getValue().getValueType(),
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ import org.bukkit.command.CommandSender;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -210,13 +211,35 @@ public final class BukkitTest extends JavaPlugin {
|
|||
.build(), Description.of("Help Query"))
|
||||
.handler(c -> minecraftHelp.queryCommands(c.<String>get("query").orElse(""),
|
||||
c.getSender())).build());
|
||||
|
||||
this.registerTeleportCommand(mgr);
|
||||
mgr.registerExceptionHandler(InvalidSyntaxException.class, (c, e) -> e.printStackTrace());
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerTeleportCommand(@Nonnull final BukkitCommandManager<CommandSender> manager) {
|
||||
manager.command(mgr.commandBuilder("teleport")
|
||||
.meta("description", "Takes in a location and teleports the player there")
|
||||
.withSenderType(Player.class)
|
||||
.argument(WorldArgument.required("world"), Description.of("World name"))
|
||||
.argumentTriplet("coords",
|
||||
TypeToken.of(Vector.class),
|
||||
Triplet.of("x", "y", "z"),
|
||||
Triplet.of(Double.class, Double.class, Double.class),
|
||||
triplet -> new Vector(triplet.getFirst(), triplet.getSecond(), triplet.getThird()),
|
||||
Description.of("Coordinates"))
|
||||
.handler(context -> {
|
||||
context.getSender().sendMessage(ChatColor.GOLD + "Teleporting!");
|
||||
Bukkit.getScheduler().runTask(this, () -> {
|
||||
final World world = context.getRequired("world");
|
||||
final Vector vector = context.getRequired("coords");
|
||||
((Player) context.getSender()).teleport(vector.toLocation(world));
|
||||
});
|
||||
})
|
||||
.build());
|
||||
}
|
||||
|
||||
@CommandDescription("Test cloud command using @CommandMethod")
|
||||
@CommandMethod(value = "annotation|a <input> [number]", permission = "some.permission.node")
|
||||
private void annotatedCommand(@Nonnull final Player player,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue