Skip to content

Commit 4e0ae70

Browse files
committed
Add ScoreHolder and Operation arguments.
This commit is a squash and fixup commit of multiple previous commits. Fixed the JavaDocs and formatting.
1 parent d2ad2e6 commit 4e0ae70

File tree

16 files changed

+413
-25
lines changed

16 files changed

+413
-25
lines changed

LICENSE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,5 @@ aerulion <[email protected]>
6565
Lukas Planz <[email protected]>
6666
6767
68+
Strokkur24 <[email protected]>
6869
```

build-data/paper.at

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,3 +788,5 @@ public-f net.minecraft.world.level.saveddata.maps.MapItemSavedData locked
788788
public-f net.minecraft.world.level.saveddata.maps.MapItemSavedData scale
789789
public-f net.minecraft.world.level.saveddata.maps.MapItemSavedData trackingPosition
790790
public-f net.minecraft.world.level.saveddata.maps.MapItemSavedData unlimitedTracking
791+
public net.minecraft.commands.arguments.OperationArgument$SimpleOperation
792+
public net.minecraft.commands.arguments.OperationArgument ERROR_INVALID_OPERATION

paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import io.papermc.paper.world.damagesource.CombatEntry;
44
import io.papermc.paper.world.damagesource.FallLocationType;
55
import net.kyori.adventure.util.Services;
6+
import org.bukkit.OfflinePlayer;
67
import org.bukkit.block.Biome;
78
import org.bukkit.damage.DamageEffect;
89
import org.bukkit.damage.DamageSource;
910
import org.bukkit.entity.LivingEntity;
11+
import org.bukkit.scoreboard.ScoreHolder;
1012
import org.jetbrains.annotations.ApiStatus;
1113
import org.jspecify.annotations.NullMarked;
1214
import org.jspecify.annotations.Nullable;
@@ -73,5 +75,21 @@ class Holder {
7375
* @return combat entry
7476
*/
7577
CombatEntry createCombatEntry(DamageSource damageSource, float damage, @Nullable FallLocationType fallLocationType, float fallDistance);
78+
79+
/**
80+
* Creates a wrapping score holder
81+
*
82+
* @param entry The entry to wrap
83+
* @return a wrapping ScoreHolder
84+
*/
85+
ScoreHolder scoreHolderOf(String entry);
86+
87+
/**
88+
* Creates a wrapping score holder
89+
*
90+
* @param player The player to wrap
91+
* @return a wrapping ScoreHolder
92+
*/
93+
ScoreHolder scoreHolderOf(OfflinePlayer player);
7694
}
7795

paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package io.papermc.paper.command.brigadier.argument;
22

33
import com.mojang.brigadier.arguments.ArgumentType;
4+
import io.papermc.paper.command.brigadier.argument.operation.Operation;
45
import io.papermc.paper.command.brigadier.argument.predicate.ItemStackPredicate;
56
import io.papermc.paper.command.brigadier.argument.range.DoubleRangeProvider;
67
import io.papermc.paper.command.brigadier.argument.range.IntegerRangeProvider;
78
import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver;
89
import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver;
910
import io.papermc.paper.command.brigadier.argument.resolvers.PlayerProfileListResolver;
1011
import io.papermc.paper.command.brigadier.argument.resolvers.RotationResolver;
12+
import io.papermc.paper.command.brigadier.argument.resolvers.ScoreHolderResolver;
1113
import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver;
1214
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver;
1315
import io.papermc.paper.entity.LookAnchor;
@@ -291,6 +293,35 @@ public static ArgumentType<Criteria> objectiveCriteria() {
291293
return provider().objectiveCriteria();
292294
}
293295

296+
/**
297+
* Represents a selector that can capture any single
298+
* score holder.
299+
*
300+
* @return argument
301+
*/
302+
public static ArgumentType<ScoreHolderResolver> scoreHolder() {
303+
return provider().scoreHolder();
304+
}
305+
306+
/**
307+
* Represents a selector that can capture multiple
308+
* score holders.
309+
*
310+
* @return argument
311+
*/
312+
public static ArgumentType<ScoreHolderResolver> scoreHolders() {
313+
return provider().scoreHolders();
314+
}
315+
316+
/**
317+
* An operation argument.
318+
*
319+
* @return argument
320+
*/
321+
public static ArgumentType<Operation> operation() {
322+
return provider().operation();
323+
}
324+
294325
/**
295326
* An entity anchor argument.
296327
*

paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package io.papermc.paper.command.brigadier.argument;
22

33
import com.mojang.brigadier.arguments.ArgumentType;
4+
import io.papermc.paper.command.brigadier.argument.operation.Operation;
45
import io.papermc.paper.command.brigadier.argument.predicate.ItemStackPredicate;
56
import io.papermc.paper.command.brigadier.argument.range.DoubleRangeProvider;
67
import io.papermc.paper.command.brigadier.argument.range.IntegerRangeProvider;
78
import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver;
89
import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver;
910
import io.papermc.paper.command.brigadier.argument.resolvers.PlayerProfileListResolver;
1011
import io.papermc.paper.command.brigadier.argument.resolvers.RotationResolver;
12+
import io.papermc.paper.command.brigadier.argument.resolvers.ScoreHolderResolver;
1113
import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver;
1214
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver;
1315
import io.papermc.paper.entity.LookAnchor;
@@ -75,6 +77,12 @@ static VanillaArgumentProvider provider() {
7577
ArgumentType<SignedMessageResolver> signedMessage();
7678

7779
ArgumentType<DisplaySlot> scoreboardDisplaySlot();
80+
81+
ArgumentType<ScoreHolderResolver> scoreHolder();
82+
83+
ArgumentType<ScoreHolderResolver> scoreHolders();
84+
85+
ArgumentType<Operation> operation();
7886

7987
ArgumentType<NamespacedKey> namespacedKey();
8088

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package io.papermc.paper.command.brigadier.argument.operation;
2+
3+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
4+
import org.bukkit.scoreboard.Objective;
5+
import org.bukkit.scoreboard.ScoreHolder;
6+
import org.bukkit.scoreboard.Scoreboard;
7+
import org.jetbrains.annotations.ApiStatus;
8+
import org.jspecify.annotations.NullMarked;
9+
10+
/**
11+
* Represents a simple arithmetic operation between two integers.
12+
*/
13+
@ApiStatus.Experimental
14+
@NullMarked
15+
public interface Operation {
16+
17+
/**
18+
* Applies this operation to a set of integers
19+
*
20+
* @param left The left side of the expression
21+
* @param right The right side of the expression
22+
* @return The result of the operation
23+
*/
24+
int apply(int left, int right) throws CommandSyntaxException;
25+
26+
/**
27+
* Applies this operation to a set of score holders
28+
*
29+
* @param scoreboard The scoreboard to edit the score of
30+
* @param sourceObjective The objective to retrieve the score from
31+
* @param targetObjective The objective to edit the score of
32+
* @param targetHolder The target of the operation
33+
* @param sourceHolder The source of the operation
34+
*/
35+
void apply(Scoreboard scoreboard, Objective targetObjective, Objective sourceObjective, ScoreHolder targetHolder, ScoreHolder sourceHolder) throws CommandSyntaxException;
36+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.papermc.paper.command.brigadier.argument.resolvers;
2+
3+
import io.papermc.paper.command.brigadier.CommandSourceStack;
4+
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
5+
import org.bukkit.scoreboard.ScoreHolder;
6+
import org.jetbrains.annotations.ApiStatus;
7+
import java.util.Collection;
8+
9+
/**
10+
* An {@link ArgumentResolver} that's capable of resolving
11+
* argument value using a {@link CommandSourceStack} into a
12+
* collection of {@link ScoreHolder}s.
13+
*
14+
* @see ArgumentTypes#scoreHolders()
15+
*/
16+
@ApiStatus.Experimental
17+
@ApiStatus.NonExtendable
18+
public interface ScoreHolderResolver extends ArgumentResolver<Collection<ScoreHolder>> {
19+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.bukkit.scoreboard;
2+
3+
import io.papermc.paper.InternalAPIBridge;
4+
import net.kyori.adventure.text.Component;
5+
import org.bukkit.OfflinePlayer;
6+
import org.jetbrains.annotations.ApiStatus;
7+
import org.jspecify.annotations.NullMarked;
8+
9+
/**
10+
* Represents anything that can be used as an entry in a {@link Scoreboard}. Includes all entities,
11+
* players, and text.
12+
*/
13+
@ApiStatus.Experimental
14+
@NullMarked
15+
public interface ScoreHolder {
16+
17+
/**
18+
* The name used to access this {@link ScoreHolder} on a scoreboard.
19+
* @return the name
20+
*/
21+
String getScoreboardName();
22+
23+
/**
24+
* The display name of this {@link ScoreHolder}.
25+
* @return the display name
26+
*/
27+
default Component getDisplayName() {
28+
return Component.text(getScoreboardName());
29+
}
30+
31+
/**
32+
* Wraps an {@link OfflinePlayer} into a {@link ScoreHolder}.
33+
* @param offlinePlayer the player to wrap
34+
* @return a {@link ScoreHolder} representing the given player
35+
*/
36+
static ScoreHolder of(OfflinePlayer offlinePlayer) {
37+
return InternalAPIBridge.get().scoreHolderOf(offlinePlayer);
38+
}
39+
40+
/**
41+
* Wraps a {@link String} into a {@link ScoreHolder}.
42+
* @param entry the text to warp
43+
* @return a {@link ScoreHolder} representing the given String
44+
*/
45+
static ScoreHolder of(String entry) {
46+
return InternalAPIBridge.get().scoreHolderOf(entry);
47+
}
48+
}

paper-api/src/main/java/org/bukkit/scoreboard/Scoreboard.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.bukkit.scoreboard;
22

3+
import com.google.common.collect.ImmutableSet;
34
import java.util.Set;
45
import org.bukkit.OfflinePlayer;
56
import org.jetbrains.annotations.NotNull;
@@ -231,7 +232,9 @@ default Objective registerNewObjective(@NotNull String name, @NotNull Criteria c
231232
*/
232233
// @Deprecated(since = "1.7.8") // Paper
233234
@NotNull
234-
Set<Score> getScores(@NotNull OfflinePlayer player);
235+
default Set<Score> getScores(@NotNull OfflinePlayer player) {
236+
return getScores(ScoreHolder.of(player));
237+
}
235238

236239
/**
237240
* Gets all scores for an entry on this Scoreboard
@@ -240,7 +243,18 @@ default Objective registerNewObjective(@NotNull String name, @NotNull Criteria c
240243
* @return immutable set of all scores tracked for the entry
241244
*/
242245
@NotNull
243-
Set<Score> getScores(@NotNull String entry);
246+
default Set<Score> getScores(@NotNull String entry) {
247+
return getScores(ScoreHolder.of(entry));
248+
}
249+
250+
/**
251+
* Gets all scores for a ScoreHolder on this Scoreboard
252+
*
253+
* @param holder the ScoreHolder whose scores are being retrieved
254+
* @return immutable set of all scores tracked for the entry
255+
*/
256+
@NotNull
257+
ImmutableSet<Score> getScores(@NotNull ScoreHolder holder);
244258

245259
/**
246260
* Removes all scores for a player on this Scoreboard
@@ -249,14 +263,20 @@ default Objective registerNewObjective(@NotNull String name, @NotNull Criteria c
249263
* @see #resetScores(String)
250264
*/
251265
// @Deprecated(since = "1.7.8") // Paper
252-
void resetScores(@NotNull OfflinePlayer player);
266+
default void resetScores(@NotNull OfflinePlayer player) {
267+
resetScores(ScoreHolder.of(player));
268+
}
253269

254270
/**
255271
* Removes all scores for an entry on this Scoreboard
256272
*
257273
* @param entry the entry to drop all current scores for
258274
*/
259-
void resetScores(@NotNull String entry);
275+
default void resetScores(@NotNull String entry) {
276+
resetScores(ScoreHolder.of(entry));
277+
}
278+
279+
void resetScores(@NotNull ScoreHolder holder);
260280

261281
/**
262282
* Gets a player's Team on this Scoreboard
@@ -324,6 +344,9 @@ default Objective registerNewObjective(@NotNull String name, @NotNull Criteria c
324344
@NotNull
325345
Set<String> getEntries();
326346

347+
@NotNull
348+
Set<ScoreHolder> getHolders();
349+
327350
/**
328351
* Clears any objective in the specified slot.
329352
*
@@ -361,4 +384,24 @@ default Objective registerNewObjective(@NotNull String name, @NotNull Criteria c
361384
*/
362385
@Nullable Team getEntityTeam(@NotNull org.bukkit.entity.Entity entity) throws IllegalArgumentException;
363386
// Paper end - improve scoreboard entries
387+
388+
/**
389+
* Gets all scores for a score holder on this Scoreboard
390+
*
391+
* @param holder the score holder whose scores are being retrieved
392+
* @return immutable set of all scores tracked for the entity
393+
* @throws IllegalArgumentException if entity is null
394+
* @see #getScores(ScoreHolder)
395+
*/
396+
@NotNull Set<Score> getScoresFor(@NotNull ScoreHolder holder) throws IllegalArgumentException;
397+
398+
/**
399+
* Removes all scores for a score holder on this Scoreboard
400+
*
401+
* @param holder the score holder to drop all current scores for
402+
* @throws IllegalArgumentException if entity is null
403+
* @see #resetScores(ScoreHolder)
404+
*/
405+
void resetScoresFor(@NotNull ScoreHolder holder) throws IllegalArgumentException;
406+
364407
}

paper-server/src/main/java/io/papermc/paper/PaperServerInternalAPIBridge.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@
66
import io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper;
77
import net.minecraft.Optionull;
88
import net.minecraft.world.damagesource.FallLocation;
9+
import org.bukkit.OfflinePlayer;
910
import org.bukkit.block.Biome;
1011
import org.bukkit.craftbukkit.block.CraftBiome;
1112
import org.bukkit.craftbukkit.damage.CraftDamageEffect;
1213
import org.bukkit.craftbukkit.damage.CraftDamageSource;
1314
import org.bukkit.craftbukkit.entity.CraftLivingEntity;
15+
import org.bukkit.craftbukkit.scoreboard.CraftScoreHolder;
16+
import org.bukkit.craftbukkit.scoreboard.CraftScoreboard;
1417
import org.bukkit.damage.DamageEffect;
1518
import org.bukkit.damage.DamageSource;
1619
import org.bukkit.entity.LivingEntity;
20+
import org.bukkit.scoreboard.ScoreHolder;
1721
import org.jspecify.annotations.NullMarked;
1822
import org.jspecify.annotations.Nullable;
1923

@@ -71,4 +75,14 @@ private CombatEntry createCombatEntry(
7175
damageSource, damage, fallLocation, fallDistance
7276
));
7377
}
78+
79+
@Override
80+
public ScoreHolder scoreHolderOf(final String entry) {
81+
return new CraftScoreHolder(CraftScoreboard.getScoreHolder(entry));
82+
}
83+
84+
@Override
85+
public ScoreHolder scoreHolderOf(final OfflinePlayer player) {
86+
return new CraftScoreHolder(CraftScoreboard.getScoreHolder(player));
87+
}
7488
}

paper-server/src/main/java/io/papermc/paper/command/brigadier/ApiMirrorRootNode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ public static void validatePrimitiveType(ArgumentType<?> type) {
124124
}
125125

126126
converted = this.unwrapArgumentWrapper(pureArgumentNode, customArgumentType, customArgumentType.getNativeType(), suggestionProvider);
127+
} else if (pureArgumentType instanceof final VanillaArgumentProviderImpl.ScoreHolderWrapperArgumentType scoreHolderWrapperArgumentType) {
128+
// This is a special case, as we override the suggestions here
129+
converted = this.unwrapArgumentWrapper(pureArgumentNode, scoreHolderWrapperArgumentType, scoreHolderWrapperArgumentType, VanillaArgumentProviderImpl.ScoreHolderWrapperArgumentType.SUGGESTIONS);
127130
} else if (pureArgumentType instanceof final VanillaArgumentProviderImpl.NativeWrapperArgumentType<?, ?> nativeWrapperArgumentType) {
128131
converted = this.unwrapArgumentWrapper(pureArgumentNode, nativeWrapperArgumentType, nativeWrapperArgumentType, null); // "null" for suggestion provider so it uses the argument type's suggestion provider
129132

0 commit comments

Comments
 (0)