From a396754e2efdf02b257f674c1850e17ea494a14c Mon Sep 17 00:00:00 2001 From: Samuel Pizette Date: Sun, 4 Dec 2022 18:52:19 -0500 Subject: [PATCH] commands rework progress - Wrote EcoDelegatedBukkitCommand.kt - Wrote EcoHandledCommand.kt - Wrote Eco#createSubCommand - Renamed RegistrableCommandBase.java to PluginCommandBase - Moved most of EcoPluginCommand.kt to EcoHandledCommand.kt - Changed Delegate type in PluginCommand from CommandBase to PluginCommandBase --- .../main/java/com/willfp/eco/core/Eco.java | 10 +- .../eco/core/command/PluginCommandBase.java | 39 ++++ .../core/command/RegistrableCommandBase.java | 7 - .../eco/core/command/impl/PluginCommand.java | 16 +- .../eco/core/command/impl/Subcommand.java | 18 +- .../command/EcoDelegatedBukkitCommand.kt | 30 +++ .../eco/internal/command/EcoHandledCommand.kt | 194 ++++++++++++++++ .../eco/internal/command/EcoPluginCommand.kt | 210 +----------------- .../eco/internal/command/EcoSubCommand.kt | 11 + .../com/willfp/eco/internal/spigot/EcoImpl.kt | 15 +- 10 files changed, 313 insertions(+), 237 deletions(-) create mode 100644 eco-api/src/main/java/com/willfp/eco/core/command/PluginCommandBase.java delete mode 100644 eco-api/src/main/java/com/willfp/eco/core/command/RegistrableCommandBase.java create mode 100644 eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoDelegatedBukkitCommand.kt create mode 100644 eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoHandledCommand.kt create mode 100644 eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoSubCommand.kt diff --git a/eco-api/src/main/java/com/willfp/eco/core/Eco.java b/eco-api/src/main/java/com/willfp/eco/core/Eco.java index 37901fe7..096e5024 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/Eco.java +++ b/eco-api/src/main/java/com/willfp/eco/core/Eco.java @@ -1,7 +1,7 @@ package com.willfp.eco.core; import com.willfp.eco.core.command.CommandBase; -import com.willfp.eco.core.command.RegistrableCommandBase; +import com.willfp.eco.core.command.PluginCommandBase; import com.willfp.eco.core.command.impl.PluginCommand; import com.willfp.eco.core.config.ConfigType; import com.willfp.eco.core.config.interfaces.Config; @@ -160,10 +160,10 @@ public interface Eco { EcoPlugin getEcoPlugin(); @NotNull - RegistrableCommandBase createPluginCommand(@NotNull EcoPlugin plugin, - @NotNull String name, - @NotNull String permission, - boolean playersOnly + PluginCommandBase createPluginCommand(@NotNull EcoPlugin plugin, + @NotNull String name, + @NotNull String permission, + boolean playersOnly ); @NotNull diff --git a/eco-api/src/main/java/com/willfp/eco/core/command/PluginCommandBase.java b/eco-api/src/main/java/com/willfp/eco/core/command/PluginCommandBase.java new file mode 100644 index 00000000..28b2c568 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/command/PluginCommandBase.java @@ -0,0 +1,39 @@ +package com.willfp.eco.core.command; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public interface PluginCommandBase extends CommandBase { + /** + * Register the PluginCommandBase to the bukkit commandMap. + */ + void register(); + + /** + * Unregister the PluginCommandBase from the bukkit commandMap. + */ + void unregister(); + + /** + * Get aliases. Leave null if this command is from plugin.yml. + * + * @return The aliases. + */ + @NotNull + default List getAliases() { + return new ArrayList<>(); + } + + /** + * Get description. + * + * @return The description. + */ + @Nullable + default String getDescription() { + return null; + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/command/RegistrableCommandBase.java b/eco-api/src/main/java/com/willfp/eco/core/command/RegistrableCommandBase.java deleted file mode 100644 index b9d803fa..00000000 --- a/eco-api/src/main/java/com/willfp/eco/core/command/RegistrableCommandBase.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.willfp.eco.core.command; - -public interface RegistrableCommandBase extends CommandBase { - void register(); - - void unregister(); -} diff --git a/eco-api/src/main/java/com/willfp/eco/core/command/impl/PluginCommand.java b/eco-api/src/main/java/com/willfp/eco/core/command/impl/PluginCommand.java index 3dd82826..953899ab 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/command/impl/PluginCommand.java +++ b/eco-api/src/main/java/com/willfp/eco/core/command/impl/PluginCommand.java @@ -3,9 +3,11 @@ package com.willfp.eco.core.command.impl; import com.willfp.eco.core.Eco; import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.command.CommandBase; -import com.willfp.eco.core.command.RegistrableCommandBase; +import com.willfp.eco.core.command.PluginCommandBase; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * PluginCommands are the class to be used instead of CommandExecutor, they function as the base * command, e.g. {@code /ecoenchants} would be a base command, with each subsequent argument @@ -15,9 +17,12 @@ import org.jetbrains.annotations.NotNull; *

* The name cannot be the same as an existing command as this will conflict. */ -public abstract class PluginCommand implements RegistrableCommandBase { +public abstract class PluginCommand implements PluginCommandBase { - private final RegistrableCommandBase delegate; + /** + * The delegate command. + */ + private final PluginCommandBase delegate; /** @@ -55,6 +60,11 @@ public abstract class PluginCommand implements RegistrableCommandBase { return delegate.addSubcommand(command); } + @Override + public @NotNull List getSubcommands() { + return delegate.getSubcommands(); + } + @Override public void register() { delegate.register(); diff --git a/eco-api/src/main/java/com/willfp/eco/core/command/impl/Subcommand.java b/eco-api/src/main/java/com/willfp/eco/core/command/impl/Subcommand.java index 68b21797..bdcdaeec 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/command/impl/Subcommand.java +++ b/eco-api/src/main/java/com/willfp/eco/core/command/impl/Subcommand.java @@ -3,11 +3,9 @@ package com.willfp.eco.core.command.impl; import com.willfp.eco.core.Eco; import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.command.CommandBase; -import com.willfp.eco.core.command.NotificationException; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import java.util.Optional; +import java.util.List; /** * Subcommands can be added to PluginCommands or to other Subcommands. @@ -65,20 +63,14 @@ public abstract class Subcommand implements CommandBase { } @Override - public @NotNull Optional notifyPlayerRequired(@NotNull String player, - @NotNull String langTarget) - throws NotificationException { - return delegate.notifyPlayerRequired(player, langTarget); - } - - @Override - public boolean notifyFalse(boolean condition, @NotNull String langTarget) - throws NotificationException { - return delegate.notifyFalse(condition, langTarget); + public @NotNull List getSubcommands() { + return delegate.getSubcommands(); } @Override public EcoPlugin getPlugin() { return delegate.getPlugin(); } + + } diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoDelegatedBukkitCommand.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoDelegatedBukkitCommand.kt new file mode 100644 index 00000000..58b648fd --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoDelegatedBukkitCommand.kt @@ -0,0 +1,30 @@ +package com.willfp.eco.internal.command + +import org.bukkit.command.Command +import org.bukkit.command.CommandSender +import org.bukkit.command.PluginIdentifiableCommand +import org.bukkit.command.TabCompleter + +/** + * Delegates a bukkit command to an eco command (for registrations). + */ +class EcoDelegatedBukkitCommand(private val delegate: EcoPluginCommand) : Command(delegate.name), TabCompleter, PluginIdentifiableCommand { + override fun execute(sender: CommandSender, label: String, args: Array?): Boolean { + return false + } + + override fun onTabComplete( + sender: CommandSender, + command: Command, + label: String, + args: Array? + ): MutableList? { + return mutableListOf() + } + + override fun getPlugin() = delegate.plugin + override fun getPermission() = delegate.permission + override fun getDescription() = delegate.description ?: "" + override fun getAliases(): MutableList = delegate.aliases + +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoHandledCommand.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoHandledCommand.kt new file mode 100644 index 00000000..7549afdb --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoHandledCommand.kt @@ -0,0 +1,194 @@ +package com.willfp.eco.internal.command + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.command.CommandBase +import com.willfp.eco.core.command.NotificationException +import org.bukkit.Bukkit +import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor +import org.bukkit.command.CommandMap +import org.bukkit.command.CommandSender +import org.bukkit.command.TabCompleter +import org.bukkit.entity.Player +import org.bukkit.util.StringUtil + +abstract class EcoHandledCommand( + private val plugin: EcoPlugin, + private val name: String, + private val permission: String, + private val playersOnly: Boolean +) : CommandBase, CommandExecutor, TabCompleter { + + + val subCommands = mutableListOf() + + override fun onCommand( + sender: CommandSender, + command: Command, + label: String, + args: Array? + ): Boolean { + + if (!command.name.equals(name, true)) { + return false + } + + if (args != null) { + handleExecution(sender, args.toList()) + } + + return true + } + + override fun onTabComplete( + sender: CommandSender, + command: Command, + label: String, + args: Array? + ): MutableList? { + return handleTabComplete(sender, args?.toList() ?: listOf()).toMutableList() + } + + override fun getPlugin() = this.plugin + + override fun getName() = this.name + + override fun getPermission() = this.permission + + override fun isPlayersOnly() = this.playersOnly + + override fun getSubcommands() = this.subCommands + + override fun addSubcommand(command: CommandBase): CommandBase { + TODO("Not yet implemented") + } + + fun CommandBase.handleExecution(sender: CommandSender, args: List) { + if (!canExecute(sender, this, plugin)) { + return + } + + if (args.isNotEmpty()) { + for (subCommand in subcommands) { + if (subCommand.name.equals(args[0], true) && !canExecute( + sender, + subCommand, + plugin + ) + ) { + return + } + + subCommand.handleExecution(sender, args.subList(1, args.size)) + return + } + } + + try { + notifyFalse(isPlayersOnly && sender !is Player, "not-player") + + if (sender is Player) { + onExecute(sender, args) + } else { + onExecute(sender, args) + } + + } catch (e: NotificationException) { + sender.sendMessage(plugin.langYml.getMessage(e.key)) + return + } + } + + /* + protected final List handleTabCompletion(@NotNull final CommandSender sender, + @NotNull final String[] args) { + + if (!sender.hasPermission(this.getPermission())) { + return null; + } + + if (args.length == 1) { + List completions = new ArrayList<>(); + + StringUtil.copyPartialMatches( + args[0], + this.getSubcommands().stream() + .filter(subCommand -> sender.hasPermission(subCommand.getPermission())) + .map(CommandBase::getName) + .collect(Collectors.toList()), + completions + ); + + Collections.sort(completions); + + if (!completions.isEmpty()) { + return completions; + } + } + + if (args.length >= 2) { + HandledCommand command = null; + + for (CommandBase subcommand : this.getSubcommands()) { + if (!sender.hasPermission(subcommand.getPermission())) { + continue; + } + + if (args[0].equalsIgnoreCase(subcommand.getName())) { + command = (HandledCommand) subcommand; + } + } + + if (command != null) { + return command.handleTabCompletion(sender, Arrays.copyOfRange(args, 1, args.length)); + } + } + + if (this.getTabCompleter() != null) { + return this.getTabCompleter().tabComplete(sender, Arrays.asList(args)); + } else { + List completions = new ArrayList<>(this.tabComplete(sender, Arrays.asList(args))); + if (sender instanceof Player player) { + completions.addAll(this.tabComplete(player, Arrays.asList(args))); + } + return completions; + } + } + */ + fun CommandBase.handleTabComplete(sender: CommandSender, args: List): List { + if (!sender.hasPermission(permission) || args.isEmpty()) return emptyList() + + val completions = subCommands.filter { sender.hasPermission(it.permission) }.map { it.name }.sorted() + + return when (args.size) { + 1 -> { + val list = mutableListOf() + StringUtil.copyPartialMatches(args[0], completions, list) + list + } + + else -> completions + } + } + + companion object { + fun getCommandMap(): CommandMap { + try { + val field = Bukkit.getServer().javaClass.getDeclaredField("commandMap") + field.trySetAccessible() + return field.get(Bukkit.getServer()) as CommandMap + } catch (e: Exception) { + throw NullPointerException("Command map wasn't found!") + } + } + + fun canExecute(sender: CommandSender, command: CommandBase, plugin: EcoPlugin): Boolean { + if (!sender.hasPermission(command.permission) && sender is Player) { + sender.sendMessage(plugin.langYml.noPermission) + return false + } + + return true + } + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoPluginCommand.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoPluginCommand.kt index 7b5890d2..2760b5d8 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoPluginCommand.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoPluginCommand.kt @@ -2,39 +2,15 @@ package com.willfp.eco.internal.command import com.willfp.eco.core.Eco import com.willfp.eco.core.EcoPlugin -import com.willfp.eco.core.command.CommandBase -import com.willfp.eco.core.command.NotificationException -import com.willfp.eco.core.command.RegistrableCommandBase +import com.willfp.eco.core.command.PluginCommandBase import org.bukkit.Bukkit -import org.bukkit.command.Command -import org.bukkit.command.CommandExecutor -import org.bukkit.command.CommandMap -import org.bukkit.command.CommandSender -import org.bukkit.command.TabCompleter -import org.bukkit.entity.Player -import org.bukkit.util.StringUtil class EcoPluginCommand( - _plugin: EcoPlugin, - _name: String, - _permission: String, - _playersOnly: Boolean -) : RegistrableCommandBase, CommandExecutor, TabCompleter { - - - val ecoPlugin: EcoPlugin - val commandName: String - val commandPermission: String - val playersOnly: Boolean - val subCommands = mutableListOf() - - init { - ecoPlugin = _plugin - commandName = _name - commandPermission = _permission - playersOnly = _playersOnly - } - + plugin: EcoPlugin, name: String, + permission: String, + playersOnly: Boolean +) : EcoHandledCommand(plugin, name, permission, playersOnly), + PluginCommandBase { override fun register() { val command = Bukkit.getPluginCommand(name) command?.let { c -> @@ -52,9 +28,7 @@ class EcoPluginCommand( val map = getCommandMap() - // TODO MOVE DELEGATED BUKKIT COMMAND TO BACKEND - // map.register(plugin.name.lowercase(), DelegatedBukkitCommand(this)) - + map.register(plugin.name.lowercase(), EcoDelegatedBukkitCommand(this)) } Eco.get().syncCommands() @@ -67,174 +41,4 @@ class EcoPluginCommand( Eco.get().syncCommands() } - - override fun onCommand( - commandSender: CommandSender, - command: Command, - s: String, - strings: Array? - ): Boolean { - - if (!command.name.equals(name, true)) { - return false - } - - if (strings != null) { - handleExecution(commandSender, strings.toList()) - } - - return true - } - - override fun onTabComplete( - commandSender: CommandSender, - command: Command, - s: String, - strings: Array? - ): MutableList? { - TODO("IMPLEMENT ON TAB COMPLETE") - } - - override fun getPlugin(): EcoPlugin = ecoPlugin - - override fun getName(): String = commandName - - override fun getPermission(): String = commandPermission - - override fun isPlayersOnly(): Boolean = playersOnly - - override fun addSubcommand(command: CommandBase): CommandBase { - TODO("Not yet implemented") - } - - override fun getSubcommands() = subCommands - - fun CommandBase.handleExecution(sender: CommandSender, args: List) { - if (!canExecute(sender, this, plugin)) { - return - } - - if (args.isNotEmpty()) { - for (subCommand in subcommands) { - if (subCommand.name.equals(args[0], true) && !canExecute( - sender, - subCommand, - plugin - ) - ) { - return - } - - subCommand.handleExecution(sender, args.subList(1, args.size)) - return - } - } - - try { - notifyFalse(isPlayersOnly && sender !is Player, "not-player") - - if (sender is Player) { - onExecute(sender, args) - } else { - onExecute(sender, args) - } - - } catch (e: NotificationException) { - sender.sendMessage(plugin.langYml.getMessage(e.key)) - return - } - } - - /* - protected final List handleTabCompletion(@NotNull final CommandSender sender, - @NotNull final String[] args) { - - if (!sender.hasPermission(this.getPermission())) { - return null; - } - - if (args.length == 1) { - List completions = new ArrayList<>(); - - StringUtil.copyPartialMatches( - args[0], - this.getSubcommands().stream() - .filter(subCommand -> sender.hasPermission(subCommand.getPermission())) - .map(CommandBase::getName) - .collect(Collectors.toList()), - completions - ); - - Collections.sort(completions); - - if (!completions.isEmpty()) { - return completions; - } - } - - if (args.length >= 2) { - HandledCommand command = null; - - for (CommandBase subcommand : this.getSubcommands()) { - if (!sender.hasPermission(subcommand.getPermission())) { - continue; - } - - if (args[0].equalsIgnoreCase(subcommand.getName())) { - command = (HandledCommand) subcommand; - } - } - - if (command != null) { - return command.handleTabCompletion(sender, Arrays.copyOfRange(args, 1, args.length)); - } - } - - if (this.getTabCompleter() != null) { - return this.getTabCompleter().tabComplete(sender, Arrays.asList(args)); - } else { - List completions = new ArrayList<>(this.tabComplete(sender, Arrays.asList(args))); - if (sender instanceof Player player) { - completions.addAll(this.tabComplete(player, Arrays.asList(args))); - } - return completions; - } - } - */ - fun CommandBase.handleTabComplete(sender: CommandSender, args: List): List { - if (!sender.hasPermission(permission) || args.isEmpty()) return emptyList() - - val completions = subCommands.filter { sender.hasPermission(it.permission) }.map { it.name }.sorted() - - return when (args.size) { - 1 -> { - val list = mutableListOf() - StringUtil.copyPartialMatches(args[0], completions, list) - list - } - - else -> completions - } - } - - companion object { - fun getCommandMap(): CommandMap { - try { - val field = Bukkit.getServer().javaClass.getDeclaredField("commandMap"); - field.trySetAccessible() - return field.get(Bukkit.getServer()) as CommandMap - } catch (e: Exception) { - throw NullPointerException("Command map wasn't found!"); - } - } - - fun canExecute(sender: CommandSender, command: CommandBase, plugin: EcoPlugin): Boolean { - if (!sender.hasPermission(command.permission) && sender is Player) { - sender.sendMessage(plugin.langYml.noPermission) - return false - } - - return true - } - } } \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoSubCommand.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoSubCommand.kt new file mode 100644 index 00000000..fe7789d2 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/EcoSubCommand.kt @@ -0,0 +1,11 @@ +package com.willfp.eco.internal.command + +import com.willfp.eco.core.EcoPlugin + +class EcoSubCommand( + plugin: EcoPlugin, name: String, + permission: String, + playersOnly: Boolean +) : EcoHandledCommand(plugin, name, permission, playersOnly) { + +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt index 09c45883..99921b25 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt @@ -4,7 +4,7 @@ import com.willfp.eco.core.Eco import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.PluginLike import com.willfp.eco.core.PluginProps -import com.willfp.eco.core.command.CommandBase +import com.willfp.eco.core.command.impl.PluginCommand import com.willfp.eco.core.config.ConfigType import com.willfp.eco.core.config.interfaces.Config import com.willfp.eco.core.data.keys.PersistentDataKey @@ -15,6 +15,7 @@ import com.willfp.eco.core.items.Items import com.willfp.eco.core.math.MathContext import com.willfp.eco.internal.EcoPropsParser import com.willfp.eco.internal.command.EcoPluginCommand +import com.willfp.eco.internal.command.EcoSubCommand import com.willfp.eco.internal.config.* import com.willfp.eco.internal.drops.EcoDropQueue import com.willfp.eco.internal.drops.EcoFastCollatedDropQueue @@ -40,6 +41,7 @@ import com.willfp.eco.internal.spigot.data.ProfileHandler import com.willfp.eco.internal.spigot.data.storage.HandlerType import com.willfp.eco.internal.spigot.integrations.bstats.MetricHandler import com.willfp.eco.internal.spigot.math.evaluateExpression +import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy import com.willfp.eco.internal.spigot.proxy.CommonsInitializerProxy import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy import com.willfp.eco.internal.spigot.proxy.EntityControllerFactoryProxy @@ -48,11 +50,9 @@ import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy import com.willfp.eco.internal.spigot.proxy.MiniMessageTranslatorProxy import com.willfp.eco.internal.spigot.proxy.SNBTConverterProxy import com.willfp.eco.internal.spigot.proxy.SkullProxy -import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy import com.willfp.eco.internal.spigot.proxy.TPSProxy import org.bukkit.Location import org.bukkit.NamespacedKey -import org.bukkit.command.Command import org.bukkit.command.CommandMap import org.bukkit.configuration.ConfigurationSection import org.bukkit.entity.Entity @@ -183,9 +183,12 @@ class EcoImpl : EcoSpigotPlugin(), Eco { name: String, permission: String, playersOnly: Boolean - ): CommandBase { - TODO("Not yet implemented") - } + ) = EcoSubCommand( + plugin, + name, + permission, + playersOnly + ) override fun createDropQueue(player: Player) = if (this.configYml.getBool("use-fast-collated-drops"))