diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java index 7e1d500b18..3d7429d7e5 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java @@ -15,5 +15,9 @@ public enum CommandRegistrationFlag { * @deprecated This is the default behavior now. */ @Deprecated(since = "1.21.4") - FLATTEN_ALIASES + FLATTEN_ALIASES, + /** + * Prevents this command from being sent to the client. + */ + SERVER_ONLY } diff --git a/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch b/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch index f892ceeba5..1254bdfc94 100644 --- a/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch +++ b/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch @@ -13,7 +13,7 @@ + public CommandNode clientNode; // Paper - Brigadier API + public CommandNode unwrappedCached = null; // Paper - Brigadier Command API + public CommandNode wrappedCached = null; // Paper - Brigadier Command API -+ public io.papermc.paper.command.brigadier.PluginCommandMeta pluginCommandMeta; // Paper - Brigadier Command API ++ public io.papermc.paper.command.brigadier.APICommandMeta apiCommandMeta; // Paper - Brigadier Command API + // CraftBukkit start + public void removeCommand(String name) { + this.children.remove(name); diff --git a/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch b/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch index 440074ebea..24a2b69e5a 100644 --- a/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch +++ b/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch @@ -172,7 +172,7 @@ } return null; -@@ -359,26 +_,120 @@ +@@ -359,26 +_,121 @@ } public void sendCommands(ServerPlayer player) { @@ -252,6 +252,7 @@ + } + // Paper end - Brigadier API + if (!org.spigotmc.SpigotConfig.sendNamespaced && commandNode.getName().contains(":")) continue; // Spigot ++ if (commandNode.wrappedCached != null && commandNode.wrappedCached.apiCommandMeta != null && commandNode.wrappedCached.apiCommandMeta.serverSideOnly()) continue; // Paper if (commandNode.canUse(source)) { ArgumentBuilder argumentBuilder = (ArgumentBuilder) commandNode.createBuilder(); + // Paper start diff --git a/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch b/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch index caa71bc362..164b4a4593 100644 --- a/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch @@ -1,12 +1,13 @@ --- a/net/minecraft/server/ReloadableServerResources.java +++ b/net/minecraft/server/ReloadableServerResources.java -@@ -38,7 +_,8 @@ +@@ -38,7 +_,9 @@ this.fullRegistryHolder = new ReloadableServerRegistries.Holder(registryAccess.compositeAccess()); this.postponedTags = postponedTags; this.recipes = new RecipeManager(registries); - this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures)); + this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures), true); // Paper - Brigadier Command API - use modern alias registration + io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setDispatcher(this.commands, CommandBuildContext.simple(registries, enabledFeatures)); // Paper - Brigadier Command API ++ io.papermc.paper.command.PaperCommands.registerCommands(); // Paper this.advancements = new ServerAdvancementManager(registries); this.functionLibrary = new ServerFunctionLibrary(functionCompilationLevel, this.commands.getDispatcher()); } diff --git a/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java b/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java index 7b58b2d629..6ca8b5fcaa 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java +++ b/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java @@ -1,10 +1,15 @@ package io.papermc.paper.command; +import com.mojang.brigadier.tree.LiteralCommandNode; +import io.papermc.paper.command.brigadier.CommandRegistrationFlag; +import io.papermc.paper.command.brigadier.CommandSourceStack; import net.minecraft.server.MinecraftServer; import org.bukkit.command.Command; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.framework.qual.DefaultQualifier; @@ -15,16 +20,31 @@ public final class PaperCommands { } private static final Map COMMANDS = new HashMap<>(); - static { + + public static void registerCommands(final MinecraftServer server) { COMMANDS.put("paper", new PaperCommand("paper")); COMMANDS.put("callback", new CallbackCommand("callback")); COMMANDS.put("mspt", new MSPTCommand("mspt")); - } - public static void registerCommands(final MinecraftServer server) { COMMANDS.forEach((s, command) -> { server.server.getCommandMap().register(s, "Paper", command); }); server.server.getCommandMap().register("bukkit", new PaperPluginsCommand()); } + + public static void registerCommands() { + // Paper commands go here + } + + private static void registerInternalCommand(final LiteralCommandNode node, final String description, final List aliases, final Set flags) { + io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.registerWithFlagsInternal( + null, + "paper", + "Paper", + node, + description, + aliases, + flags + ); + } } diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/APICommandMeta.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/APICommandMeta.java new file mode 100644 index 0000000000..90a604cfc2 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/APICommandMeta.java @@ -0,0 +1,31 @@ +package io.papermc.paper.command.brigadier; + +import io.papermc.paper.plugin.configuration.PluginMeta; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +@NullMarked +public record APICommandMeta(@Nullable PluginMeta pluginMeta, @Nullable String description, List aliases, @Nullable String helpCommandNamespace, boolean serverSideOnly) { + + public APICommandMeta(final @Nullable PluginMeta pluginMeta, final @Nullable String description) { + this(pluginMeta, description, Collections.emptyList(), null, false); + } + + public APICommandMeta { + aliases = List.copyOf(aliases); + } + + @Nullable + public Plugin plugin() { + return this.pluginMeta == null ? null : Objects.requireNonNull(Bukkit.getPluginManager().getPlugin(this.pluginMeta.getName())); + } + + public APICommandMeta withAliases(List registeredAliases) { + return new APICommandMeta(this.pluginMeta, this.description, List.copyOf(registeredAliases), this.helpCommandNamespace, this.serverSideOnly); + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java index 944cd83288..2d1de331ae 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java @@ -35,8 +35,8 @@ public final class PaperBrigadier { throw new IllegalArgumentException("Unsure how to wrap a " + node); } - final PluginCommandMeta meta; - if ((meta = node.pluginCommandMeta) == null) { + final APICommandMeta meta; + if ((meta = node.apiCommandMeta) == null) { return new VanillaCommandWrapper(node); } CommandNode argumentCommandNode = node; @@ -46,6 +46,12 @@ public final class PaperBrigadier { Map, String> map = PaperCommands.INSTANCE.getDispatcherInternal().getSmartUsage(argumentCommandNode, DUMMY); String usage = map.isEmpty() ? node.getUsageText() : node.getUsageText() + " " + String.join("\n" + node.getUsageText() + " ", map.values()); + + // Internal command + if (meta.pluginMeta() == null) { + return new VanillaCommandWrapper(node.getName(), meta.description(), usage, meta.aliases(), node, meta.helpCommandNamespace()); + } + return new PluginVanillaCommandWrapper(node.getName(), meta.description(), usage, meta.aliases(), node, meta.plugin()); } diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java index 4b6d845423..84fab94f38 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java @@ -91,10 +91,13 @@ public class PaperCommands implements Commands, PaperRegistrar registerWithFlags(final PluginMeta pluginMeta, final LiteralCommandNode node, final @Nullable String description, final Collection aliases, final Set flags) { - final PluginCommandMeta meta = new PluginCommandMeta(pluginMeta, description); - final String identifier = pluginMeta.getName().toLowerCase(Locale.ROOT); + return registerWithFlagsInternal(pluginMeta, pluginMeta.getName().toLowerCase(Locale.ROOT), null, node, description, aliases, flags); + } + + public @Unmodifiable Set registerWithFlagsInternal(final @Nullable PluginMeta pluginMeta, final String namespace, final @Nullable String helpNamespaceOverride, final LiteralCommandNode node, final @Nullable String description, final Collection aliases, final Set flags) { + final APICommandMeta meta = new APICommandMeta(pluginMeta, description, List.of(), helpNamespaceOverride, flags.contains(CommandRegistrationFlag.SERVER_ONLY)); final String literal = node.getLiteral(); - final LiteralCommandNode pluginLiteral = PaperBrigadier.copyLiteral(identifier + ":" + literal, node); + final LiteralCommandNode pluginLiteral = PaperBrigadier.copyLiteral(namespace + ":" + literal, node); final Set registeredLabels = new HashSet<>(aliases.size() * 2 + 2); @@ -111,27 +114,27 @@ public class PaperCommands implements Commands, PaperRegistrar redirectTo, final PluginCommandMeta meta) { + private boolean registerCopy(final String aliasLiteral, final LiteralCommandNode redirectTo, final APICommandMeta meta) { final LiteralCommandNode node = PaperBrigadier.copyLiteral(aliasLiteral, redirectTo); - node.pluginCommandMeta = meta; + node.apiCommandMeta = meta; return this.registerIntoDispatcher(node, false); } private boolean registerIntoDispatcher(final LiteralCommandNode node, boolean override) { final CommandNode existingChild = this.getDispatcher().getRoot().getChild(node.getLiteral()); - if (existingChild != null && existingChild.pluginCommandMeta == null && !(existingChild instanceof BukkitCommandNode)) { + if (existingChild != null && existingChild.apiCommandMeta == null && !(existingChild instanceof BukkitCommandNode)) { override = true; // override vanilla commands } if (existingChild == null || override) { // Avoid merging behavior. Maybe something to look into in the future diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginCommandMeta.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginCommandMeta.java deleted file mode 100644 index 45701bcca0..0000000000 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginCommandMeta.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.papermc.paper.command.brigadier; - -import io.papermc.paper.plugin.configuration.PluginMeta; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; -import org.jspecify.annotations.NullMarked; -import org.jspecify.annotations.Nullable; - -@NullMarked -public record PluginCommandMeta(PluginMeta pluginMeta, @Nullable String description, List aliases) { - - public PluginCommandMeta(final PluginMeta pluginMeta, final @Nullable String description) { - this(pluginMeta, description, Collections.emptyList()); - } - - public PluginCommandMeta { - aliases = List.copyOf(aliases); - } - - public Plugin plugin() { - return Objects.requireNonNull(Bukkit.getPluginManager().getPlugin(this.pluginMeta.getName())); - } -} diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginVanillaCommandWrapper.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginVanillaCommandWrapper.java index a0e2ac509f..a9b6d2781f 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginVanillaCommandWrapper.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginVanillaCommandWrapper.java @@ -17,7 +17,7 @@ public class PluginVanillaCommandWrapper extends VanillaCommandWrapper implement private final List aliases; public PluginVanillaCommandWrapper(String name, String description, String usageMessage, List aliases, CommandNode vanillaCommand, Plugin plugin) { - super(name, description, usageMessage, aliases, vanillaCommand); + super(name, description, usageMessage, aliases, vanillaCommand, null); this.plugin = plugin; this.aliases = aliases; } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java index f492098acc..7876e09b91 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java @@ -26,10 +26,12 @@ import org.bukkit.entity.minecart.CommandMinecart; public class VanillaCommandWrapper extends BukkitCommand { // Paper public final CommandNode vanillaCommand; + public final String helpCommandNamespace; - public VanillaCommandWrapper(String name, String description, String usageMessage, List aliases, CommandNode vanillaCommand) { + public VanillaCommandWrapper(String name, String description, String usageMessage, List aliases, CommandNode vanillaCommand, String helpCommandNamespace) { super(name, description, usageMessage, aliases); this.vanillaCommand = vanillaCommand; + this.helpCommandNamespace = helpCommandNamespace; } Commands commands() { @@ -40,6 +42,7 @@ public class VanillaCommandWrapper extends BukkitCommand { // Paper super(vanillaCommand.getName(), "A Mojang provided command.", vanillaCommand.getUsageText(), Collections.emptyList()); this.vanillaCommand = vanillaCommand; this.setPermission(VanillaCommandWrapper.getPermission(vanillaCommand)); + this.helpCommandNamespace = "Minecraft"; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/help/SimpleHelpMap.java b/paper-server/src/main/java/org/bukkit/craftbukkit/help/SimpleHelpMap.java index bd5b968e87..70b45a7d41 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/help/SimpleHelpMap.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/help/SimpleHelpMap.java @@ -199,18 +199,15 @@ public class SimpleHelpMap implements HelpMap { } private String getCommandPluginName(Command command) { - // Paper start - Move up if (command instanceof PluginIdentifiableCommand) { return ((PluginIdentifiableCommand) command).getPlugin().getName(); } - // Paper end - if (command instanceof VanillaCommandWrapper) { - return "Minecraft"; + if (command instanceof VanillaCommandWrapper wrapper) { + return wrapper.helpCommandNamespace; } if (command instanceof BukkitCommand) { return "Bukkit"; } - // Paper - Move PluginIdentifiableCommand instanceof check to allow brig commands return null; }