Paper icon indicating copy to clipboard operation
Paper copied to clipboard

Expose certain scoreboard related argument types

Open Strokkur424 opened this issue 5 months ago • 1 comments

Closes #12540

This PR exposes a few scoreboard related Vanilla arguments for use in-API.

  • [x] OperationArgument
  • [x] ScoreHolderArgument
  • [x] ObjectiveArgument whilst this argument is just a wrapper around a String, since it provides potentially useful errors, I decided to expose it anyways
  • [x] TeamArgument same as the ObjectiveArgument

Operation Argument

(Brigadier jumpscare!) Operation argument usage preview

image

Code:

Commands.literal("test")
    .then(Commands.argument("left", IntegerArgumentType.integer())
        .then(Commands.argument("operation", ArgumentTypes.operation())
            .then(Commands.argument("right", IntegerArgumentType.integer())
                .executes(ctx -> {
                    int left = IntegerArgumentType.getInteger(ctx, "left");
                    Operation operation = ctx.getArgument("operation", Operation.class);
                    int right = IntegerArgumentType.getInteger(ctx, "right");

                    IntIntPair result = operation.apply(left, right);
                    ctx.getSource().getSender().sendRichMessage("<green><left></green> <operation> <red><right></red> results in <green><left_new></green> and <red><right_new></red>",
                        Placeholder.unparsed("left", Integer.toString(left)),
                        Placeholder.unparsed("operation", ctx.getInput().split(" ")[2]),
                        Placeholder.unparsed("right", Integer.toString(right)),
                        Placeholder.unparsed("left_new", Integer.toString(result.leftInt())),
                        Placeholder.unparsed("right_new", Integer.toString(result.rightInt()))
                    );
                    return 1;
                })
            )
        )
    )
    .build()

ScoreHolder Argument

In addition to adding the argument, I have also taken the liberty of exposing a ScoreHolder interface, which is implemented by all entities, OfflinePlayer, and also has a string-only implementation.

(Brigadier jumpscare!) ScoreHolder argument usage preview Preview:

image

Code:

Commands.literal("test")
    .then(Commands.argument("scoreholder", ArgumentTypes.scoreHolder())
        .executes(ctx -> {
            ScoreHolder holder = ctx.getArgument("scoreholder", ScoreHolderResolver.class).resolve(ctx.getSource()).getFirst();
            ctx.getSource().getSender().sendRichMessage("The scoreholder's display name is: <name>. Its nms representation is: <nms>",
                Placeholder.component("name", holder.getScoreDisplayName()),
                Placeholder.unparsed("nms", holder.toString())
            );
            return 1;
        })
    )
    .build()

Objective argument

(Brigadier jumpscare!) Objective argument usage preview

image

Commands.literal("testobjective-default")
    .then(Commands.argument("objective", ArgumentTypes.objective())
        .executes(ctx -> {
            Objective objective = ctx.getArgument("objective", ObjectiveResolver.class).resolve(ctx.getSource());

            ctx.getSource().getSender().sendRichMessage("You selected the objective <objective> (Criteria: <criteria>)",
                Placeholder.component("objective", objective.displayName()),
                Placeholder.unparsed("criteria", objective.getTrackedCriteria().getName())
            );
            return 1;
        })
    )
    .build()

Objective argument (writable)

Vanilla differentiates between writable and non-writable objectives when resolving. Therefore, there is a second set of methods exposed on the ObjectiveResolver, which do this additional 'writable criteria' check.

(Brigadier jumpscare!) Objective argument usage with writable resolvers

image

Commands.literal("testobjective-writeable")
    .then(Commands.argument("objective", ArgumentTypes.objective())
        .executes(ctx -> {
            Objective objective = ctx.getArgument("objective", ObjectiveResolver.class).resolveWritable(ctx.getSource());

            ctx.getSource().getSender().sendRichMessage("You selected the writable objective <objective> (Criteria: <criteria>)",
                Placeholder.component("objective", objective.displayName()),
                Placeholder.unparsed("criteria", objective.getTrackedCriteria().getName())
            );
            return 1;
        })
    )
    .build()

Team argument

This argument has a custom resolver attached to it in order to allow resolving not only for the main server scoreboard, but also any additional scoreboard. This is not a feature of the nms ScoreboardArgument, but I thought this might be a good thing to add for plugin reasons.

(Brigadier jumpscare!) Team argument usage preview

image

Commands.literal("testteam")
    .then(Commands.argument("team", ArgumentTypes.team())
        .executes(ctx -> {
            Team team = ctx.getArgument("team", TeamResolver.class).resolve(ctx.getSource());
            ctx.getSource().getSender().sendRichMessage("You selected team <teamcolor><name></teamcolor>!",
                Placeholder.styling("teamcolor", team.color()),
                Placeholder.unparsed("name", team.getName())
            );
            return 1;
        })
    )
    .build()

Strokkur424 avatar May 10 '25 10:05 Strokkur424