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
This commit is contained in:
Samuel Pizette
2022-12-04 18:52:19 -05:00
parent 6f97f47712
commit a396754e2e
10 changed files with 313 additions and 237 deletions

View File

@@ -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

View File

@@ -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<String> getAliases() {
return new ArrayList<>();
}
/**
* Get description.
*
* @return The description.
*/
@Nullable
default String getDescription() {
return null;
}
}

View File

@@ -1,7 +0,0 @@
package com.willfp.eco.core.command;
public interface RegistrableCommandBase extends CommandBase {
void register();
void unregister();
}

View File

@@ -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;
* <p>
* 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<CommandBase> getSubcommands() {
return delegate.getSubcommands();
}
@Override
public void register() {
delegate.register();

View File

@@ -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<Player> 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<CommandBase> getSubcommands() {
return delegate.getSubcommands();
}
@Override
public EcoPlugin getPlugin() {
return delegate.getPlugin();
}
}

View File

@@ -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<out String>?): Boolean {
return false
}
override fun onTabComplete(
sender: CommandSender,
command: Command,
label: String,
args: Array<out String>?
): MutableList<String>? {
return mutableListOf()
}
override fun getPlugin() = delegate.plugin
override fun getPermission() = delegate.permission
override fun getDescription() = delegate.description ?: ""
override fun getAliases(): MutableList<String> = delegate.aliases
}

View File

@@ -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<CommandBase>()
override fun onCommand(
sender: CommandSender,
command: Command,
label: String,
args: Array<out String>?
): 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<out String>?
): MutableList<String>? {
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<String>) {
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<String> handleTabCompletion(@NotNull final CommandSender sender,
@NotNull final String[] args) {
if (!sender.hasPermission(this.getPermission())) {
return null;
}
if (args.length == 1) {
List<String> 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<String> 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<String>): List<String> {
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<String>()
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
}
}
}

View File

@@ -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<CommandBase>()
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<out String>?
): 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<out String>?
): MutableList<String>? {
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<String>) {
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<String> handleTabCompletion(@NotNull final CommandSender sender,
@NotNull final String[] args) {
if (!sender.hasPermission(this.getPermission())) {
return null;
}
if (args.length == 1) {
List<String> 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<String> 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<String>): List<String> {
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<String>()
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
}
}
}

View File

@@ -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) {
}

View File

@@ -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"))