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));
}