mirror of
https://github.com/PaperMC/Paper.git
synced 2025-08-05 22:52:13 -07:00
Supports the ability for commands to be registered internally (#12520)
This commit is contained in:
@@ -15,5 +15,9 @@ public enum CommandRegistrationFlag {
|
|||||||
* @deprecated This is the default behavior now.
|
* @deprecated This is the default behavior now.
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "1.21.4")
|
@Deprecated(since = "1.21.4")
|
||||||
FLATTEN_ALIASES
|
FLATTEN_ALIASES,
|
||||||
|
/**
|
||||||
|
* Prevents this command from being sent to the client.
|
||||||
|
*/
|
||||||
|
SERVER_ONLY
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
+ public CommandNode<net.minecraft.commands.CommandSourceStack> clientNode; // Paper - Brigadier API
|
+ public CommandNode<net.minecraft.commands.CommandSourceStack> clientNode; // Paper - Brigadier API
|
||||||
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> unwrappedCached = null; // Paper - Brigadier Command API
|
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> unwrappedCached = null; // Paper - Brigadier Command API
|
||||||
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> wrappedCached = null; // Paper - Brigadier Command API
|
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> 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
|
+ // CraftBukkit start
|
||||||
+ public void removeCommand(String name) {
|
+ public void removeCommand(String name) {
|
||||||
+ this.children.remove(name);
|
+ this.children.remove(name);
|
||||||
|
@@ -172,7 +172,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -359,26 +_,120 @@
|
@@ -359,26 +_,121 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendCommands(ServerPlayer player) {
|
public void sendCommands(ServerPlayer player) {
|
||||||
@@ -252,6 +252,7 @@
|
|||||||
+ }
|
+ }
|
||||||
+ // Paper end - Brigadier API
|
+ // Paper end - Brigadier API
|
||||||
+ if (!org.spigotmc.SpigotConfig.sendNamespaced && commandNode.getName().contains(":")) continue; // Spigot
|
+ 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)) {
|
if (commandNode.canUse(source)) {
|
||||||
ArgumentBuilder<SharedSuggestionProvider, ?> argumentBuilder = (ArgumentBuilder) commandNode.createBuilder();
|
ArgumentBuilder<SharedSuggestionProvider, ?> argumentBuilder = (ArgumentBuilder) commandNode.createBuilder();
|
||||||
+ // Paper start
|
+ // Paper start
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
--- a/net/minecraft/server/ReloadableServerResources.java
|
--- a/net/minecraft/server/ReloadableServerResources.java
|
||||||
+++ b/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.fullRegistryHolder = new ReloadableServerRegistries.Holder(registryAccess.compositeAccess());
|
||||||
this.postponedTags = postponedTags;
|
this.postponedTags = postponedTags;
|
||||||
this.recipes = new RecipeManager(registries);
|
this.recipes = new RecipeManager(registries);
|
||||||
- this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures));
|
- 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
|
+ 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.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.advancements = new ServerAdvancementManager(registries);
|
||||||
this.functionLibrary = new ServerFunctionLibrary(functionCompilationLevel, this.commands.getDispatcher());
|
this.functionLibrary = new ServerFunctionLibrary(functionCompilationLevel, this.commands.getDispatcher());
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,15 @@
|
|||||||
package io.papermc.paper.command;
|
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 net.minecraft.server.MinecraftServer;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
|
||||||
@@ -15,16 +20,31 @@ public final class PaperCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<String, Command> COMMANDS = new HashMap<>();
|
private static final Map<String, Command> COMMANDS = new HashMap<>();
|
||||||
static {
|
|
||||||
|
public static void registerCommands(final MinecraftServer server) {
|
||||||
COMMANDS.put("paper", new PaperCommand("paper"));
|
COMMANDS.put("paper", new PaperCommand("paper"));
|
||||||
COMMANDS.put("callback", new CallbackCommand("callback"));
|
COMMANDS.put("callback", new CallbackCommand("callback"));
|
||||||
COMMANDS.put("mspt", new MSPTCommand("mspt"));
|
COMMANDS.put("mspt", new MSPTCommand("mspt"));
|
||||||
}
|
|
||||||
|
|
||||||
public static void registerCommands(final MinecraftServer server) {
|
|
||||||
COMMANDS.forEach((s, command) -> {
|
COMMANDS.forEach((s, command) -> {
|
||||||
server.server.getCommandMap().register(s, "Paper", command);
|
server.server.getCommandMap().register(s, "Paper", command);
|
||||||
});
|
});
|
||||||
server.server.getCommandMap().register("bukkit", new PaperPluginsCommand());
|
server.server.getCommandMap().register("bukkit", new PaperPluginsCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void registerCommands() {
|
||||||
|
// Paper commands go here
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void registerInternalCommand(final LiteralCommandNode<CommandSourceStack> node, final String description, final List<String> aliases, final Set<CommandRegistrationFlag> flags) {
|
||||||
|
io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.registerWithFlagsInternal(
|
||||||
|
null,
|
||||||
|
"paper",
|
||||||
|
"Paper",
|
||||||
|
node,
|
||||||
|
description,
|
||||||
|
aliases,
|
||||||
|
flags
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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<String> 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<String> registeredAliases) {
|
||||||
|
return new APICommandMeta(this.pluginMeta, this.description, List.copyOf(registeredAliases), this.helpCommandNamespace, this.serverSideOnly);
|
||||||
|
}
|
||||||
|
}
|
@@ -35,8 +35,8 @@ public final class PaperBrigadier {
|
|||||||
throw new IllegalArgumentException("Unsure how to wrap a " + node);
|
throw new IllegalArgumentException("Unsure how to wrap a " + node);
|
||||||
}
|
}
|
||||||
|
|
||||||
final PluginCommandMeta meta;
|
final APICommandMeta meta;
|
||||||
if ((meta = node.pluginCommandMeta) == null) {
|
if ((meta = node.apiCommandMeta) == null) {
|
||||||
return new VanillaCommandWrapper(node);
|
return new VanillaCommandWrapper(node);
|
||||||
}
|
}
|
||||||
CommandNode<CommandSourceStack> argumentCommandNode = node;
|
CommandNode<CommandSourceStack> argumentCommandNode = node;
|
||||||
@@ -46,6 +46,12 @@ public final class PaperBrigadier {
|
|||||||
|
|
||||||
Map<CommandNode<CommandSourceStack>, String> map = PaperCommands.INSTANCE.getDispatcherInternal().getSmartUsage(argumentCommandNode, DUMMY);
|
Map<CommandNode<CommandSourceStack>, String> map = PaperCommands.INSTANCE.getDispatcherInternal().getSmartUsage(argumentCommandNode, DUMMY);
|
||||||
String usage = map.isEmpty() ? node.getUsageText() : node.getUsageText() + " " + String.join("\n" + node.getUsageText() + " ", map.values());
|
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());
|
return new PluginVanillaCommandWrapper(node.getName(), meta.description(), usage, meta.aliases(), node, meta.plugin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -91,10 +91,13 @@ public class PaperCommands implements Commands, PaperRegistrar<LifecycleEventOwn
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Unmodifiable Set<String> registerWithFlags(final PluginMeta pluginMeta, final LiteralCommandNode<CommandSourceStack> node, final @Nullable String description, final Collection<String> aliases, final Set<CommandRegistrationFlag> flags) {
|
public @Unmodifiable Set<String> registerWithFlags(final PluginMeta pluginMeta, final LiteralCommandNode<CommandSourceStack> node, final @Nullable String description, final Collection<String> aliases, final Set<CommandRegistrationFlag> flags) {
|
||||||
final PluginCommandMeta meta = new PluginCommandMeta(pluginMeta, description);
|
return registerWithFlagsInternal(pluginMeta, pluginMeta.getName().toLowerCase(Locale.ROOT), null, node, description, aliases, flags);
|
||||||
final String identifier = pluginMeta.getName().toLowerCase(Locale.ROOT);
|
}
|
||||||
|
|
||||||
|
public @Unmodifiable Set<String> registerWithFlagsInternal(final @Nullable PluginMeta pluginMeta, final String namespace, final @Nullable String helpNamespaceOverride, final LiteralCommandNode<CommandSourceStack> node, final @Nullable String description, final Collection<String> aliases, final Set<CommandRegistrationFlag> flags) {
|
||||||
|
final APICommandMeta meta = new APICommandMeta(pluginMeta, description, List.of(), helpNamespaceOverride, flags.contains(CommandRegistrationFlag.SERVER_ONLY));
|
||||||
final String literal = node.getLiteral();
|
final String literal = node.getLiteral();
|
||||||
final LiteralCommandNode<CommandSourceStack> pluginLiteral = PaperBrigadier.copyLiteral(identifier + ":" + literal, node);
|
final LiteralCommandNode<CommandSourceStack> pluginLiteral = PaperBrigadier.copyLiteral(namespace + ":" + literal, node);
|
||||||
|
|
||||||
final Set<String> registeredLabels = new HashSet<>(aliases.size() * 2 + 2);
|
final Set<String> registeredLabels = new HashSet<>(aliases.size() * 2 + 2);
|
||||||
|
|
||||||
@@ -111,27 +114,27 @@ public class PaperCommands implements Commands, PaperRegistrar<LifecycleEventOwn
|
|||||||
if (this.registerCopy(alias, pluginLiteral, meta)) {
|
if (this.registerCopy(alias, pluginLiteral, meta)) {
|
||||||
registeredAliases.add(alias);
|
registeredAliases.add(alias);
|
||||||
}
|
}
|
||||||
if (this.registerCopy(identifier + ":" + alias, pluginLiteral, meta)) {
|
if (this.registerCopy(namespace + ":" + alias, pluginLiteral, meta)) {
|
||||||
registeredAliases.add(identifier + ":" + alias);
|
registeredAliases.add(namespace + ":" + alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginLiteral.pluginCommandMeta = new PluginCommandMeta(pluginMeta, description, registeredAliases);
|
pluginLiteral.apiCommandMeta = meta.withAliases(registeredAliases);
|
||||||
node.pluginCommandMeta = pluginLiteral.pluginCommandMeta;
|
node.apiCommandMeta = pluginLiteral.apiCommandMeta;
|
||||||
|
|
||||||
registeredLabels.addAll(registeredAliases);
|
registeredLabels.addAll(registeredAliases);
|
||||||
return registeredLabels.isEmpty() ? Collections.emptySet() : Collections.unmodifiableSet(registeredLabels);
|
return registeredLabels.isEmpty() ? Collections.emptySet() : Collections.unmodifiableSet(registeredLabels);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean registerCopy(final String aliasLiteral, final LiteralCommandNode<CommandSourceStack> redirectTo, final PluginCommandMeta meta) {
|
private boolean registerCopy(final String aliasLiteral, final LiteralCommandNode<CommandSourceStack> redirectTo, final APICommandMeta meta) {
|
||||||
final LiteralCommandNode<CommandSourceStack> node = PaperBrigadier.copyLiteral(aliasLiteral, redirectTo);
|
final LiteralCommandNode<CommandSourceStack> node = PaperBrigadier.copyLiteral(aliasLiteral, redirectTo);
|
||||||
node.pluginCommandMeta = meta;
|
node.apiCommandMeta = meta;
|
||||||
return this.registerIntoDispatcher(node, false);
|
return this.registerIntoDispatcher(node, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean registerIntoDispatcher(final LiteralCommandNode<CommandSourceStack> node, boolean override) {
|
private boolean registerIntoDispatcher(final LiteralCommandNode<CommandSourceStack> node, boolean override) {
|
||||||
final CommandNode<CommandSourceStack> existingChild = this.getDispatcher().getRoot().getChild(node.getLiteral());
|
final CommandNode<CommandSourceStack> 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
|
override = true; // override vanilla commands
|
||||||
}
|
}
|
||||||
if (existingChild == null || override) { // Avoid merging behavior. Maybe something to look into in the future
|
if (existingChild == null || override) { // Avoid merging behavior. Maybe something to look into in the future
|
||||||
|
@@ -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<String> 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()));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -17,7 +17,7 @@ public class PluginVanillaCommandWrapper extends VanillaCommandWrapper implement
|
|||||||
private final List<String> aliases;
|
private final List<String> aliases;
|
||||||
|
|
||||||
public PluginVanillaCommandWrapper(String name, String description, String usageMessage, List<String> aliases, CommandNode<CommandSourceStack> vanillaCommand, Plugin plugin) {
|
public PluginVanillaCommandWrapper(String name, String description, String usageMessage, List<String> aliases, CommandNode<CommandSourceStack> vanillaCommand, Plugin plugin) {
|
||||||
super(name, description, usageMessage, aliases, vanillaCommand);
|
super(name, description, usageMessage, aliases, vanillaCommand, null);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.aliases = aliases;
|
this.aliases = aliases;
|
||||||
}
|
}
|
||||||
|
@@ -26,10 +26,12 @@ import org.bukkit.entity.minecart.CommandMinecart;
|
|||||||
public class VanillaCommandWrapper extends BukkitCommand { // Paper
|
public class VanillaCommandWrapper extends BukkitCommand { // Paper
|
||||||
|
|
||||||
public final CommandNode<CommandSourceStack> vanillaCommand;
|
public final CommandNode<CommandSourceStack> vanillaCommand;
|
||||||
|
public final String helpCommandNamespace;
|
||||||
|
|
||||||
public VanillaCommandWrapper(String name, String description, String usageMessage, List<String> aliases, CommandNode<CommandSourceStack> vanillaCommand) {
|
public VanillaCommandWrapper(String name, String description, String usageMessage, List<String> aliases, CommandNode<CommandSourceStack> vanillaCommand, String helpCommandNamespace) {
|
||||||
super(name, description, usageMessage, aliases);
|
super(name, description, usageMessage, aliases);
|
||||||
this.vanillaCommand = vanillaCommand;
|
this.vanillaCommand = vanillaCommand;
|
||||||
|
this.helpCommandNamespace = helpCommandNamespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands commands() {
|
Commands commands() {
|
||||||
@@ -40,6 +42,7 @@ public class VanillaCommandWrapper extends BukkitCommand { // Paper
|
|||||||
super(vanillaCommand.getName(), "A Mojang provided command.", vanillaCommand.getUsageText(), Collections.emptyList());
|
super(vanillaCommand.getName(), "A Mojang provided command.", vanillaCommand.getUsageText(), Collections.emptyList());
|
||||||
this.vanillaCommand = vanillaCommand;
|
this.vanillaCommand = vanillaCommand;
|
||||||
this.setPermission(VanillaCommandWrapper.getPermission(vanillaCommand));
|
this.setPermission(VanillaCommandWrapper.getPermission(vanillaCommand));
|
||||||
|
this.helpCommandNamespace = "Minecraft";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -199,18 +199,15 @@ public class SimpleHelpMap implements HelpMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getCommandPluginName(Command command) {
|
private String getCommandPluginName(Command command) {
|
||||||
// Paper start - Move up
|
|
||||||
if (command instanceof PluginIdentifiableCommand) {
|
if (command instanceof PluginIdentifiableCommand) {
|
||||||
return ((PluginIdentifiableCommand) command).getPlugin().getName();
|
return ((PluginIdentifiableCommand) command).getPlugin().getName();
|
||||||
}
|
}
|
||||||
// Paper end
|
if (command instanceof VanillaCommandWrapper wrapper) {
|
||||||
if (command instanceof VanillaCommandWrapper) {
|
return wrapper.helpCommandNamespace;
|
||||||
return "Minecraft";
|
|
||||||
}
|
}
|
||||||
if (command instanceof BukkitCommand) {
|
if (command instanceof BukkitCommand) {
|
||||||
return "Bukkit";
|
return "Bukkit";
|
||||||
}
|
}
|
||||||
// Paper - Move PluginIdentifiableCommand instanceof check to allow brig commands
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user