Skip to content

Expose certain scoreboard related argument types #12541

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,5 @@ aerulion <[email protected]>
Lukas Planz <[email protected]>
granny <[email protected]>
mja00 <[email protected]>
Strokkur24 <[email protected]>
```
2 changes: 2 additions & 0 deletions build-data/paper.at
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public net.minecraft.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwab
public net.minecraft.advancements.Advancement decorateName(Lnet/minecraft/advancements/DisplayInfo;)Lnet/minecraft/network/chat/Component;
public net.minecraft.commands.CommandSourceStack source
public net.minecraft.commands.arguments.DimensionArgument ERROR_INVALID_VALUE
public net.minecraft.commands.arguments.OperationArgument ERROR_INVALID_OPERATION
public net.minecraft.commands.arguments.OperationArgument$SimpleOperation
public net.minecraft.commands.arguments.blocks.BlockInput tag
public net.minecraft.core.MappedRegistry validateWrite(Lnet/minecraft/resources/ResourceKey;)V
public net.minecraft.nbt.ListTag <init>(Ljava/util/List;)V
Expand Down
10 changes: 10 additions & 0 deletions paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import io.papermc.paper.world.damagesource.CombatEntry;
import io.papermc.paper.world.damagesource.FallLocationType;
import net.kyori.adventure.util.Services;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Biome;
import org.bukkit.damage.DamageEffect;
import org.bukkit.damage.DamageSource;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scoreboard.ScoreHolder;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
Expand Down Expand Up @@ -73,5 +75,13 @@ class Holder {
* @return combat entry
*/
CombatEntry createCombatEntry(DamageSource damageSource, float damage, @Nullable FallLocationType fallLocationType, float fallDistance);

/**
* Creates a wrapping score holder
*
* @param entry The entry to wrap
* @return a wrapping ScoreHolder
*/
ScoreHolder scoreHolderOf(String entry);
}

Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package io.papermc.paper.command.brigadier.argument;

import com.mojang.brigadier.arguments.ArgumentType;
import io.papermc.paper.command.brigadier.argument.operation.Operation;
import io.papermc.paper.command.brigadier.argument.predicate.ItemStackPredicate;
import io.papermc.paper.command.brigadier.argument.range.DoubleRangeProvider;
import io.papermc.paper.command.brigadier.argument.range.IntegerRangeProvider;
import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.ObjectiveResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.PlayerProfileListResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.RotationResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.ScoreHolderResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.TeamResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver;
import io.papermc.paper.entity.LookAnchor;
Expand All @@ -28,6 +32,8 @@
import org.bukkit.inventory.ItemStack;
import org.bukkit.scoreboard.Criteria;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;

Expand Down Expand Up @@ -291,6 +297,53 @@ public static ArgumentType<Criteria> objectiveCriteria() {
return provider().objectiveCriteria();
}

/**
* Represents a selector that can capture any single
* score holder.
*
* @return argument
*/
public static ArgumentType<ScoreHolderResolver> scoreHolder() {
return provider().scoreHolder();
}

/**
* Represents a selector that can capture multiple
* score holders.
*
* @return argument
*/
public static ArgumentType<ScoreHolderResolver> scoreHolders() {
return provider().scoreHolders();
}

/**
* An operation argument.
*
* @return argument
*/
public static ArgumentType<Operation> operation() {
return provider().operation();
}

/**
* An objective argument.
*
* @return argument
*/
public static ArgumentType<ObjectiveResolver> objective() {
return provider().objective();
}

/**
* A team argument.
*
* @return argument
*/
public static ArgumentType<TeamResolver> team() {
return provider().team();
}

/**
* An entity anchor argument.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package io.papermc.paper.command.brigadier.argument;

import com.mojang.brigadier.arguments.ArgumentType;
import io.papermc.paper.command.brigadier.argument.operation.Operation;
import io.papermc.paper.command.brigadier.argument.predicate.ItemStackPredicate;
import io.papermc.paper.command.brigadier.argument.range.DoubleRangeProvider;
import io.papermc.paper.command.brigadier.argument.range.IntegerRangeProvider;
import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.ObjectiveResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.PlayerProfileListResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.RotationResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.ScoreHolderResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.TeamResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver;
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver;
import io.papermc.paper.entity.LookAnchor;
Expand All @@ -30,6 +34,8 @@
import org.bukkit.inventory.ItemStack;
import org.bukkit.scoreboard.Criteria;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;

Expand Down Expand Up @@ -75,6 +81,16 @@ static VanillaArgumentProvider provider() {
ArgumentType<SignedMessageResolver> signedMessage();

ArgumentType<DisplaySlot> scoreboardDisplaySlot();

ArgumentType<ScoreHolderResolver> scoreHolder();

ArgumentType<ScoreHolderResolver> scoreHolders();

ArgumentType<Operation> operation();

ArgumentType<ObjectiveResolver> objective();

ArgumentType<TeamResolver> team();

ArgumentType<NamespacedKey> namespacedKey();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.papermc.paper.command.brigadier.argument.operation;

import com.mojang.brigadier.exceptions.CommandSyntaxException;
import it.unimi.dsi.fastutil.ints.IntIntPair;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;

/**
* Represents a simple arithmetic operation between two integers.
* An {@link Operation} backs an operator.
* Most arithmetic operators (like {@code +=, -=, /=, etc.}) are
* supported, alongside certain conditional operators ({@code >=, <=, ==, etc.}).
* <p>
* Note that conditional operators, instead of yielding a boolean value, return the value
* that matches the operation.
* For example, the {@code <=} operator always returns the <strong>smaller</strong> value
* of two given values.
*/
@ApiStatus.Experimental
@NullMarked
public interface Operation {
Copy link
Contributor

Choose a reason for hiding this comment

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

Javadocs, what is an operation.
What are common usage patterns etc.

Operation also is a very broad name, idk if there a is a point in finding something more specific to what this is.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is more okay in internals, because this type lives purely as an inner type to OperationArgument.
But yea, on a top level, this doesn't mean much.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also experimental annotation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lynxplay do you perhaps have any idea what I could rename the Operation class to so that it makes more sense, even on a top level? I thought about IntegerOperation, ScoreOperation, or even CommandOperation, but all of these sounds misleading, so I am not fully happy about that yet


/**
* Applies this operation to a pair of integers.
* <p>
* Arithmetic between two integers always follows this pattern:
* <pre>
* return left &lt;operator&gt; right
* </pre>
* On certain operators, such as division, the order matters.
* {@code 20 %= 10} yields a different result than{@code 10 %= 20}.
*
* @param left left side of the expression
* @param right right side of the expression
* @return result of this operation
*/
IntIntPair apply(int left, int right) throws CommandSyntaxException;

/**
* Applies this operation to a pair of integers.
* <p>
* Arithmetic between two integers always follows this pattern:
* <pre>
* return left &lt;operator&gt; right
* </pre>
* On certain operators, such as division, the order matters.
* {@code 20 %= 10} yields a different result than{@code 10 %= 20}.
*
* @param left left side of the expression
* @param right right side of the expression
* @return the left side of the result of this operation
* @see #apply(int, int)
*/
default int applyLeftSide(int left, int right) throws CommandSyntaxException {
return apply(left, right).leftInt();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.papermc.paper.command.brigadier.argument.resolvers;

import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
import org.bukkit.Bukkit;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Scoreboard;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;

/**
* A resolver that's capable of resolving
* an {@link Objective} value using a {@link Scoreboard} and {@link CommandSourceStack}.
*
* @see ArgumentTypes#objective()
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
@NullMarked
public interface ObjectiveResolver {

/**
* Resolves the argument with the given command source stack.
* <p>
* This method is the same as calling {@link #resolve(Scoreboard, CommandSourceStack)} with
* the scoreboard retrieved from {@code Bukkit.getScoreboardManager().getMainScoreboard()}.
*
* @param sourceStack source stack
* @return resolved objective
*/
default Objective resolve(CommandSourceStack sourceStack) throws CommandSyntaxException {
return resolve(Bukkit.getScoreboardManager().getMainScoreboard(), sourceStack);
}

/**
* Resolves the argument with the given command source stack.
* <p>
* This method is the same as calling {@link #resolve(Scoreboard, CommandSourceStack)} with
* the scoreboard retrieved from {@code Bukkit.getScoreboardManager().getMainScoreboard()}.
*
* @param sourceStack source stack
* @return resolved objective, whose criteria is writable
*/
default Objective resolveWritable(CommandSourceStack sourceStack) throws CommandSyntaxException {
return resolveWritable(Bukkit.getScoreboardManager().getMainScoreboard(), sourceStack);
}

/**
* Resolves the argument with the given command source stack.
*
* @param scoreboard scoreboard to get the objective from
* @param sourceStack source stack
* @return resolved objective
*/
Objective resolve(Scoreboard scoreboard, CommandSourceStack sourceStack) throws CommandSyntaxException;

/**
* Resolves the argument with the given command source stack.
*
* @param scoreboard scoreboard to get the objective from
* @param sourceStack source stack
* @return resolved objective, whose criteria is writable
*/
Objective resolveWritable(Scoreboard scoreboard, CommandSourceStack sourceStack) throws CommandSyntaxException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.papermc.paper.command.brigadier.argument.resolvers;

import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
import org.bukkit.scoreboard.ScoreHolder;
import org.jetbrains.annotations.ApiStatus;
import java.util.Collection;
import java.util.List;

/**
* An {@link ArgumentResolver} that's capable of resolving
* an argument value using a {@link CommandSourceStack} into a
* list of {@link ScoreHolder}s.
*
* @see ArgumentTypes#scoreHolders()
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface ScoreHolderResolver extends ArgumentResolver<List<ScoreHolder>> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package io.papermc.paper.command.brigadier.argument.resolvers;

import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
import org.bukkit.Bukkit;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.ScoreboardManager;
import org.bukkit.scoreboard.Team;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;

/**
* A resolver that's capable of resolving
* a {@link Team} value using a {@link Scoreboard} and {@link CommandSourceStack}.
*
* @see ArgumentTypes#objective()
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
@NullMarked
public interface TeamResolver {

/**
* Resolves the argument with the given command source stack.
* <p>
* This method is the same as calling {@link #resolve(Scoreboard, CommandSourceStack)} with
* the scoreboard retrieved from {@code Bukkit.getScoreboardManager().getMainScoreboard()}.
*
* @param sourceStack source stack
* @return resolved team
* @see #resolve(Scoreboard, CommandSourceStack)
* @see ScoreboardManager#getMainScoreboard()
*/
default Team resolve(CommandSourceStack sourceStack) throws CommandSyntaxException {
return resolve(Bukkit.getScoreboardManager().getMainScoreboard(), sourceStack);
}

/**
* Resolves the argument with the given scoreboard and command source stack.
*
* @param scoreboard scoreboard to get the team from
* @param sourceStack source stack
* @return resolved team
*/
Team resolve(Scoreboard scoreboard, CommandSourceStack sourceStack) throws CommandSyntaxException;
}
3 changes: 2 additions & 1 deletion paper-api/src/main/java/org/bukkit/OfflinePlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.bukkit.entity.Player;
import org.bukkit.permissions.ServerOperator;
import org.bukkit.profile.PlayerProfile;
import org.bukkit.scoreboard.ScoreHolder;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

Expand All @@ -20,7 +21,7 @@
* player needing to be online.
*/
@NullMarked
public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable, io.papermc.paper.persistence.PersistentDataViewHolder { // Paper - Add Offline PDC API
public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable, io.papermc.paper.persistence.PersistentDataViewHolder, ScoreHolder { // Paper - Add Offline PDC API

/**
* Checks if this player is currently online
Expand Down
3 changes: 2 additions & 1 deletion paper-api/src/main/java/org/bukkit/entity/Entity.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.bukkit.material.Directional;
import org.bukkit.metadata.Metadatable;
import org.bukkit.persistence.PersistentDataHolder;
import org.bukkit.scoreboard.ScoreHolder;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.ApiStatus;
Expand All @@ -37,7 +38,7 @@
* Not all methods are guaranteed to work/may have side effects when
* {@link #isInWorld()} is false.
*/
public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource<net.kyori.adventure.text.event.HoverEvent.ShowEntity>, net.kyori.adventure.sound.Sound.Emitter, DataComponentView { // Paper
public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource<net.kyori.adventure.text.event.HoverEvent.ShowEntity>, net.kyori.adventure.sound.Sound.Emitter, DataComponentView, ScoreHolder { // Paper

/**
* Gets the entity's current position
Expand Down
Loading
Loading