Description
Description
This suggestion started as a question by Adixe in discord
Currently, whenever a command is registered, it is automatically registered under the minecraft
namespace. So, if you register a command /hello
, you can also run it using /minecraft:hello
. (https://commandapi.jorel.dev/8.5.1/intro.html#how-the-commandapi-works)
It would be nice if developers could control what namespace their commands get registered under.
Expected code
// default - runnable as /command or /minecraft:command
new CommandAPICommand("command").register();
// plugin namespace - runnable as /command or /pluginname:command
new CommandAPICommand("command").register(Plugin);
// custom namespace - runnable as /command or /custom:command
new CommandAPICommand("command").register("custom");
// no namespace - only runnable as /command
new CommandAPICommand("command").register("");
Extra details
The org.bukkit.SimpleCommandMap
class handles tracking, tab-completing, and dispatching all commands on the server, including CommandAPICommands via the VanillaCommandWrapper class.
package org.bukkit.command;
public class SimpleCommandMap implements CommandMap {
protected final Map<String, Command> knownCommands = new HashMap();
// Pretty much what registering does
public register(String name, String nameSpace, Command command) {
this.knownCommands.put(nameSpace + ":" + name, command);
this.knownCommands.put(name, command);
}
@Nullable
public Command getCommand(@NotNull String name) {
Command target = (Command)this.knownCommands.get(name.toLowerCase(Locale.ENGLISH));
return target;
}
public boolean dispatch(@NotNull CommandSender sender, @NotNull String commandLine) throws CommandException {
String[] args = commandLine.split(" ");
if (args.length == 0) {
return false;
} else {
String sentCommandLabel = args[0].toLowerCase(Locale.ENGLISH);
Command target = this.getCommand(sentCommandLabel);
if (target == null) {
return false;
} else {
// execute the target Command
}
}
}
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String cmdLine, @Nullable Location location) {
int spaceIndex = cmdLine.indexOf(32);
if (spaceIndex == -1) {
ArrayList<String> completions = new ArrayList();
Map<String, Command> kn
6742
ownCommands = this.knownCommands;
// tab complete command names based on the knownCommands map
} else {
String commandName = cmdLine.substring(0, spaceIndex);
Command target = this.getCommand(commandName);
if (target == null) {
return null;
} else {
// tab complete based on what the target command says
}
}
}
}
The knownCommands
HashMap determines which commands can be accessed. If a string exists in the map, there is a Command it can run, and if it is not in the map, Spigot shouldn't think it exists. Adding entries we want and removing entries we don't want (doesn't the removing part already happen when force unregistering commands?) should allow us to register exactly the namespaces we want.
Also, if a developer chooses to register their commands with their Plugin class, there could be a feature for looking up which commands are registered by which plugins.