✨ Improve Bukkit conflict management
Conflicting commands will now obey plugin load order. Brigadier aliases will be created for namespaced aliases. No asynchronous completions will be provided for conflicting commands and will only be provided for the namespaced label. Furthermore, error handling the command tree has been improved and the methods now return a pair, rather than an optional. This means that there's no need to catch and unwrap exceptions and they will be forwarded in the correct form.
This commit is contained in:
parent
8eaf0ac772
commit
22993a46d7
10 changed files with 271 additions and 172 deletions
|
|
@ -35,14 +35,18 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
class BukkitPluginRegistrationHandler<C> implements CommandRegistrationHandler {
|
||||
public class BukkitPluginRegistrationHandler<C> implements CommandRegistrationHandler {
|
||||
|
||||
private final Map<CommandArgument<?, ?>, org.bukkit.command.Command> registeredCommands = new HashMap<>();
|
||||
private final Set<String> recognizedAliases = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
private Map<String, org.bukkit.command.Command> bukkitCommands;
|
||||
private BukkitCommandManager<C> bukkitCommandManager;
|
||||
|
|
@ -51,7 +55,7 @@ class BukkitPluginRegistrationHandler<C> implements CommandRegistrationHandler {
|
|||
BukkitPluginRegistrationHandler() {
|
||||
}
|
||||
|
||||
void initialize(final @NonNull BukkitCommandManager<C> bukkitCommandManager) throws Exception {
|
||||
final void initialize(final @NonNull BukkitCommandManager<C> bukkitCommandManager) throws Exception {
|
||||
final Method getCommandMap = Bukkit.getServer().getClass().getDeclaredMethod("getCommandMap");
|
||||
getCommandMap.setAccessible(true);
|
||||
this.commandMap = (CommandMap) getCommandMap.invoke(Bukkit.getServer());
|
||||
|
|
@ -65,31 +69,41 @@ class BukkitPluginRegistrationHandler<C> implements CommandRegistrationHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean registerCommand(final @NonNull Command<?> command) {
|
||||
public final boolean registerCommand(final @NonNull Command<?> command) {
|
||||
/* We only care about the root command argument */
|
||||
final CommandArgument<?, ?> commandArgument = command.getArguments().get(0);
|
||||
if (this.registeredCommands.containsKey(commandArgument)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String label;
|
||||
final String prefixedLabel = String.format("%s:%s", this.bukkitCommandManager.getOwningPlugin().getName(),
|
||||
commandArgument.getName()).toLowerCase();
|
||||
if (bukkitCommands.containsKey(commandArgument.getName())) {
|
||||
label = String.format("%s:%s", this.bukkitCommandManager.getOwningPlugin().getName(), commandArgument.getName());
|
||||
label = prefixedLabel;
|
||||
} else {
|
||||
label = commandArgument.getName();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") final List<String> aliases = ((StaticArgument<C>) commandArgument).getAlternativeAliases();
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<String> aliases = new ArrayList<>(((StaticArgument<C>) commandArgument).getAlternativeAliases());
|
||||
|
||||
if (!label.contains(":")) {
|
||||
aliases.add(prefixedLabel);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") final BukkitCommand<C> bukkitCommand = new BukkitCommand<>(
|
||||
commandArgument.getName(),
|
||||
label,
|
||||
(this.bukkitCommandManager.getSplitAliases() ? Collections.<String>emptyList() : aliases),
|
||||
(Command<C>) command,
|
||||
(CommandArgument<C, ?>) commandArgument,
|
||||
this.bukkitCommandManager);
|
||||
this.registeredCommands.put(commandArgument, bukkitCommand);
|
||||
this.commandMap.register(commandArgument.getName(), this.bukkitCommandManager.getOwningPlugin().getName().toLowerCase(),
|
||||
this.commandMap.register(label,
|
||||
this.bukkitCommandManager.getOwningPlugin().getName().toLowerCase(),
|
||||
bukkitCommand);
|
||||
this.registerExternal(commandArgument.getName(), command, bukkitCommand);
|
||||
this.registerExternal(label, command, bukkitCommand);
|
||||
this.recognizedAliases.add(label);
|
||||
|
||||
if (this.bukkitCommandManager.getSplitAliases()) {
|
||||
for (final String alias : aliases) {
|
||||
|
|
@ -104,6 +118,7 @@ class BukkitPluginRegistrationHandler<C> implements CommandRegistrationHandler {
|
|||
.getName().toLowerCase(),
|
||||
bukkitCommand);
|
||||
this.registerExternal(alias, command, aliasCommand);
|
||||
this.recognizedAliases.add(alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -111,6 +126,16 @@ class BukkitPluginRegistrationHandler<C> implements CommandRegistrationHandler {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given alias is recognizable by this registration handler
|
||||
*
|
||||
* @param alias Alias
|
||||
* @return {@code true} if the alias is recognized, else {@code false}
|
||||
*/
|
||||
public boolean isRecognized(@NonNull final String alias) {
|
||||
return this.recognizedAliases.contains(alias);
|
||||
}
|
||||
|
||||
protected void registerExternal(final @NonNull String label,
|
||||
final @NonNull Command<?> command,
|
||||
final @NonNull BukkitCommand<C> bukkitCommand) {
|
||||
|
|
|
|||
|
|
@ -128,6 +128,13 @@ public final class BungeeCommand<C> extends Command implements TabExecutor {
|
|||
);
|
||||
} else {
|
||||
commandSender.sendMessage(new ComponentBuilder(throwable.getMessage()).create());
|
||||
this.manager.getOwningPlugin().getLogger().warning(
|
||||
String.format("(Cloud) Unknown exception type '%s' with cause '%s'",
|
||||
throwable.getClass().getCanonicalName(),
|
||||
throwable.getCause() == null ? "none"
|
||||
: throwable.getCause()
|
||||
.getClass().getCanonicalName())
|
||||
);
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
//
|
||||
package cloud.commandframework.paper;
|
||||
|
||||
import cloud.commandframework.bukkit.BukkitPluginRegistrationHandler;
|
||||
import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
|
@ -51,6 +52,12 @@ class AsyncCommandSuggestionsListener<C> implements Listener {
|
|||
if (paperCommandManager.getCommandTree().getNamedNode(arguments[0]) == null) {
|
||||
return;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
final BukkitPluginRegistrationHandler<C> bukkitPluginRegistrationHandler =
|
||||
(BukkitPluginRegistrationHandler<C>) this.paperCommandManager.getCommandRegistrationHandler();
|
||||
if (!bukkitPluginRegistrationHandler.isRecognized(arguments[0])) {
|
||||
return;
|
||||
}
|
||||
final CommandSender sender = event.getSender();
|
||||
final C cloudSender = this.paperCommandManager.getCommandSenderMapper().apply(sender);
|
||||
final List<String> suggestions = new ArrayList<>(this.paperCommandManager.suggest(cloudSender,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent;
|
|||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.PluginIdentifiableCommand;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
|
@ -49,6 +50,7 @@ import java.util.UUID;
|
|||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class PaperBrigadierListener<C> implements Listener {
|
||||
|
||||
|
|
@ -168,8 +170,21 @@ class PaperBrigadierListener<C> implements Listener {
|
|||
|
||||
@EventHandler
|
||||
public void onCommandRegister(@Nonnull final CommandRegisteredEvent<BukkitBrigadierCommandSource> event) {
|
||||
if (!(event.getCommand() instanceof PluginIdentifiableCommand)) {
|
||||
return;
|
||||
} else if (!((PluginIdentifiableCommand) event.getCommand())
|
||||
.getPlugin().equals(this.paperCommandManager.getOwningPlugin())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CommandTree<C> commandTree = this.paperCommandManager.getCommandTree();
|
||||
final CommandTree.Node<CommandArgument<C, ?>> node = commandTree.getNamedNode(event.getCommandLabel());
|
||||
|
||||
String label = event.getCommandLabel();
|
||||
if (label.contains(":")) {
|
||||
label = label.split(Pattern.quote(":"))[1];
|
||||
}
|
||||
|
||||
final CommandTree.Node<CommandArgument<C, ?>> node = commandTree.getNamedNode(label);
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue