diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitAsyncCommandExecutor.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitAsyncCommandExecutor.java new file mode 100644 index 000000000..54be74b6c --- /dev/null +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitAsyncCommandExecutor.java @@ -0,0 +1,80 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.bukkit; + +import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent; + +import me.lucko.luckperms.common.command.utils.ArgumentTokenizer; +import me.lucko.luckperms.common.sender.Sender; + +import org.bukkit.command.Command; +import org.bukkit.command.PluginCommand; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +import java.util.List; + +public class BukkitAsyncCommandExecutor extends BukkitCommandExecutor implements Listener { + public BukkitAsyncCommandExecutor(LPBukkitPlugin plugin, PluginCommand command) { + super(plugin, command); + } + + public void register() { + super.register(); + this.plugin.getBootstrap().getServer().getPluginManager().registerEvents(this, this.plugin.getBootstrap()); + } + + @EventHandler(ignoreCancelled = true) + public void onAsyncTabComplete(AsyncTabCompleteEvent e) { + if (!e.isCommand()) { + return; + } + + String buffer = e.getBuffer(); + if (buffer.charAt(0) == '/') { + buffer = buffer.substring(1); + } + + int firstSpace = buffer.indexOf(' '); + if (firstSpace < 0) { + return; + } + + String commandLabel = buffer.substring(1, firstSpace); + Command command = this.plugin.getBootstrap().getServer().getCommandMap().getCommand(commandLabel); + if (command != this.command) { + return; + } + + Sender wrapped = this.plugin.getSenderFactory().wrap(e.getSender()); + List arguments = ArgumentTokenizer.TAB_COMPLETE.tokenizeInput(buffer.substring(firstSpace + 1)); + List completions = tabCompleteCommand(wrapped, arguments); + + e.setCompletions(completions); + e.setHandled(true); + } + +} diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitCommandExecutor.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitCommandExecutor.java index 6bd129ea4..752a4f7ba 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitCommandExecutor.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitCommandExecutor.java @@ -32,17 +32,25 @@ import me.lucko.luckperms.common.sender.Sender; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; import org.bukkit.command.TabExecutor; import org.checkerframework.checker.nullness.qual.NonNull; import java.util.List; public class BukkitCommandExecutor extends CommandManager implements CommandExecutor, TabExecutor { - private final LPBukkitPlugin plugin; + protected final LPBukkitPlugin plugin; + protected final PluginCommand command; - public BukkitCommandExecutor(LPBukkitPlugin plugin) { + public BukkitCommandExecutor(LPBukkitPlugin plugin, PluginCommand command) { super(plugin); this.plugin = plugin; + this.command = command; + } + + public void register() { + this.command.setExecutor(this); + this.command.setTabCompleter(this); } @Override diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java index 3c1d67c98..d98fe94b6 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java @@ -112,15 +112,6 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin { this.senderFactory = new BukkitSenderFactory(this); } - private static boolean isBrigadierSupported() { - try { - Class.forName("com.mojang.brigadier.CommandDispatcher"); - return true; - } catch (ClassNotFoundException var1) { - return false; - } - } - @Override protected Set getGlobalDependencies() { Set dependencies = super.getGlobalDependencies(); @@ -150,15 +141,24 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin { @Override protected void registerCommands() { - this.commandManager = new BukkitCommandExecutor(this); - PluginCommand cmd = this.bootstrap.getCommand("luckperms"); - cmd.setExecutor(this.commandManager); - cmd.setTabCompleter(this.commandManager); + PluginCommand command = this.bootstrap.getCommand("luckperms"); + if (command == null) { + getLogger().severe("Unable to register /luckperms command with the server"); + return; + } + + if (isAsyncTabCompleteSupported()) { + this.commandManager = new BukkitAsyncCommandExecutor(this); + } else { + this.commandManager = new BukkitCommandExecutor(this); + } + + this.commandManager.register(command); // setup brigadier if (isBrigadierSupported()) { try { - LuckPermsBrigadier.register(this, cmd); + LuckPermsBrigadier.register(this, command); } catch (Exception e) { if (!(e instanceof RuntimeException && e.getMessage().contains("not supported by the server"))) { e.printStackTrace(); @@ -359,6 +359,23 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin { return configFile; } + private static boolean classExists(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException var1) { + return false; + } + } + + private static boolean isBrigadierSupported() { + return classExists("com.mojang.brigadier.CommandDispatcher"); + } + + private static boolean isAsyncTabCompleteSupported() { + return classExists("com.destroystokyo.paper.event.server.AsyncTabCompleteEvent"); + } + @Override public Optional getQueryOptionsForUser(User user) { return this.bootstrap.getPlayer(user.getUniqueId()).map(player -> this.contextManager.getQueryOptions(player));