Paper icon indicating copy to clipboard operation
Paper copied to clipboard

Expose more argument types

Open Strokkur424 opened this issue 4 months ago • 1 comments

This PR aims to expose the following argument types:

  • [x] Angle
  • [x] Swizzle
  • [x] Block predicate
  • ~~Particle (custom data is currently broken)~~ Out of scope
  • [x] Vec2 (in form of a new ~~Vec2FinePosition~~. Renamed to ColumnFinePosition)
  • [x] ColumnPos (in form of a new ColumnBlockPosition)

~~The code to test it currently committed under TestPlugin.java, please remove that on merge.~~ No longer commited. For documentation purposes, the current state of the testing code (which includes example usage) is this:

TestPlugin.java
package io.papermc.testplugin;

import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.Commands;
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
import io.papermc.paper.command.brigadier.argument.predicate.BlockPredicate;
import io.papermc.paper.command.brigadier.argument.resolvers.AngleResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.ColumnBlockPositionResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.ColumnFinePositionResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver;
import io.papermc.paper.math.BlockPosition;
import io.papermc.paper.math.ColumnBlockPosition;
import io.papermc.paper.math.ColumnFinePosition;
import io.papermc.paper.math.FinePosition;
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
import java.util.EnumSet;
import java.util.Set;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.Axis;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;

public final class TestPlugin extends JavaPlugin implements Listener {

    @Override
    public void onEnable() {
        this.getServer().getPluginManager().registerEvents(this, this);

        Set<LiteralArgumentBuilder<CommandSourceStack>> commands = Set.of(
            angle(), swizzle(), blockPredicate(), particle(), columnFine(), columnBlock()
        );

        this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS.newHandler(
            event -> commands.forEach(builder -> event.registrar().register(builder.build()))
        ));
    }

    private LiteralArgumentBuilder<CommandSourceStack> angle() {
        return Commands.literal("angle")
            .then(Commands.argument("angle", ArgumentTypes.angle())
                .executes(ctx -> {
                    float angle = ctx.getArgument("angle", AngleResolver.class).resolve(ctx.getSource());
                    ctx.getSource().getSender().sendRichMessage("Your selected angle is <aqua>:" + angle);
                    return 1;
                })
            );
    }

    private LiteralArgumentBuilder<CommandSourceStack> swizzle() {
        return Commands.literal("swizzle")
            .then(Commands.argument("swizzle", ArgumentTypes.swizzle())
                .executes(ctx -> {
                    EnumSet<Axis> axes = (EnumSet<Axis>) ctx.getArgument("swizzle", EnumSet.class);

                    StringBuilder builder = new StringBuilder();
                    if (axes.contains(Axis.X)) {
                        builder.append("<red>X ");
                    }
                    if (axes.contains(Axis.Y)) {
                        builder.append("<green>Y ");
                    }
                    if (axes.contains(Axis.Z)) {
                        builder.append("<blue>Z");
                    }

                    String axesString = builder.toString().trim();
                    ctx.getSource().getSender().sendRichMessage("You selected: <axes>",
                        Placeholder.parsed("axes", axesString.isEmpty() ? "<gray>None" : axesString)
                    );
                    return 1;
                })
            );
    }

    private LiteralArgumentBuilder<CommandSourceStack> blockPredicate() {
        return Commands.literal("blockpredicate")
            .then(Commands.argument("position", ArgumentTypes.blockPosition())
                .then(Commands.argument("blockpredicate", ArgumentTypes.blockPredicate())
                    .executes(ctx -> {
                        BlockPredicate predicate = ctx.getArgument("blockpredicate", BlockPredicate.class);
                        BlockPosition position = ctx.getArgument("position", BlockPositionResolver.class).resolve(ctx.getSource());
                        World world = ctx.getSource().getLocation().getWorld();

                        if (predicate.test(position.toLocation(world).getBlock())) {
                            ctx.getSource().getSender().sendRichMessage("<green>Obviously that block matches, lol.");
                        } else {
                            ctx.getSource().getSender().sendRichMessage("<red>Why would that match. Use your eyes ☠️");
                        }

                        return 1;
                    })
                )
            );
    }

    private LiteralArgumentBuilder<CommandSourceStack> particle() {
        return Commands.literal("particle")
            .then(Commands.argument("particle", ArgumentTypes.particle())
                .then(Commands.argument("position", ArgumentTypes.finePosition(true))
                    .executes(ctx -> {
                        Particle particle = ctx.getArgument("particle", Particle.class);
                        FinePosition position = ctx.getArgument("position", FinePositionResolver.class).resolve(ctx.getSource());
                        World world = ctx.getSource().getLocation().getWorld();

                        // TODO: Fix particles
                        world.spawnParticle(particle, position.toLocation(world), 10);
                        return 1;
                    })
                )
            );
    }

    private LiteralArgumentBuilder<CommandSourceStack> columnFine() {
        return Commands.literal("columnfine")
            .then(Commands.argument("columnfine", ArgumentTypes.columnFinePosition())
                .executes(ctx -> {
                    ColumnFinePosition pos = ctx.getArgument("columnfine", ColumnFinePositionResolver.class).resolve(ctx.getSource());
                    ctx.getSource().getSender().sendRichMessage("The position you selected is at x: <red><x></red> z: <blue><z></blue>",
                        Placeholder.unparsed("x", Double.toString(pos.x())),
                        Placeholder.unparsed("z", Double.toString(pos.z()))
                    );
                    return 1;
                })
            );
    }

    private LiteralArgumentBuilder<CommandSourceStack> columnBlock() {
        return Commands.literal("columnblock")
            .then(Commands.argument("columnblock", ArgumentTypes.columnBlockPosition())
                .executes(ctx -> {
                    ColumnBlockPosition pos = ctx.getArgument("columnblock", ColumnBlockPositionResolver.class).resolve(ctx.getSource());
                    ctx.getSource().getSender().sendRichMessage("The position you selected is at x: <red><x></red> z: <blue><z></blue>",
                        Placeholder.unparsed("x", Double.toString(pos.x())),
                        Placeholder.unparsed("z", Double.toString(pos.z()))
                    );
                    return 1;
                })
            );
    }
}

Strokkur424 avatar Jun 13 '25 21:06 Strokkur424