Skip to content

Conversation

@Strokkur424
Copy link
Member

@Strokkur424 Strokkur424 commented May 10, 2025

Closes #12540

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

  • OperationArgument
  • ScoreHolderArgument
  • ObjectiveArgument whilst this argument is just a wrapper around a String, since it provides potentially useful errors, I decided to expose it anyways
  • 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()

@github-project-automation github-project-automation bot moved this to Awaiting review in Paper PR Queue May 10, 2025
@Strokkur424 Strokkur424 changed the title Add operation argument Expose certain scoreboard related argument types May 10, 2025
@Strokkur424 Strokkur424 marked this pull request as ready for review May 10, 2025 13:24
@Strokkur424 Strokkur424 requested a review from a team as a code owner May 10, 2025 13:24
Copy link
Contributor

@lynxplay lynxplay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I'll poke some other team members about this, so I'd wait a bit with implementing my feedback given how drastic it is.

@github-project-automation github-project-automation bot moved this from Awaiting review to Changes required in Paper PR Queue May 11, 2025
@Strokkur424 Strokkur424 force-pushed the feat/operation-argument branch 3 times, most recently from 0b2ca4b to 4e0ae70 Compare May 11, 2025 13:17
@Strokkur424 Strokkur424 force-pushed the feat/operation-argument branch from 48706b4 to c675e17 Compare June 13, 2025 15:49
@Strokkur424 Strokkur424 requested a review from lynxplay June 13, 2025 19:00
@Strokkur424 Strokkur424 force-pushed the feat/operation-argument branch from 5e0e732 to 5dbc0bf Compare June 17, 2025 17:39
@Strokkur424
Copy link
Member Author

Rebased to 1.21.6

@Strokkur424 Strokkur424 force-pushed the feat/operation-argument branch 5 times, most recently from 9afa696 to 732f946 Compare June 21, 2025 19:23
@Strokkur424 Strokkur424 force-pushed the feat/operation-argument branch from 732f946 to 375a424 Compare July 12, 2025 12:46
@Strokkur424
Copy link
Member Author

Rebased to 1.21.7

@Strokkur424 Strokkur424 force-pushed the feat/operation-argument branch from 375a424 to af5bb54 Compare July 17, 2025 17:46
@Strokkur424
Copy link
Member Author

Rebased to 1.21.8

@Strokkur424 Strokkur424 force-pushed the feat/operation-argument branch from 73a3411 to f2f06c0 Compare August 17, 2025 19:15
@Strokkur424
Copy link
Member Author

Fixed the compile time errors, woops 😅

@Strokkur424 Strokkur424 force-pushed the feat/operation-argument branch from 21d52af to eb87d6a Compare October 3, 2025 13:35
@Strokkur424
Copy link
Member Author

✨ Rebased for 1.21.9 ✨

@Strokkur424
Copy link
Member Author

Updated the PR for 1.21.11

@Strokkur424 Strokkur424 requested a review from lynxplay December 27, 2025 23:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Changes required

Development

Successfully merging this pull request may close these issues.

Add Brigadier ArgumentType Support for Vanilla-style Operation Symbols (+=, *=, %=, etc)

4 participants