Finish converting most of the undeprecated api to jspecify

This commit is contained in:
Jake Potrebic 2024-09-30 11:44:36 -07:00
commit 0adf5876db
45 changed files with 782 additions and 718 deletions

View file

@ -512,14 +512,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import java.util.Collections;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Implementing this interface allows for easily creating "Bukkit-style" {@code String[] args} commands.
+ * The implementation handles converting the command to a representation compatible with Brigadier on registration, usually in the form of {@literal /commandlabel <greedy_string>}.
+ */
+@ApiStatus.Experimental
+@NullMarked
+@FunctionalInterface
+public interface BasicCommand {
+
@ -530,7 +531,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param args the arguments of the command ignoring repeated spaces
+ */
+ @ApiStatus.OverrideOnly
+ void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args);
+ void execute(CommandSourceStack commandSourceStack, String[] args);
+
+ /**
+ * Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
@ -540,7 +541,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @return a collection of suggestions
+ */
+ @ApiStatus.OverrideOnly
+ default @NotNull Collection<String> suggest(final @NotNull CommandSourceStack commandSourceStack, final @NotNull String[] args) {
+ default Collection<String> suggest(final CommandSourceStack commandSourceStack, final String[] args) {
+ return Collections.emptyList();
+ }
+
@ -552,8 +553,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @see #permission()
+ */
+ @ApiStatus.OverrideOnly
+ default boolean canUse(final @NotNull CommandSender sender) {
+ return this.permission() == null || sender.hasPermission(this.permission());
+ default boolean canUse(final CommandSender sender) {
+ final String permission = this.permission();
+ return permission == null || sender.hasPermission(permission);
+ }
+
+ /**
@ -598,8 +600,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Entity;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * The command source type for Brigadier commands registered using Paper API.
@ -613,8 +615,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * exist yet, or no specific sender is available. Methods on such a {@link CommandSender}
+ * will either have no effect or throw an {@link UnsupportedOperationException}.</p>
+ */
+@ApiStatus.NonExtendable
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.NonExtendable
+public interface CommandSourceStack {
+
+ /**
@ -622,7 +625,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return a cloned location instance.
+ */
+ @NotNull Location getLocation();
+ Location getLocation();
+
+ /**
+ * Gets the command sender that executed this command.
@ -631,7 +634,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return the command sender instance
+ */
+ @NotNull CommandSender getSender();
+ CommandSender getSender();
+
+ /**
+ * Gets the entity that executes this command.
@ -664,9 +667,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import java.util.Collections;
+import java.util.Set;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * The registrar for custom commands. Supports Brigadier commands and {@link BasicCommand}.
@ -709,6 +712,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @see io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents#COMMANDS
+ */
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.NonExtendable
+public interface Commands extends Registrar {
+
@ -718,7 +722,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param literal literal name
+ * @return a new builder instance
+ */
+ static @NotNull LiteralArgumentBuilder<CommandSourceStack> literal(final @NotNull String literal) {
+ static LiteralArgumentBuilder<CommandSourceStack> literal(final String literal) {
+ return LiteralArgumentBuilder.literal(literal);
+ }
+
@ -730,7 +734,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param <T> the generic type of the argument value
+ * @return a new required argument builder
+ */
+ static <T> @NotNull RequiredArgumentBuilder<CommandSourceStack, T> argument(final @NotNull String name, final @NotNull ArgumentType<T> argumentType) {
+ static <T> RequiredArgumentBuilder<CommandSourceStack, T> argument(final String name, final ArgumentType<T> argumentType) {
+ return RequiredArgumentBuilder.argument(name, argumentType);
+ }
+
@ -754,7 +758,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @return the dispatcher instance
+ */
+ @ApiStatus.Experimental
+ @NotNull CommandDispatcher<CommandSourceStack> getDispatcher();
+ CommandDispatcher<CommandSourceStack> getDispatcher();
+
+ /**
+ * Registers a command for the current plugin context.
@ -768,7 +772,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param node the built literal command node
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ default @Unmodifiable @NotNull Set<String> register(final @NotNull LiteralCommandNode<CommandSourceStack> node) {
+ default @Unmodifiable Set<String> register(final LiteralCommandNode<CommandSourceStack> node) {
+ return this.register(node, null, Collections.emptyList());
+ }
+
@ -785,7 +789,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param description the help description for the root literal node
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ default @Unmodifiable @NotNull Set<String> register(final @NotNull LiteralCommandNode<CommandSourceStack> node, final @Nullable String description) {
+ default @Unmodifiable Set<String> register(final LiteralCommandNode<CommandSourceStack> node, final @Nullable String description) {
+ return this.register(node, description, Collections.emptyList());
+ }
+
@ -802,7 +806,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param aliases a collection of aliases to register the literal node's command to
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ default @Unmodifiable @NotNull Set<String> register(final @NotNull LiteralCommandNode<CommandSourceStack> node, final @NotNull Collection<String> aliases) {
+ default @Unmodifiable Set<String> register(final LiteralCommandNode<CommandSourceStack> node, final Collection<String> aliases) {
+ return this.register(node, null, aliases);
+ }
+
@ -820,7 +824,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param aliases a collection of aliases to register the literal node's command to
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ @Unmodifiable @NotNull Set<String> register(@NotNull LiteralCommandNode<CommandSourceStack> node, @Nullable String description, @NotNull Collection<String> aliases);
+ @Unmodifiable Set<String> register(LiteralCommandNode<CommandSourceStack> node, @Nullable String description, Collection<String> aliases);
+
+ /**
+ * Registers a command for a plugin.
@ -837,7 +841,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param aliases a collection of aliases to register the literal node's command to
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ @Unmodifiable @NotNull Set<String> register(@NotNull PluginMeta pluginMeta, @NotNull LiteralCommandNode<CommandSourceStack> node, @Nullable String description, @NotNull Collection<String> aliases);
+ @Unmodifiable Set<String> register(PluginMeta pluginMeta, LiteralCommandNode<CommandSourceStack> node, @Nullable String description, Collection<String> aliases);
+
+ /**
+ * This allows configuring the registration of your command, which is not intended for public use.
@ -854,7 +858,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * See {@link CommandRegistrationFlag} for a more indepth explanation of this method's use-case.
+ */
+ @ApiStatus.Internal
+ @Unmodifiable @NotNull Set<String> registerWithFlags(@NotNull PluginMeta pluginMeta, @NotNull LiteralCommandNode<CommandSourceStack> node, @Nullable String description, @NotNull Collection<String> aliases, @NotNull Set<CommandRegistrationFlag> flags);
+ @Unmodifiable Set<String> registerWithFlags(PluginMeta pluginMeta, LiteralCommandNode<CommandSourceStack> node, @Nullable String description, Collection<String> aliases, Set<CommandRegistrationFlag> flags);
+
+ /**
+ * Registers a command under the same logic as {@link Commands#register(LiteralCommandNode, String, Collection)}.
@ -863,7 +867,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param basicCommand the basic command instance to register
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ default @Unmodifiable @NotNull Set<String> register(final @NotNull String label, final @NotNull BasicCommand basicCommand) {
+ default @Unmodifiable Set<String> register(final String label, final BasicCommand basicCommand) {
+ return this.register(label, null, Collections.emptyList(), basicCommand);
+ }
+
@ -875,7 +879,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param basicCommand the basic command instance to register
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ default @Unmodifiable @NotNull Set<String> register(final @NotNull String label, final @Nullable String description, final @NotNull BasicCommand basicCommand) {
+ default @Unmodifiable Set<String> register(final String label, final @Nullable String description, final BasicCommand basicCommand) {
+ return this.register(label, description, Collections.emptyList(), basicCommand);
+ }
+
@ -887,7 +891,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param basicCommand the basic command instance to register
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ default @Unmodifiable @NotNull Set<String> register(final @NotNull String label, final @NotNull Collection<String> aliases, final @NotNull BasicCommand basicCommand) {
+ default @Unmodifiable Set<String> register(final String label, final Collection<String> aliases, final BasicCommand basicCommand) {
+ return this.register(label, null, aliases, basicCommand);
+ }
+
@ -900,7 +904,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param basicCommand the basic command instance to register
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ @Unmodifiable @NotNull Set<String> register(@NotNull String label, @Nullable String description, @NotNull Collection<String> aliases, @NotNull BasicCommand basicCommand);
+ @Unmodifiable Set<String> register(String label, @Nullable String description, Collection<String> aliases, BasicCommand basicCommand);
+
+ /**
+ * Registers a command under the same logic as {@link Commands#register(PluginMeta, LiteralCommandNode, String, Collection)}.
@ -912,7 +916,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param basicCommand the basic command instance to register
+ * @return successfully registered root command labels (including aliases and namespaced variants)
+ */
+ @Unmodifiable @NotNull Set<String> register(@NotNull PluginMeta pluginMeta, @NotNull String label, @Nullable String description, @NotNull Collection<String> aliases, @NotNull BasicCommand basicCommand);
+ @Unmodifiable Set<String> register(PluginMeta pluginMeta, String label, @Nullable String description, Collection<String> aliases, BasicCommand basicCommand);
+}
diff --git a/src/main/java/io/papermc/paper/command/brigadier/MessageComponentSerializer.java b/src/main/java/io/papermc/paper/command/brigadier/MessageComponentSerializer.java
new file mode 100644
@ -926,12 +930,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.serializer.ComponentSerializer;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A component serializer for converting between {@link Message} and {@link Component}.
+ */
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.NonExtendable
+public interface MessageComponentSerializer extends ComponentSerializer<Component, Component, Message> {
+
@ -940,7 +945,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return serializer instance
+ */
+ static @NotNull MessageComponentSerializer message() {
+ static MessageComponentSerializer message() {
+ return MessageComponentSerializerHolder.PROVIDER.orElseThrow();
+ }
+}
@ -998,7 +1003,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import org.bukkit.scoreboard.Criteria;
+import org.bukkit.scoreboard.DisplaySlot;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+import static io.papermc.paper.command.brigadier.argument.VanillaArgumentProvider.provider;
+
@ -1011,6 +1016,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * <p>{@link CustomArgumentType} is provided for customizing parsing or result types server-side, while sending the vanilla argument type to the client.</p>
+ */
+@ApiStatus.Experimental
+@NullMarked
+public final class ArgumentTypes {
+
+ /**
@ -1019,7 +1025,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument that takes one entity
+ */
+ public static @NotNull ArgumentType<EntitySelectorArgumentResolver> entity() {
+ public static ArgumentType<EntitySelectorArgumentResolver> entity() {
+ return provider().entity();
+ }
+
@ -1029,7 +1035,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument that takes multiple entities
+ */
+ public static @NotNull ArgumentType<EntitySelectorArgumentResolver> entities() {
+ public static ArgumentType<EntitySelectorArgumentResolver> entities() {
+ return provider().entities();
+ }
+
@ -1039,7 +1045,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument that takes one player
+ */
+ public static @NotNull ArgumentType<PlayerSelectorArgumentResolver> player() {
+ public static ArgumentType<PlayerSelectorArgumentResolver> player() {
+ return provider().player();
+ }
+
@ -1049,7 +1055,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument that takes multiple players
+ */
+ public static @NotNull ArgumentType<PlayerSelectorArgumentResolver> players() {
+ public static ArgumentType<PlayerSelectorArgumentResolver> players() {
+ return provider().players();
+ }
+
@ -1059,7 +1065,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return player profile argument
+ */
+ public static @NotNull ArgumentType<PlayerProfileListResolver> playerProfiles() {
+ public static ArgumentType<PlayerProfileListResolver> playerProfiles() {
+ return provider().playerProfiles();
+ }
+
@ -1068,7 +1074,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return block position argument
+ */
+ public static @NotNull ArgumentType<BlockPositionResolver> blockPosition() {
+ public static ArgumentType<BlockPositionResolver> blockPosition() {
+ return provider().blockPosition();
+ }
+
@ -1078,7 +1084,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @return fine position argument
+ * @see #finePosition(boolean) to center whole numbers
+ */
+ public static @NotNull ArgumentType<FinePositionResolver> finePosition() {
+ public static ArgumentType<FinePositionResolver> finePosition() {
+ return finePosition(false);
+ }
+
@ -1088,7 +1094,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param centerIntegers if whole numbers should be centered (+0.5)
+ * @return fine position argument
+ */
+ public static @NotNull ArgumentType<FinePositionResolver> finePosition(final boolean centerIntegers) {
+ public static ArgumentType<FinePositionResolver> finePosition(final boolean centerIntegers) {
+ return provider().finePosition(centerIntegers);
+ }
+
@ -1098,7 +1104,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<BlockState> blockState() {
+ public static ArgumentType<BlockState> blockState() {
+ return provider().blockState();
+ }
+
@ -1108,7 +1114,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<ItemStack> itemStack() {
+ public static ArgumentType<ItemStack> itemStack() {
+ return provider().itemStack();
+ }
+
@ -1117,7 +1123,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<ItemStackPredicate> itemPredicate() {
+ public static ArgumentType<ItemStackPredicate> itemPredicate() {
+ return provider().itemStackPredicate();
+ }
+
@ -1126,7 +1132,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<NamedTextColor> namedColor() {
+ public static ArgumentType<NamedTextColor> namedColor() {
+ return provider().namedColor();
+ }
+
@ -1135,7 +1141,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<Component> component() {
+ public static ArgumentType<Component> component() {
+ return provider().component();
+ }
+
@ -1144,7 +1150,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<Style> style() {
+ public static ArgumentType<Style> style() {
+ return provider().style();
+ }
+
@ -1155,7 +1161,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<SignedMessageResolver> signedMessage() {
+ public static ArgumentType<SignedMessageResolver> signedMessage() {
+ return provider().signedMessage();
+ }
+
@ -1164,7 +1170,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<DisplaySlot> scoreboardDisplaySlot() {
+ public static ArgumentType<DisplaySlot> scoreboardDisplaySlot() {
+ return provider().scoreboardDisplaySlot();
+ }
+
@ -1173,7 +1179,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<NamespacedKey> namespacedKey() {
+ public static ArgumentType<NamespacedKey> namespacedKey() {
+ return provider().namespacedKey();
+ }
+
@ -1183,7 +1189,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @return argument
+ */
+ // include both key types as we are slowly moving to use adventure's key
+ public static @NotNull ArgumentType<Key> key() {
+ public static ArgumentType<Key> key() {
+ return provider().key();
+ }
+
@ -1192,7 +1198,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<IntegerRangeProvider> integerRange() {
+ public static ArgumentType<IntegerRangeProvider> integerRange() {
+ return provider().integerRange();
+ }
+
@ -1201,7 +1207,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<DoubleRangeProvider> doubleRange() {
+ public static ArgumentType<DoubleRangeProvider> doubleRange() {
+ return provider().doubleRange();
+ }
+
@ -1210,7 +1216,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<World> world() {
+ public static ArgumentType<World> world() {
+ return provider().world();
+ }
+
@ -1219,16 +1225,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<GameMode> gameMode() {
+ public static ArgumentType<GameMode> gameMode() {
+ return provider().gameMode();
+ }
+
+ /**
+ * A argument for getting a heightmap type.
+ * An argument for getting a heightmap type.
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<HeightMap> heightMap() {
+ public static ArgumentType<HeightMap> heightMap() {
+ return provider().heightMap();
+ }
+
@ -1237,7 +1243,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<UUID> uuid() {
+ public static ArgumentType<UUID> uuid() {
+ return provider().uuid();
+ }
+
@ -1246,7 +1252,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<Criteria> objectiveCriteria() {
+ public static ArgumentType<Criteria> objectiveCriteria() {
+ return provider().objectiveCriteria();
+ }
+
@ -1255,7 +1261,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<LookAnchor> entityAnchor() {
+ public static ArgumentType<LookAnchor> entityAnchor() {
+ return provider().entityAnchor();
+ }
+
@ -1271,7 +1277,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return argument
+ */
+ public static @NotNull ArgumentType<Integer> time() {
+ public static ArgumentType<Integer> time() {
+ return time(0);
+ }
+
@ -1288,7 +1294,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param mintime The minimum time required for this argument.
+ * @return argument
+ */
+ public static @NotNull ArgumentType<Integer> time(final int mintime) {
+ public static ArgumentType<Integer> time(final int mintime) {
+ return provider().time(mintime);
+ }
+
@ -1298,7 +1304,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @return argument
+ * @see Mirror
+ */
+ public static @NotNull ArgumentType<Mirror> templateMirror() {
+ public static ArgumentType<Mirror> templateMirror() {
+ return provider().templateMirror();
+ }
+
@ -1308,7 +1314,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @return argument
+ * @see StructureRotation
+ */
+ public static @NotNull ArgumentType<StructureRotation> templateRotation() {
+ public static ArgumentType<StructureRotation> templateRotation() {
+ return provider().templateRotation();
+ }
+
@ -1319,7 +1325,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @return argument
+ * @param <T> the registry value type
+ */
+ public static <T> @NotNull ArgumentType<T> resource(final @NotNull RegistryKey<T> registryKey) {
+ public static <T> ArgumentType<T> resource(final RegistryKey<T> registryKey) {
+ return provider().resource(registryKey);
+ }
+
@ -1331,7 +1337,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param <T> the registry value type
+ * @see RegistryArgumentExtractor#getTypedKey(com.mojang.brigadier.context.CommandContext, RegistryKey, String)
+ */
+ public static <T> @NotNull ArgumentType<TypedKey<T>> resourceKey(final @NotNull RegistryKey<T> registryKey) {
+ public static <T> ArgumentType<TypedKey<T>> resourceKey(final RegistryKey<T> registryKey) {
+ return provider().resourceKey(registryKey);
+ }
+
@ -1355,7 +1361,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import java.util.Collection;
+import java.util.concurrent.CompletableFuture;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * An argument type that wraps around a native-to-vanilla argument type.
@ -1370,6 +1376,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param <N> type with an argument native to vanilla Minecraft (from {@link ArgumentTypes})
+ */
+@ApiStatus.Experimental
+@NullMarked
+public interface CustomArgumentType<T, N> extends ArgumentType<T> {
+
+ /**
@ -1384,7 +1391,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @throws CommandSyntaxException if an error occurs while parsing
+ */
+ @Override
+ @NotNull T parse(final @NotNull StringReader reader) throws CommandSyntaxException;
+ T parse(final StringReader reader) throws CommandSyntaxException;
+
+ /**
+ * Gets the native type that this argument uses,
@ -1392,7 +1399,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return native argument type
+ */
+ @NotNull ArgumentType<N> getNativeType();
+ ArgumentType<N> getNativeType();
+
+ /**
+ * Cannot be controlled by the server.
@ -1403,7 +1410,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ */
+ @Override
+ @ApiStatus.NonExtendable
+ default @NotNull Collection<String> getExamples() {
+ default Collection<String> getExamples() {
+ return this.getNativeType().getExamples();
+ }
+
@ -1416,7 +1423,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param <S> context type
+ */
+ @Override
+ default <S> @NotNull CompletableFuture<Suggestions> listSuggestions(final @NotNull CommandContext<S> context, final @NotNull SuggestionsBuilder builder) {
+ default <S> CompletableFuture<Suggestions> listSuggestions(final CommandContext<S> context, final SuggestionsBuilder builder) {
+ return ArgumentType.super.listSuggestions(context, builder);
+ }
+
@ -1436,7 +1443,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ @ApiStatus.NonExtendable
+ @Override
+ default @NotNull T parse(final @NotNull StringReader reader) throws CommandSyntaxException {
+ default T parse(final StringReader reader) throws CommandSyntaxException {
+ return this.convert(this.getNativeType().parse(reader));
+ }
+
@ -1447,7 +1454,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @return converted value
+ * @throws CommandSyntaxException if an exception occurs while parsing
+ */
+ @NotNull T convert(@NotNull N nativeType) throws CommandSyntaxException;
+ T convert(N nativeType) throws CommandSyntaxException;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/command/brigadier/argument/RegistryArgumentExtractor.java b/src/main/java/io/papermc/paper/command/brigadier/argument/RegistryArgumentExtractor.java
@ -1461,11 +1468,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import com.mojang.brigadier.context.CommandContext;
+import io.papermc.paper.registry.RegistryKey;
+import io.papermc.paper.registry.TypedKey;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Utilities for extracting registry-related arguments from a {@link CommandContext}.
+ */
+@NullMarked
+public final class RegistryArgumentExtractor {
+
+ /**
@ -1480,7 +1488,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @throws IllegalArgumentException if the registry key doesn't match the typed key
+ */
+ @SuppressWarnings("unchecked")
+ public static <T, S> @NonNull TypedKey<T> getTypedKey(final @NonNull CommandContext<S> context, final @NonNull RegistryKey<T> registryKey, final @NonNull String name) {
+ public static <T, S> TypedKey<T> getTypedKey(final CommandContext<S> context, final RegistryKey<T> registryKey, final String name) {
+ final TypedKey<T> typedKey = context.getArgument(name, TypedKey.class);
+ if (typedKey.registryKey().equals(registryKey)) {
+ return typedKey;
@ -1505,7 +1513,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import java.util.concurrent.CompletableFuture;
+import net.kyori.adventure.chat.SignedMessage;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A resolver for a {@link SignedMessage}
@ -1513,6 +1521,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @see ArgumentTypes#signedMessage()
+ */
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.NonExtendable
+public interface SignedMessageResolver {
+
@ -1521,7 +1530,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ *
+ * @return string content
+ */
+ @NotNull String content();
+ String content();
+
+ /**
+ * Resolves this signed message. This will the {@link CommandContext}
@ -1535,7 +1544,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @return a completable future for the {@link SignedMessage}
+ * @throws CommandSyntaxException syntax exception
+ */
+ @NotNull CompletableFuture<SignedMessage> resolveSignedMessage(@NotNull String argumentName, @NotNull CommandContext<CommandSourceStack> context) throws CommandSyntaxException;
+ CompletableFuture<SignedMessage> resolveSignedMessage(String argumentName, CommandContext<CommandSourceStack> context) throws CommandSyntaxException;
+
+}
diff --git a/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java b/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java
@ -1575,12 +1584,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scoreboard.Criteria;
+import org.bukkit.scoreboard.DisplaySlot;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+@ApiStatus.Internal
+@DefaultQualifier(NonNull.class)
+@NullMarked
+interface VanillaArgumentProvider {
+
+ Optional<VanillaArgumentProvider> PROVIDER = ServiceLoader.load(VanillaArgumentProvider.class)
@ -1722,7 +1730,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+import com.google.common.collect.Range;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * A provider for a range of numbers
@ -1731,13 +1739,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @see io.papermc.paper.command.brigadier.argument.ArgumentTypes
+ */
+@ApiStatus.Experimental
+@NullMarked
+public sealed interface RangeProvider<T extends Comparable<?>> permits DoubleRangeProvider, IntegerRangeProvider {
+
+ /**
+ * Provides the given range.
+ * @return range
+ */
+ @NotNull
+ Range<T> range();
+}
diff --git a/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/ArgumentResolver.java b/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/ArgumentResolver.java
@ -1751,7 +1759,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import io.papermc.paper.command.brigadier.CommandSourceStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * An {@link ArgumentResolver} is capable of resolving
@ -1761,6 +1769,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @see io.papermc.paper.command.brigadier.argument.ArgumentTypes
+ */
+@ApiStatus.Experimental
+@NullMarked
+@ApiStatus.NonExtendable
+public interface ArgumentResolver<T> {
+
@ -1770,7 +1779,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param sourceStack source stack
+ * @return resolved
+ */
+ @NotNull T resolve(@NotNull CommandSourceStack sourceStack) throws CommandSyntaxException;
+ T resolve(CommandSourceStack sourceStack) throws CommandSyntaxException;
+}
diff --git a/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/BlockPositionResolver.java b/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/BlockPositionResolver.java
new file mode 100644
@ -1928,9 +1937,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.ApiStatus;
@@ -0,0 +0,0 @@ import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Experimental
import org.jspecify.annotations.NullMarked;
@@ -0,0 +0,0 @@ import org.jspecify.annotations.NullMarked;
@NullMarked
public final class LifecycleEvents {
+ /**