From 35129eb5222769e50e7e411c54c9049548104824 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 6 Sep 2025 11:49:47 -0700 Subject: [PATCH 01/20] Add helper methods for vanilla-style command feedback --- .../command/brigadier/CommandSourceStack.java | 50 +++++++++++++++++++ .../commands/CommandSourceStack.java.patch | 12 +++++ .../brigadier/PaperCommandSourceStack.java | 33 ++++++++++-- 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index a6e01ffa3f30..4adde2927a9a 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -2,11 +2,17 @@ import com.mojang.brigadier.RedirectModifier; import com.mojang.brigadier.tree.CommandNode; +import net.kyori.adventure.text.ComponentLike; +import org.bukkit.GameRule; import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.Nullable; +import java.util.function.Supplier; + +import static java.util.Objects.requireNonNull; /** * The command source type for Brigadier commands registered using Paper API. @@ -67,4 +73,48 @@ public interface CommandSourceStack { * @see com.mojang.brigadier.builder.ArgumentBuilder#fork(CommandNode, RedirectModifier) */ CommandSourceStack withExecutor(Entity executor); + + /** + * Sends a system message to the {@link #getExecutor()} if it is a {@link Player}, + * otherwise sends a system message to the {@link #getSender()}. + * + * @param message the message to send + */ + void sendSystemMessage(ComponentLike message); + + /** + * Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution + * according to vanilla semantics. + * + * @param message the message to send + * @param allowInformingAdmins whether admins and console may be informed of this success + * @see #sendSuccess(Supplier, boolean) for further details + */ + default void sendSuccess(ComponentLike message, boolean allowInformingAdmins) { + requireNonNull(message, "message"); + this.sendSuccess(() -> message, allowInformingAdmins); + } + + /** + * Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution + * according to vanilla semantics. + * + *

This currently includes checking for environments with suppressed output, + * {@link GameRule#SEND_COMMAND_FEEDBACK}, and {@link GameRule#LOG_ADMIN_COMMANDS}.

+ * + *

If no message is sent (due to the above reasons or otherwise) the message supplier will not be invoked.

+ * + * @param messageSupplier the message to send + * @param allowInformingAdmins whether admins and console may be informed of this success + */ + void sendSuccess(Supplier messageSupplier, boolean allowInformingAdmins); + + /** + * Sends a system message indicating a failed command execution to the {@link #getSender()}. + * + *

Respects vanilla semantics for accepting failure output and suppressed output environments.

+ * + * @param message the message to send + */ + void sendFailure(ComponentLike message); } diff --git a/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch b/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch index 8f350ebabe4a..5fcde063410d 100644 --- a/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch +++ b/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch @@ -81,6 +81,18 @@ public Vec3 getPosition() { return this.worldPosition; } +@@ -481,7 +_,10 @@ + } + } + +- public void sendSuccess(Supplier messageSupplier, boolean allowLogging) { ++ // Paper start - extend Supplier to resolve ambiguity with API method of same signature ++ public interface SuccessMessageSupplier extends Supplier {} ++ public void sendSuccess(SuccessMessageSupplier messageSupplier, boolean allowLogging) { ++ // Paper end - extend Supplier to resolve ambiguity with API method of same signature + boolean flag = this.source.acceptsSuccess() && !this.silent; + boolean flag1 = allowLogging && this.source.shouldInformAdmins() && !this.silent; + if (flag || flag1) { @@ -500,20 +_,25 @@ Component component = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) { diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java index 0f7bbc9193bd..cac6fa504795 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java @@ -2,6 +2,8 @@ import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; import com.google.common.base.Preconditions; +import io.papermc.paper.adventure.PaperAdventure; +import net.kyori.adventure.text.ComponentLike; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; @@ -11,6 +13,9 @@ import org.bukkit.entity.Entity; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; +import java.util.function.Supplier; + +import static java.util.Objects.requireNonNull; public interface PaperCommandSourceStack extends CommandSourceStack, BukkitBrigadierCommandSource { @@ -26,14 +31,12 @@ public interface PaperCommandSourceStack extends CommandSourceStack, BukkitBriga } @Override - @NonNull - default CommandSender getSender() { + default @NonNull CommandSender getSender() { return this.getHandle().getBukkitSender(); } @Override - @Nullable - default Entity getExecutor() { + default @Nullable Entity getExecutor() { net.minecraft.world.entity.Entity nmsEntity = this.getHandle().getEntity(); if (nmsEntity == null) { return null; @@ -43,11 +46,31 @@ default Entity getExecutor() { } @Override - default CommandSourceStack withExecutor(@NonNull Entity executor) { + default @NonNull CommandSourceStack withExecutor(@NonNull Entity executor) { Preconditions.checkNotNull(executor, "Executor cannot be null."); return this.getHandle().withEntity(((CraftEntity) executor).getHandle()); } + @Override + default void sendSystemMessage(final @NonNull ComponentLike message) { + requireNonNull(message, "message"); + this.getHandle().sendSystemMessage(PaperAdventure.asVanilla(message.asComponent())); + } + + @Override + default void sendSuccess(final @NonNull Supplier<@NonNull ComponentLike> messageSupplier, final boolean allowInformingAdmins) { + requireNonNull(messageSupplier, "messageSupplier"); + this.getHandle().sendSuccess(() -> { + return PaperAdventure.asVanilla(requireNonNull(messageSupplier.get(), "messageSupplier.get()").asComponent()); + }, allowInformingAdmins); + } + + @Override + default void sendFailure(final @NonNull ComponentLike message) { + requireNonNull(message, "message"); + this.getHandle().sendFailure(PaperAdventure.asVanilla(message.asComponent()), false); + } + // OLD METHODS @Override default org.bukkit.entity.Entity getBukkitEntity() { From 033263f5b45e433c43b039c249b3d401ce0c8c75 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 6 Sep 2025 12:00:23 -0700 Subject: [PATCH 02/20] fix compile --- .../server/commands/FillBiomeCommand.java.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 paper-server/patches/sources/net/minecraft/server/commands/FillBiomeCommand.java.patch diff --git a/paper-server/patches/sources/net/minecraft/server/commands/FillBiomeCommand.java.patch b/paper-server/patches/sources/net/minecraft/server/commands/FillBiomeCommand.java.patch new file mode 100644 index 000000000000..6e5c83b4d774 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/server/commands/FillBiomeCommand.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/commands/FillBiomeCommand.java ++++ b/net/minecraft/server/commands/FillBiomeCommand.java +@@ -108,7 +_,7 @@ + } + + public static Either fill( +- ServerLevel level, BlockPos from, BlockPos to, Holder biome, Predicate> filter, Consumer> messageOutput ++ ServerLevel level, BlockPos from, BlockPos to, Holder biome, Predicate> filter, Consumer messageOutput // Paper - fix type for our change + ) { + BlockPos blockPos = quantize(from); + BlockPos blockPos1 = quantize(to); From 55f359243bb4b5cd21c88555ac85bb0a1410aed7 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 6 Sep 2025 12:23:08 -0700 Subject: [PATCH 03/20] Adjust brig tests --- .../command/brigadier/CommandSourceStack.java | 1 + .../testplugin/brigtests/Registration.java | 37 ++++++++++++++----- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 4adde2927a9a..ff8f740c75c6 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -111,6 +111,7 @@ default void sendSuccess(ComponentLike message, boolean allowInformingAdmins) { /** * Sends a system message indicating a failed command execution to the {@link #getSender()}. + * Does not apply red styling to the message as vanilla does to allow for custom failure message styling. * *

Respects vanilla semantics for accepting failure output and suppressed output environments.

* diff --git a/test-plugin/src/main/java/io/papermc/testplugin/brigtests/Registration.java b/test-plugin/src/main/java/io/papermc/testplugin/brigtests/Registration.java index 01837b2088ae..7d8b92200048 100644 --- a/test-plugin/src/main/java/io/papermc/testplugin/brigtests/Registration.java +++ b/test-plugin/src/main/java/io/papermc/testplugin/brigtests/Registration.java @@ -1,6 +1,8 @@ package io.papermc.testplugin.brigtests; import com.mojang.brigadier.Command; +import com.mojang.brigadier.arguments.BoolArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; import io.papermc.paper.command.brigadier.BasicCommand; import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.Commands; @@ -19,6 +21,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.command.defaults.BukkitCommand; @@ -45,7 +49,7 @@ private static void registerViaLifecycleEvents(final JavaPlugin plugin) { .then( Commands.argument("name", ArgumentTypes.resource(RegistryKey.ENCHANTMENT)) .executes(ctx -> { - ctx.getSource().getSender().sendPlainMessage(ctx.getArgument("name", Enchantment.class).toString()); + ctx.getSource().sendSuccess(Component.text(ctx.getArgument("name", Enchantment.class).toString()), false); return Command.SINGLE_SUCCESS; }) ).build() @@ -55,7 +59,7 @@ private static void registerViaLifecycleEvents(final JavaPlugin plugin) { Commands.argument("key", ArgumentTypes.resourceKey(RegistryKey.ENCHANTMENT)) .executes(ctx -> { final TypedKey key = RegistryArgumentExtractor.getTypedKey(ctx, RegistryKey.ENCHANTMENT, "key"); - ctx.getSource().getSender().sendPlainMessage(key.toString()); + ctx.getSource().sendSuccess(Component.text(key.toString()), false); return Command.SINGLE_SUCCESS; }) ).build() @@ -65,7 +69,7 @@ private static void registerViaLifecycleEvents(final JavaPlugin plugin) { Commands.argument("pos", ArgumentTypes.finePosition(false)) .executes(ctx -> { final FinePositionResolver position = ctx.getArgument("pos", FinePositionResolver.class); - ctx.getSource().getSender().sendPlainMessage("Position: " + position.resolve(ctx.getSource())); + ctx.getSource().sendSuccess(Component.text("Position: " + position.resolve(ctx.getSource())), false); return Command.SINGLE_SUCCESS; }) ).build() @@ -73,7 +77,7 @@ private static void registerViaLifecycleEvents(final JavaPlugin plugin) { // ensure plugin commands override commands.register(Commands.literal("tag") .executes(ctx -> { - ctx.getSource().getSender().sendPlainMessage("overriden command"); + ctx.getSource().sendSuccess(Component.text("overriden command"), false); return Command.SINGLE_SUCCESS; }) .build(), @@ -88,7 +92,7 @@ private static void registerViaLifecycleEvents(final JavaPlugin plugin) { .then(Commands.literal("sub_command") .requires(source -> source.getSender().hasPermission("testplugin.test")) .executes(ctx -> { - ctx.getSource().getSender().sendPlainMessage("root_command sub_command"); + ctx.getSource().sendSuccess(Component.text("root_command sub_command"), false); return Command.SINGLE_SUCCESS; })).build(), null, @@ -165,14 +169,14 @@ public static void registerViaBootstrap(final BootstrapContext context) { .then(Commands.literal("item") .then(Commands.argument("mat", MaterialArgumentType.item()) .executes(ctx -> { - ctx.getSource().getSender().sendPlainMessage(ctx.getArgument("mat", Material.class).name()); + ctx.getSource().sendSuccess(Component.text(ctx.getArgument("mat", Material.class).name()), false); return Command.SINGLE_SUCCESS; }) ) ).then(Commands.literal("block") .then(Commands.argument("mat", MaterialArgumentType.block()) .executes(ctx -> { - ctx.getSource().getSender().sendPlainMessage(ctx.getArgument("mat", Material.class).name()); + ctx.getSource().sendSuccess(Component.text(ctx.getArgument("mat", Material.class).name()), false); return Command.SINGLE_SUCCESS; }) ) @@ -181,6 +185,21 @@ public static void registerViaBootstrap(final BootstrapContext context) { null, Collections.emptyList() ); + + commands.register(Commands.literal("send_success") + .then(Commands.argument("allow_inform_admins", BoolArgumentType.bool()) + .then(Commands.argument("msg", StringArgumentType.greedyString()) + .executes(ctx -> { + ctx.getSource().sendSuccess( + MiniMessage.miniMessage().deserialize(StringArgumentType.getString(ctx, "msg")), + BoolArgumentType.getBool(ctx, "allow_inform_admins") + ); + return Command.SINGLE_SUCCESS; + }))) + .build(), + null, + Collections.emptyList() + ); }); lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS.newHandler(event -> { @@ -188,8 +207,8 @@ public static void registerViaBootstrap(final BootstrapContext context) { commands.register(Commands.literal("heya") .then(Commands.argument("range", ArgumentTypes.doubleRange()) .executes((ct) -> { - ct.getSource().getSender().sendPlainMessage(ct.getArgument("range", DoubleRangeProvider.class).range().toString()); - return 1; + ct.getSource().sendSuccess(Component.text(ct.getArgument("range", DoubleRangeProvider.class).range().toString()), false); + return Command.SINGLE_SUCCESS; }) ).build(), null, From 05f38012375a3bb1d7db7e02aadf2f5be4bfb9d9 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 6 Sep 2025 13:22:37 -0700 Subject: [PATCH 04/20] remove supplier API --- .../command/brigadier/CommandSourceStack.java | 22 ++----------------- .../commands/CommandSourceStack.java.patch | 12 ---------- .../commands/FillBiomeCommand.java.patch | 11 ---------- .../brigadier/PaperCommandSourceStack.java | 9 +++----- 4 files changed, 5 insertions(+), 49 deletions(-) delete mode 100644 paper-server/patches/sources/net/minecraft/server/commands/FillBiomeCommand.java.patch diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index ff8f740c75c6..2e94bd21a114 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -10,9 +10,6 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.Nullable; -import java.util.function.Supplier; - -import static java.util.Objects.requireNonNull; /** * The command source type for Brigadier commands registered using Paper API. @@ -82,19 +79,6 @@ public interface CommandSourceStack { */ void sendSystemMessage(ComponentLike message); - /** - * Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution - * according to vanilla semantics. - * - * @param message the message to send - * @param allowInformingAdmins whether admins and console may be informed of this success - * @see #sendSuccess(Supplier, boolean) for further details - */ - default void sendSuccess(ComponentLike message, boolean allowInformingAdmins) { - requireNonNull(message, "message"); - this.sendSuccess(() -> message, allowInformingAdmins); - } - /** * Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution * according to vanilla semantics. @@ -102,12 +86,10 @@ default void sendSuccess(ComponentLike message, boolean allowInformingAdmins) { *

This currently includes checking for environments with suppressed output, * {@link GameRule#SEND_COMMAND_FEEDBACK}, and {@link GameRule#LOG_ADMIN_COMMANDS}.

* - *

If no message is sent (due to the above reasons or otherwise) the message supplier will not be invoked.

- * - * @param messageSupplier the message to send + * @param message the message to send * @param allowInformingAdmins whether admins and console may be informed of this success */ - void sendSuccess(Supplier messageSupplier, boolean allowInformingAdmins); + void sendSuccess(ComponentLike message, boolean allowInformingAdmins); /** * Sends a system message indicating a failed command execution to the {@link #getSender()}. diff --git a/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch b/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch index 5fcde063410d..8f350ebabe4a 100644 --- a/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch +++ b/paper-server/patches/sources/net/minecraft/commands/CommandSourceStack.java.patch @@ -81,18 +81,6 @@ public Vec3 getPosition() { return this.worldPosition; } -@@ -481,7 +_,10 @@ - } - } - -- public void sendSuccess(Supplier messageSupplier, boolean allowLogging) { -+ // Paper start - extend Supplier to resolve ambiguity with API method of same signature -+ public interface SuccessMessageSupplier extends Supplier {} -+ public void sendSuccess(SuccessMessageSupplier messageSupplier, boolean allowLogging) { -+ // Paper end - extend Supplier to resolve ambiguity with API method of same signature - boolean flag = this.source.acceptsSuccess() && !this.silent; - boolean flag1 = allowLogging && this.source.shouldInformAdmins() && !this.silent; - if (flag || flag1) { @@ -500,20 +_,25 @@ Component component = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) { diff --git a/paper-server/patches/sources/net/minecraft/server/commands/FillBiomeCommand.java.patch b/paper-server/patches/sources/net/minecraft/server/commands/FillBiomeCommand.java.patch deleted file mode 100644 index 6e5c83b4d774..000000000000 --- a/paper-server/patches/sources/net/minecraft/server/commands/FillBiomeCommand.java.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/net/minecraft/server/commands/FillBiomeCommand.java -+++ b/net/minecraft/server/commands/FillBiomeCommand.java -@@ -108,7 +_,7 @@ - } - - public static Either fill( -- ServerLevel level, BlockPos from, BlockPos to, Holder biome, Predicate> filter, Consumer> messageOutput -+ ServerLevel level, BlockPos from, BlockPos to, Holder biome, Predicate> filter, Consumer messageOutput // Paper - fix type for our change - ) { - BlockPos blockPos = quantize(from); - BlockPos blockPos1 = quantize(to); diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java index cac6fa504795..d9a85afbda60 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java @@ -13,7 +13,6 @@ import org.bukkit.entity.Entity; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; -import java.util.function.Supplier; import static java.util.Objects.requireNonNull; @@ -58,11 +57,9 @@ default void sendSystemMessage(final @NonNull ComponentLike message) { } @Override - default void sendSuccess(final @NonNull Supplier<@NonNull ComponentLike> messageSupplier, final boolean allowInformingAdmins) { - requireNonNull(messageSupplier, "messageSupplier"); - this.getHandle().sendSuccess(() -> { - return PaperAdventure.asVanilla(requireNonNull(messageSupplier.get(), "messageSupplier.get()").asComponent()); - }, allowInformingAdmins); + default void sendSuccess(final @NonNull ComponentLike message, final boolean allowInformingAdmins) { + requireNonNull(message, "message"); + this.getHandle().sendSuccess(() -> PaperAdventure.asVanilla(message.asComponent()), allowInformingAdmins); } @Override From f1a5d1fe3ce8605b1f7f21ac47def748264fee19 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 6 Sep 2025 13:31:56 -0700 Subject: [PATCH 05/20] rename sendSystemMessage --- .../io/papermc/paper/command/brigadier/CommandSourceStack.java | 2 +- .../paper/command/brigadier/PaperCommandSourceStack.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 2e94bd21a114..1a6c78892a0e 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -77,7 +77,7 @@ public interface CommandSourceStack { * * @param message the message to send */ - void sendSystemMessage(ComponentLike message); + void sendToTarget(ComponentLike message); /** * Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java index d9a85afbda60..330919d7e50f 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java @@ -51,7 +51,7 @@ public interface PaperCommandSourceStack extends CommandSourceStack, BukkitBriga } @Override - default void sendSystemMessage(final @NonNull ComponentLike message) { + default void sendToTarget(final @NonNull ComponentLike message) { requireNonNull(message, "message"); this.getHandle().sendSystemMessage(PaperAdventure.asVanilla(message.asComponent())); } From e086eba479eb1d932ac01457c03f8fd53f85fea7 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 7 Oct 2025 12:55:38 -0700 Subject: [PATCH 06/20] Use preconditions --- .../paper/command/brigadier/PaperCommandSourceStack.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java index 330919d7e50f..d37d9c77aa41 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java @@ -14,8 +14,6 @@ import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; -import static java.util.Objects.requireNonNull; - public interface PaperCommandSourceStack extends CommandSourceStack, BukkitBrigadierCommandSource { net.minecraft.commands.CommandSourceStack getHandle(); @@ -52,19 +50,19 @@ public interface PaperCommandSourceStack extends CommandSourceStack, BukkitBriga @Override default void sendToTarget(final @NonNull ComponentLike message) { - requireNonNull(message, "message"); + Preconditions.checkNotNull(message, "message cannot be null."); this.getHandle().sendSystemMessage(PaperAdventure.asVanilla(message.asComponent())); } @Override default void sendSuccess(final @NonNull ComponentLike message, final boolean allowInformingAdmins) { - requireNonNull(message, "message"); + Preconditions.checkNotNull(message, "message cannot be null."); this.getHandle().sendSuccess(() -> PaperAdventure.asVanilla(message.asComponent()), allowInformingAdmins); } @Override default void sendFailure(final @NonNull ComponentLike message) { - requireNonNull(message, "message"); + Preconditions.checkNotNull(message, "message cannot be null."); this.getHandle().sendFailure(PaperAdventure.asVanilla(message.asComponent()), false); } From 5339b2df98b361cf498f330d7b4d5e5f3f3fa7a8 Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Fri, 2 Oct 2026 11:10:42 +0200 Subject: [PATCH 07/20] Rename sendSystemMessage to sendReply --- .../io/papermc/paper/command/brigadier/CommandSourceStack.java | 2 +- .../paper/command/brigadier/PaperCommandSourceStack.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 610dfd6d3549..5b6dff704ecf 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -90,7 +90,7 @@ public interface CommandSourceStack { * * @param message the message to send */ - void sendToTarget(ComponentLike message); + void sendReply(ComponentLike message); /** * Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java index 1cb17fe0b9d4..7f225a39e640 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java @@ -52,7 +52,7 @@ default CommandSourceStack withExecutor(Entity executor) { } @Override - default void sendToTarget(final ComponentLike message) { + default void sendReply(final ComponentLike message) { Preconditions.checkNotNull(message, "message cannot be null."); this.getHandle().sendSystemMessage(PaperAdventure.asVanilla(message.asComponent())); } From c217fb806c380fd46e71d50a46892926c123b74c Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Fri, 2 Oct 2026 11:13:03 +0200 Subject: [PATCH 08/20] Add simple sendSuccess overload --- .../command/brigadier/CommandSourceStack.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 5b6dff704ecf..2674f9ea4ca9 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -5,6 +5,7 @@ import com.mojang.brigadier.tree.CommandNode; import net.kyori.adventure.text.ComponentLike; import org.bukkit.GameRule; +import org.bukkit.GameRules; import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Entity; @@ -104,6 +105,20 @@ public interface CommandSourceStack { */ void sendSuccess(ComponentLike message, boolean allowInformingAdmins); + /** + * Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution + * according to vanilla semantics. This method informs admins and the console of this success. + * + *

This currently includes checking for environments with suppressed output, + * {@link GameRule#SEND_COMMAND_FEEDBACK}, and {@link GameRule#LOG_ADMIN_COMMANDS}.

+ * + * @param message the message to send + * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed + */ + default void sendSuccess(ComponentLike message) { + sendSuccess(message, true); + } + /** * Sends a system message indicating a failed command execution to the {@link #getSender()}. * Does not apply red styling to the message as vanilla does to allow for custom failure message styling. From f4479ae97da1dbb3b1ef8b573253d1e2470c393e Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Fri, 2 Oct 2026 11:14:35 +0200 Subject: [PATCH 09/20] Replace GameRule mention in JD with GameRules --- .../papermc/paper/command/brigadier/CommandSourceStack.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 2674f9ea4ca9..5dbc89a11b1b 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -4,7 +4,6 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.CommandNode; import net.kyori.adventure.text.ComponentLike; -import org.bukkit.GameRule; import org.bukkit.GameRules; import org.bukkit.Location; import org.bukkit.command.CommandSender; @@ -98,7 +97,7 @@ public interface CommandSourceStack { * according to vanilla semantics. * *

This currently includes checking for environments with suppressed output, - * {@link GameRule#SEND_COMMAND_FEEDBACK}, and {@link GameRule#LOG_ADMIN_COMMANDS}.

+ * {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.

* * @param message the message to send * @param allowInformingAdmins whether admins and console may be informed of this success @@ -110,7 +109,7 @@ public interface CommandSourceStack { * according to vanilla semantics. This method informs admins and the console of this success. * *

This currently includes checking for environments with suppressed output, - * {@link GameRule#SEND_COMMAND_FEEDBACK}, and {@link GameRule#LOG_ADMIN_COMMANDS}.

+ * {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.

* * @param message the message to send * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed From 8f032530d2ba55a1947df50fc8a17f0ab8db387e Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Fri, 2 Oct 2026 11:33:48 +0200 Subject: [PATCH 10/20] Add rich variants accepting MiniMessage --- .../command/brigadier/CommandSourceStack.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 5dbc89a11b1b..6fe85c28ede8 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -4,6 +4,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.CommandNode; import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.bukkit.GameRules; import org.bukkit.Location; import org.bukkit.command.CommandSender; @@ -92,6 +94,21 @@ public interface CommandSourceStack { */ void sendReply(ComponentLike message); + /** + * Sends a system message with the MiniMessage format to the {@link #getExecutor()} + * if it is a {@link Player}, otherwise sends it to the {@link #getSender()}. + * + *

See MiniMessage docs and + * MiniMessage Placeholders docs + * for more information on the format.

+ * + * @param message the MiniMessage message to send + * @param resolvers resolvers to use + */ + default void sendRichReply(String message, TagResolver... resolvers) { + sendReply(MiniMessage.miniMessage().deserialize(message, resolvers)); + } + /** * Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution * according to vanilla semantics. @@ -118,6 +135,45 @@ default void sendSuccess(ComponentLike message) { sendSuccess(message, true); } + /** + * Sends a system message with the MiniMessage format to the {@link #getSender()}, admins, and console indicating + * successful command execution according to vanilla semantics. + * + *

This currently includes checking for environments with suppressed output, + * {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.

+ * + *

See MiniMessage docs and + * MiniMessage Placeholders docs + * for more information on the format.

+ * + * @param message the MiniMessage message to send + * @param allowInformingAdmins whether admins and console may be informed of this success + * @param resolvers resolvers to use + */ + default void sendRichSuccess(String message, boolean allowInformingAdmins, TagResolver... resolvers) { + sendSuccess(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers), allowInformingAdmins); + } + + /** + * Sends a system message with the MiniMessage format to the {@link #getSender()}, admins, and console indicating + * successful command execution according to vanilla semantics. This method informs admins and the console of + * this success. + * + *

This currently includes checking for environments with suppressed output, + * {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.

+ * + *

See MiniMessage docs and + * MiniMessage Placeholders docs + * for more information on the format.

+ * + * @param message the MiniMessage message to send + * @param resolvers resolvers to use + * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed + */ + default void sendRichSuccess(String message, TagResolver... resolvers) { + sendRichSuccess(message, true, resolvers); + } + /** * Sends a system message indicating a failed command execution to the {@link #getSender()}. * Does not apply red styling to the message as vanilla does to allow for custom failure message styling. @@ -127,4 +183,21 @@ default void sendSuccess(ComponentLike message) { * @param message the message to send */ void sendFailure(ComponentLike message); + + /** + * Sends a system message with the MiniMessage format indicating a failed command execution to the{@link #getSender()}. + * Does not apply red styling to the message as vanilla does to allow for custom failure message styling. + * + *

Respects vanilla semantics for accepting failure output and suppressed output environments.

+ * + *

See MiniMessage docs and + * MiniMessage Placeholders docs + * for more information on the format.

+ * + * @param message the MiniMessage message to send + * @param resolvers resolvers to use + */ + default void sendRichFailure(String message, TagResolver... resolvers) { + sendFailure(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers)); + } } From e98d48c5c480ace1822acde4b94255b5dc13a5bb Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Fri, 2 Oct 2026 11:44:46 +0200 Subject: [PATCH 11/20] Update testplugin to use some of the new methods --- .../testplugin/brigtests/Registration.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test-plugin/src/main/java/io/papermc/testplugin/brigtests/Registration.java b/test-plugin/src/main/java/io/papermc/testplugin/brigtests/Registration.java index 7d8b92200048..ce93c61e68f3 100644 --- a/test-plugin/src/main/java/io/papermc/testplugin/brigtests/Registration.java +++ b/test-plugin/src/main/java/io/papermc/testplugin/brigtests/Registration.java @@ -49,7 +49,7 @@ private static void registerViaLifecycleEvents(final JavaPlugin plugin) { .then( Commands.argument("name", ArgumentTypes.resource(RegistryKey.ENCHANTMENT)) .executes(ctx -> { - ctx.getSource().sendSuccess(Component.text(ctx.getArgument("name", Enchantment.class).toString()), false); + ctx.getSource().sendSuccess(Component.translatable(ctx.getArgument("name", Enchantment.class)), false); return Command.SINGLE_SUCCESS; }) ).build() @@ -69,7 +69,7 @@ private static void registerViaLifecycleEvents(final JavaPlugin plugin) { Commands.argument("pos", ArgumentTypes.finePosition(false)) .executes(ctx -> { final FinePositionResolver position = ctx.getArgument("pos", FinePositionResolver.class); - ctx.getSource().sendSuccess(Component.text("Position: " + position.resolve(ctx.getSource())), false); + ctx.getSource().sendRichSuccess("Position: " + position.resolve(ctx.getSource()), false); return Command.SINGLE_SUCCESS; }) ).build() @@ -77,7 +77,7 @@ private static void registerViaLifecycleEvents(final JavaPlugin plugin) { // ensure plugin commands override commands.register(Commands.literal("tag") .executes(ctx -> { - ctx.getSource().sendSuccess(Component.text("overriden command"), false); + ctx.getSource().sendRichSuccess("overriden command", false); return Command.SINGLE_SUCCESS; }) .build(), @@ -92,7 +92,7 @@ private static void registerViaLifecycleEvents(final JavaPlugin plugin) { .then(Commands.literal("sub_command") .requires(source -> source.getSender().hasPermission("testplugin.test")) .executes(ctx -> { - ctx.getSource().sendSuccess(Component.text("root_command sub_command"), false); + ctx.getSource().sendRichSuccess("root_command sub_command", false); return Command.SINGLE_SUCCESS; })).build(), null, @@ -130,7 +130,7 @@ public void execute(@NotNull final CommandSourceStack commandSourceStack, final return true; }) .executes(ctx -> { - ctx.getSource().getExecutor().sendMessage("You are in lava!"); + ctx.getSource().sendRichReply("You are in lava!"); return Command.SINGLE_SUCCESS; })).build(), null, @@ -169,14 +169,14 @@ public static void registerViaBootstrap(final BootstrapContext context) { .then(Commands.literal("item") .then(Commands.argument("mat", MaterialArgumentType.item()) .executes(ctx -> { - ctx.getSource().sendSuccess(Component.text(ctx.getArgument("mat", Material.class).name()), false); + ctx.getSource().sendSuccess(Component.translatable(ctx.getArgument("mat", Material.class)), false); return Command.SINGLE_SUCCESS; }) ) ).then(Commands.literal("block") .then(Commands.argument("mat", MaterialArgumentType.block()) .executes(ctx -> { - ctx.getSource().sendSuccess(Component.text(ctx.getArgument("mat", Material.class).name()), false); + ctx.getSource().sendSuccess(Component.translatable(ctx.getArgument("mat", Material.class)), false); return Command.SINGLE_SUCCESS; }) ) @@ -190,8 +190,8 @@ public static void registerViaBootstrap(final BootstrapContext context) { .then(Commands.argument("allow_inform_admins", BoolArgumentType.bool()) .then(Commands.argument("msg", StringArgumentType.greedyString()) .executes(ctx -> { - ctx.getSource().sendSuccess( - MiniMessage.miniMessage().deserialize(StringArgumentType.getString(ctx, "msg")), + ctx.getSource().sendRichSuccess( + StringArgumentType.getString(ctx, "msg"), BoolArgumentType.getBool(ctx, "allow_inform_admins") ); return Command.SINGLE_SUCCESS; From eb68e6c6ab658a1c6f3583d9893bfa6e38431e5e Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Sat, 3 Oct 2026 21:56:26 +0200 Subject: [PATCH 12/20] Update docs links --- .../command/brigadier/CommandSourceStack.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 6fe85c28ede8..e1e62eaab42d 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -98,8 +98,8 @@ public interface CommandSourceStack { * Sends a system message with the MiniMessage format to the {@link #getExecutor()} * if it is a {@link Player}, otherwise sends it to the {@link #getSender()}. * - *

See MiniMessage docs and - * MiniMessage Placeholders docs + *

See MiniMessage docs and + * MiniMessage Placeholders docs * for more information on the format.

* * @param message the MiniMessage message to send @@ -142,8 +142,8 @@ default void sendSuccess(ComponentLike message) { *

This currently includes checking for environments with suppressed output, * {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.

* - *

See MiniMessage docs and - * MiniMessage Placeholders docs + *

See MiniMessage docs and + * MiniMessage Placeholders docs * for more information on the format.

* * @param message the MiniMessage message to send @@ -162,8 +162,8 @@ default void sendRichSuccess(String message, boolean allowInformingAdmins, TagRe *

This currently includes checking for environments with suppressed output, * {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.

* - *

See MiniMessage docs and - * MiniMessage Placeholders docs + *

See MiniMessage docs and + * MiniMessage Placeholders docs * for more information on the format.

* * @param message the MiniMessage message to send @@ -190,8 +190,8 @@ default void sendRichSuccess(String message, TagResolver... resolvers) { * *

Respects vanilla semantics for accepting failure output and suppressed output environments.

* - *

See MiniMessage docs and - * MiniMessage Placeholders docs + *

See MiniMessage docs and + * MiniMessage Placeholders docs * for more information on the format.

* * @param message the MiniMessage message to send From 64891cbd4eb0f982c2aba18434639a9dbdd234a4 Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Sat, 3 Oct 2026 21:59:26 +0200 Subject: [PATCH 13/20] Add missing 'this' and replace checkNotNull with checkArgument --- .../paper/command/brigadier/CommandSourceStack.java | 10 +++++----- .../command/brigadier/PaperCommandSourceStack.java | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index e1e62eaab42d..d70a042d2e1d 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -106,7 +106,7 @@ public interface CommandSourceStack { * @param resolvers resolvers to use */ default void sendRichReply(String message, TagResolver... resolvers) { - sendReply(MiniMessage.miniMessage().deserialize(message, resolvers)); + this.sendReply(MiniMessage.miniMessage().deserialize(message, resolvers)); } /** @@ -132,7 +132,7 @@ default void sendRichReply(String message, TagResolver... resolvers) { * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed */ default void sendSuccess(ComponentLike message) { - sendSuccess(message, true); + this.sendSuccess(message, true); } /** @@ -151,7 +151,7 @@ default void sendSuccess(ComponentLike message) { * @param resolvers resolvers to use */ default void sendRichSuccess(String message, boolean allowInformingAdmins, TagResolver... resolvers) { - sendSuccess(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers), allowInformingAdmins); + this.sendSuccess(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers), allowInformingAdmins); } /** @@ -171,7 +171,7 @@ default void sendRichSuccess(String message, boolean allowInformingAdmins, TagRe * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed */ default void sendRichSuccess(String message, TagResolver... resolvers) { - sendRichSuccess(message, true, resolvers); + this.sendRichSuccess(message, true, resolvers); } /** @@ -198,6 +198,6 @@ default void sendRichSuccess(String message, TagResolver... resolvers) { * @param resolvers resolvers to use */ default void sendRichFailure(String message, TagResolver... resolvers) { - sendFailure(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers)); + this.sendFailure(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers)); } } diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java index 7f225a39e640..8f311a8081fa 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommandSourceStack.java @@ -53,19 +53,19 @@ default CommandSourceStack withExecutor(Entity executor) { @Override default void sendReply(final ComponentLike message) { - Preconditions.checkNotNull(message, "message cannot be null."); + Preconditions.checkArgument(message != null, "message cannot be null."); this.getHandle().sendSystemMessage(PaperAdventure.asVanilla(message.asComponent())); } @Override default void sendSuccess(final ComponentLike message, final boolean allowInformingAdmins) { - Preconditions.checkNotNull(message, "message cannot be null."); + Preconditions.checkArgument(message != null, "message cannot be null."); this.getHandle().sendSuccess(() -> PaperAdventure.asVanilla(message.asComponent()), allowInformingAdmins); } @Override default void sendFailure(final ComponentLike message) { - Preconditions.checkNotNull(message, "message cannot be null."); + Preconditions.checkArgument(message != null, "message cannot be null."); this.getHandle().sendFailure(PaperAdventure.asVanilla(message.asComponent()), false); } From 238c37002448f0361db02f875e57ff40b579a139 Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Sat, 3 Oct 2026 22:03:31 +0200 Subject: [PATCH 14/20] Add explicit argument checks and mention exception in Javadoc --- .../paper/command/brigadier/CommandSourceStack.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index d70a042d2e1d..6eadf900b960 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -1,5 +1,6 @@ package io.papermc.paper.command.brigadier; +import com.google.common.base.Preconditions; import com.mojang.brigadier.RedirectModifier; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.CommandNode; @@ -91,6 +92,7 @@ public interface CommandSourceStack { * otherwise sends a system message to the {@link #getSender()}. * * @param message the message to send + * @throws IllegalArgumentException if the message is null */ void sendReply(ComponentLike message); @@ -104,8 +106,10 @@ public interface CommandSourceStack { * * @param message the MiniMessage message to send * @param resolvers resolvers to use + * @throws IllegalArgumentException if the message is null */ default void sendRichReply(String message, TagResolver... resolvers) { + Preconditions.checkArgument(message != null, "message cannot be null."); this.sendReply(MiniMessage.miniMessage().deserialize(message, resolvers)); } @@ -118,6 +122,7 @@ default void sendRichReply(String message, TagResolver... resolvers) { * * @param message the message to send * @param allowInformingAdmins whether admins and console may be informed of this success + * @throws IllegalArgumentException if the message is null */ void sendSuccess(ComponentLike message, boolean allowInformingAdmins); @@ -130,6 +135,7 @@ default void sendRichReply(String message, TagResolver... resolvers) { * * @param message the message to send * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed + * @throws IllegalArgumentException if the message is null */ default void sendSuccess(ComponentLike message) { this.sendSuccess(message, true); @@ -149,8 +155,10 @@ default void sendSuccess(ComponentLike message) { * @param message the MiniMessage message to send * @param allowInformingAdmins whether admins and console may be informed of this success * @param resolvers resolvers to use + * @throws IllegalArgumentException if the message is null */ default void sendRichSuccess(String message, boolean allowInformingAdmins, TagResolver... resolvers) { + Preconditions.checkArgument(message != null, "message cannot be null."); this.sendSuccess(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers), allowInformingAdmins); } @@ -169,6 +177,7 @@ default void sendRichSuccess(String message, boolean allowInformingAdmins, TagRe * @param message the MiniMessage message to send * @param resolvers resolvers to use * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed + * @throws IllegalArgumentException if the message is null */ default void sendRichSuccess(String message, TagResolver... resolvers) { this.sendRichSuccess(message, true, resolvers); @@ -181,6 +190,7 @@ default void sendRichSuccess(String message, TagResolver... resolvers) { *

Respects vanilla semantics for accepting failure output and suppressed output environments.

* * @param message the message to send + * @throws IllegalArgumentException if the message is null */ void sendFailure(ComponentLike message); @@ -196,8 +206,10 @@ default void sendRichSuccess(String message, TagResolver... resolvers) { * * @param message the MiniMessage message to send * @param resolvers resolvers to use + * @throws IllegalArgumentException if the message is null */ default void sendRichFailure(String message, TagResolver... resolvers) { + Preconditions.checkArgument(message != null, "message cannot be null."); this.sendFailure(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers)); } } From 3e153388c987aa4154ec42b9083223cace4a074c Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Tue, 6 Oct 2026 00:23:00 +0200 Subject: [PATCH 15/20] Include pointered target in sendRichReply --- .../papermc/paper/command/brigadier/CommandSourceStack.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 6eadf900b960..8878a6916845 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -110,7 +110,11 @@ public interface CommandSourceStack { */ default void sendRichReply(String message, TagResolver... resolvers) { Preconditions.checkArgument(message != null, "message cannot be null."); - this.sendReply(MiniMessage.miniMessage().deserialize(message, resolvers)); + this.sendReply(MiniMessage.miniMessage().deserialize( + message, + getExecutor() instanceof Player player ? player : getSender(), + resolvers + )); } /** From 2880b2abfbde0925617edd639586fc7454a3cae3 Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Tue, 6 Oct 2026 00:27:22 +0200 Subject: [PATCH 16/20] Document pointered pass behavior --- .../paper/command/brigadier/CommandSourceStack.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 8878a6916845..6b603e92c70a 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -4,6 +4,7 @@ import com.mojang.brigadier.RedirectModifier; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.CommandNode; +import net.kyori.adventure.pointer.Pointered; import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; @@ -104,6 +105,9 @@ public interface CommandSourceStack { * MiniMessage Placeholders docs * for more information on the format.

* + *

This method provides the target of the system message as a {@link net.kyori.adventure.pointer.Pointered} + * to the MiniMessage {@link MiniMessage#deserialize(String, Pointered, TagResolver...)} method.

+ * * @param message the MiniMessage message to send * @param resolvers resolvers to use * @throws IllegalArgumentException if the message is null @@ -156,6 +160,9 @@ default void sendSuccess(ComponentLike message) { * MiniMessage Placeholders docs * for more information on the format.

* + *

This method provides the {@link CommandSender} of this command as a {@link net.kyori.adventure.pointer.Pointered} + * to the MiniMessage {@link MiniMessage#deserialize(String, Pointered, TagResolver...)} method.

+ * * @param message the MiniMessage message to send * @param allowInformingAdmins whether admins and console may be informed of this success * @param resolvers resolvers to use @@ -178,6 +185,9 @@ default void sendRichSuccess(String message, boolean allowInformingAdmins, TagRe * MiniMessage Placeholders docs * for more information on the format.

* + *

This method provides the {@link CommandSender} of this command as a {@link net.kyori.adventure.pointer.Pointered} + * to the MiniMessage {@link MiniMessage#deserialize(String, Pointered, TagResolver...)} method.

+ * * @param message the MiniMessage message to send * @param resolvers resolvers to use * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed @@ -208,6 +218,9 @@ default void sendRichSuccess(String message, TagResolver... resolvers) { * MiniMessage Placeholders docs * for more information on the format.

* + *

This method provides the {@link CommandSender} of this command as a {@link net.kyori.adventure.pointer.Pointered} + * to the MiniMessage {@link MiniMessage#deserialize(String, Pointered, TagResolver...)} method.

+ * * @param message the MiniMessage message to send * @param resolvers resolvers to use * @throws IllegalArgumentException if the message is null From 9294d7c7c17185ce135ab337beee9ad4dcaeaa20 Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Tue, 6 Oct 2026 00:46:20 +0200 Subject: [PATCH 17/20] I keep forgetting these Co-authored-by: Pedro <3602279+Doc94@users.noreply.github.com> --- .../io/papermc/paper/command/brigadier/CommandSourceStack.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index 6b603e92c70a..b3d9346ad0fb 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -116,7 +116,7 @@ default void sendRichReply(String message, TagResolver... resolvers) { Preconditions.checkArgument(message != null, "message cannot be null."); this.sendReply(MiniMessage.miniMessage().deserialize( message, - getExecutor() instanceof Player player ? player : getSender(), + this.getExecutor() instanceof Player player ? player : this.getSender(), resolvers )); } From ebce9586325696dcb968d3a330e0125f1db401e7 Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Tue, 6 Oct 2026 13:56:12 +0200 Subject: [PATCH 18/20] I forgot more of 'em --- .../papermc/paper/command/brigadier/CommandSourceStack.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index b3d9346ad0fb..eb6dbe8a8576 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -170,7 +170,7 @@ default void sendSuccess(ComponentLike message) { */ default void sendRichSuccess(String message, boolean allowInformingAdmins, TagResolver... resolvers) { Preconditions.checkArgument(message != null, "message cannot be null."); - this.sendSuccess(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers), allowInformingAdmins); + this.sendSuccess(MiniMessage.miniMessage().deserialize(message, this.getSender(), resolvers), allowInformingAdmins); } /** @@ -227,6 +227,6 @@ default void sendRichSuccess(String message, TagResolver... resolvers) { */ default void sendRichFailure(String message, TagResolver... resolvers) { Preconditions.checkArgument(message != null, "message cannot be null."); - this.sendFailure(MiniMessage.miniMessage().deserialize(message, getSender(), resolvers)); + this.sendFailure(MiniMessage.miniMessage().deserialize(message, this.getSender(), resolvers)); } } From 73822d7203778b8fc3aecd8520c143b5f9702c36 Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Sun, 11 Oct 2026 16:49:56 +0200 Subject: [PATCH 19/20] Remove unnecessary overload --- .../command/brigadier/CommandSourceStack.java | 27 ++----------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index eb6dbe8a8576..da27f60e4ebc 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -149,30 +149,6 @@ default void sendSuccess(ComponentLike message) { this.sendSuccess(message, true); } - /** - * Sends a system message with the MiniMessage format to the {@link #getSender()}, admins, and console indicating - * successful command execution according to vanilla semantics. - * - *

This currently includes checking for environments with suppressed output, - * {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.

- * - *

See MiniMessage docs and - * MiniMessage Placeholders docs - * for more information on the format.

- * - *

This method provides the {@link CommandSender} of this command as a {@link net.kyori.adventure.pointer.Pointered} - * to the MiniMessage {@link MiniMessage#deserialize(String, Pointered, TagResolver...)} method.

- * - * @param message the MiniMessage message to send - * @param allowInformingAdmins whether admins and console may be informed of this success - * @param resolvers resolvers to use - * @throws IllegalArgumentException if the message is null - */ - default void sendRichSuccess(String message, boolean allowInformingAdmins, TagResolver... resolvers) { - Preconditions.checkArgument(message != null, "message cannot be null."); - this.sendSuccess(MiniMessage.miniMessage().deserialize(message, this.getSender(), resolvers), allowInformingAdmins); - } - /** * Sends a system message with the MiniMessage format to the {@link #getSender()}, admins, and console indicating * successful command execution according to vanilla semantics. This method informs admins and the console of @@ -194,7 +170,8 @@ default void sendRichSuccess(String message, boolean allowInformingAdmins, TagRe * @throws IllegalArgumentException if the message is null */ default void sendRichSuccess(String message, TagResolver... resolvers) { - this.sendRichSuccess(message, true, resolvers); + Preconditions.checkArgument(message != null, "message cannot be null."); + this.sendSuccess(MiniMessage.miniMessage().deserialize(message, this.getSender(), resolvers), true); } /** From 07b54458d43c729813f331d1a0fe5f4853f569d6 Mon Sep 17 00:00:00 2001 From: Strokkur24 Date: Sun, 11 Oct 2026 16:51:03 +0200 Subject: [PATCH 20/20] Make final --- .../paper/command/brigadier/CommandSourceStack.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java index da27f60e4ebc..da840ef3e570 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java @@ -112,11 +112,11 @@ public interface CommandSourceStack { * @param resolvers resolvers to use * @throws IllegalArgumentException if the message is null */ - default void sendRichReply(String message, TagResolver... resolvers) { + default void sendRichReply(final String message, final TagResolver... resolvers) { Preconditions.checkArgument(message != null, "message cannot be null."); this.sendReply(MiniMessage.miniMessage().deserialize( message, - this.getExecutor() instanceof Player player ? player : this.getSender(), + this.getExecutor() instanceof final Player player ? player : this.getSender(), resolvers )); } @@ -145,7 +145,7 @@ default void sendRichReply(String message, TagResolver... resolvers) { * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed * @throws IllegalArgumentException if the message is null */ - default void sendSuccess(ComponentLike message) { + default void sendSuccess(final ComponentLike message) { this.sendSuccess(message, true); } @@ -169,7 +169,7 @@ default void sendSuccess(ComponentLike message) { * @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed * @throws IllegalArgumentException if the message is null */ - default void sendRichSuccess(String message, TagResolver... resolvers) { + default void sendRichSuccess(final String message, final TagResolver... resolvers) { Preconditions.checkArgument(message != null, "message cannot be null."); this.sendSuccess(MiniMessage.miniMessage().deserialize(message, this.getSender(), resolvers), true); } @@ -202,7 +202,7 @@ default void sendRichSuccess(String message, TagResolver... resolvers) { * @param resolvers resolvers to use * @throws IllegalArgumentException if the message is null */ - default void sendRichFailure(String message, TagResolver... resolvers) { + default void sendRichFailure(final String message, final TagResolver... resolvers) { Preconditions.checkArgument(message != null, "message cannot be null."); this.sendFailure(MiniMessage.miniMessage().deserialize(message, this.getSender(), resolvers)); }