From a6d1122f7f1e7673a986d4f22c7f375d052fed61 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Fri, 11 Jan 2019 00:41:26 +0100 Subject: [PATCH] Some command improvements Removing commands on component/plugin disable --- .idea/modules.xml | 1 - .../buttondevteam/core/CommandCaller.java | 73 ++++-- .../java/buttondevteam/core/MainPlugin.java | 242 +++++++++--------- .../lib/architecture/ButtonPlugin.java | 2 + .../lib/architecture/Component.java | 4 +- .../buttondevteam/lib/chat/TBMCChatAPI.java | 100 ++++++-- .../lib/chat/TBMCCommandBase.java | 217 ++++++++-------- 7 files changed, 361 insertions(+), 278 deletions(-) diff --git a/.idea/modules.xml b/.idea/modules.xml index fc07820..0b24af5 100755 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -4,7 +4,6 @@ - diff --git a/ButtonCore/src/main/java/buttondevteam/core/CommandCaller.java b/ButtonCore/src/main/java/buttondevteam/core/CommandCaller.java index 7ab952a..e93d386 100755 --- a/ButtonCore/src/main/java/buttondevteam/core/CommandCaller.java +++ b/ButtonCore/src/main/java/buttondevteam/core/CommandCaller.java @@ -21,41 +21,27 @@ public class CommandCaller implements CommandExecutor { public static void RegisterCommand(TBMCCommandBase cmd) throws Exception { if (instance == null) instance = new CommandCaller(); - String topcmd = cmd.GetCommandPath(); - if (topcmd == null) - throw new Exception("Command " + cmd.getClass().getSimpleName() + " has no command path!"); - if (cmd.getPlugin() == null) - throw new Exception("Command " + cmd.GetCommandPath() + " has no plugin!"); - int i; - if ((i = topcmd.indexOf(' ')) != -1) // Get top-level command - topcmd = topcmd.substring(0, i); - { - PluginCommand pc = ((JavaPlugin) cmd.getPlugin()).getCommand(topcmd); - if (pc == null) - throw new Exception("Top level command " + topcmd + " not registered in plugin.yml for plugin: " - + cmd.getPlugin().getName()); - else { - pc.setExecutor(instance); - String[] helptext = cmd.GetHelpText(topcmd); - if (helptext == null || helptext.length == 0) - throw new Exception("Command " + cmd.GetCommandPath() + " has no help text!"); - pc.setUsage(helptext.length > 1 ? helptext[1] : helptext[0]); - } - } + String[] topcmd = new String[1]; //Holds out param + PluginCommand pc = getPluginCommand(cmd, topcmd); + pc.setExecutor(instance); + String[] helptext = cmd.GetHelpText(topcmd[0]); + if (helptext == null || helptext.length == 0) + throw new Exception("Command " + cmd.GetCommandPath() + " has no help text!"); + pc.setUsage(helptext.length > 1 ? helptext[1] : helptext[0]); } @Override public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) { - String path = command.getName().toLowerCase(); + StringBuilder path = new StringBuilder(command.getName().toLowerCase()); for (String arg : args) - path += " " + arg; - TBMCCommandBase cmd = TBMCChatAPI.GetCommands().get(path); + path.append(" ").append(arg); + TBMCCommandBase cmd = TBMCChatAPI.GetCommands().get(path.toString()); int argc = 0; String[] subcmds = null; - while (cmd == null && (subcmds = TBMCChatAPI.GetSubCommands(path, sender)).length == 0 && path.contains(" ")) { - path = path.substring(0, path.lastIndexOf(' ')); + while (cmd == null && (subcmds = TBMCChatAPI.GetSubCommands(path.toString(), sender)).length == 0 && path.toString().contains(" ")) { + path = new StringBuilder(path.substring(0, path.toString().lastIndexOf(' '))); argc++; - cmd = TBMCChatAPI.GetCommands().get(path); + cmd = TBMCChatAPI.GetCommands().get(path.toString()); } if (cmd == null) { if (subcmds.length > 0) //Subcmds will always have value here (see assignment above) @@ -85,4 +71,37 @@ public class CommandCaller implements CommandExecutor { } return true; } + + public static void UnregisterCommand(TBMCCommandBase cmd) throws Exception { + PluginCommand pc = getPluginCommand(cmd, null); + pc.setExecutor(null); //Sets the executor to this plugin + } + + /** + * Gets the plugin command from the TBMC command. + * + * @param cmd The TBMC command + * @param out_topcmd An array with at least 1 elements or null + * @return The Bukkit plugin command - an exception is generated if null + * @throws Exception If the command isn't set up properly (or a different error) + */ + public static PluginCommand getPluginCommand(TBMCCommandBase cmd, String[] out_topcmd) throws Exception { + String topcmd = cmd.GetCommandPath(); + if (topcmd == null) + throw new Exception("Command " + cmd.getClass().getSimpleName() + " has no command path!"); + if (cmd.getPlugin() == null) + throw new Exception("Command " + cmd.GetCommandPath() + " has no plugin!"); + int i; + if ((i = topcmd.indexOf(' ')) != -1) // Get top-level command + topcmd = topcmd.substring(0, i); + if (out_topcmd != null && out_topcmd.length > 0) + out_topcmd[0] = topcmd; + { + PluginCommand pc = ((JavaPlugin) cmd.getPlugin()).getCommand(topcmd); + if (pc == null) + throw new Exception("Top level command " + topcmd + " not registered in plugin.yml for plugin: " + + cmd.getPlugin().getName()); + return pc; + } + } } diff --git a/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java b/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java index b3a4aaa..92a3517 100755 --- a/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java +++ b/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java @@ -1,117 +1,125 @@ -package buttondevteam.core; - -import buttondevteam.component.restart.RestartComponent; -import buttondevteam.component.updater.PluginUpdater; -import buttondevteam.component.updater.PluginUpdaterComponent; -import buttondevteam.lib.TBMCCoreAPI; -import buttondevteam.lib.architecture.Component; -import buttondevteam.lib.chat.Channel; -import buttondevteam.lib.chat.ChatRoom; -import buttondevteam.lib.chat.Color; -import buttondevteam.lib.chat.TBMCChatAPI; -import buttondevteam.lib.player.ChromaGamerBase; -import buttondevteam.lib.player.TBMCPlayer; -import buttondevteam.lib.player.TBMCPlayerBase; -import com.earth2me.essentials.Essentials; -import net.milkbowl.vault.permission.Permission; -import org.bukkit.Bukkit; -import org.bukkit.command.BlockCommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.plugin.RegisteredServiceProvider; -import org.bukkit.plugin.java.JavaPlugin; - -import javax.annotation.Nullable; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.Arrays; -import java.util.Optional; -import java.util.UUID; -import java.util.logging.Logger; - -public class MainPlugin extends JavaPlugin { - public static MainPlugin Instance; - @Nullable - public static Permission permission; - public static boolean Test; - public static Essentials ess; - - private Logger logger; - - @Override - public void onEnable() { - // Logs "Plugin Enabled", registers commands - Instance = this; - PluginDescriptionFile pdf = getDescription(); - logger = getLogger(); - setupPermissions(); - Test = getConfig().getBoolean("test", true); - saveConfig(); - Component.registerComponent(this, new PluginUpdaterComponent()); - Component.registerComponent(this, new RestartComponent()); - ComponentManager.enableComponents(); - TBMCChatAPI.AddCommand(this, MemberCommand.class); - TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this); - ChromaGamerBase.addConverter(commandSender -> Optional.ofNullable(commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender - ? TBMCPlayer.getPlayer(new UUID(0, 0), TBMCPlayer.class) : null)); //Console & cmdblocks - ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof Player - ? TBMCPlayer.getPlayer(((Player) sender).getUniqueId(), TBMCPlayer.class) : null)); //Players, has higher priority - TBMCCoreAPI.RegisterUserClass(TBMCPlayerBase.class); - TBMCChatAPI.RegisterChatChannel(Channel.GlobalChat = new Channel("§fOOC§f", Color.White, "ooc", null)); - Channel.GlobalChat.IDs = new String[]{"g"}; //Support /g as well - TBMCChatAPI.RegisterChatChannel( - Channel.AdminChat = new Channel("§cADMIN§f", Color.Red, "a", Channel.inGroupFilter(null))); - TBMCChatAPI.RegisterChatChannel( - Channel.ModChat = new Channel("§9MOD§f", Color.Blue, "mod", Channel.inGroupFilter("mod"))); - TBMCChatAPI.RegisterChatChannel(new Channel("§6DEV§f", Color.Gold, "dev", Channel.inGroupFilter("developer"))); - TBMCChatAPI.RegisterChatChannel(new ChatRoom("§cRED§f", Color.DarkRed, "red")); - TBMCChatAPI.RegisterChatChannel(new ChatRoom("§6ORANGE§f", Color.Gold, "orange")); - TBMCChatAPI.RegisterChatChannel(new ChatRoom("§eYELLOW§f", Color.Yellow, "yellow")); - TBMCChatAPI.RegisterChatChannel(new ChatRoom("§aGREEN§f", Color.Green, "green")); - TBMCChatAPI.RegisterChatChannel(new ChatRoom("§bBLUE§f", Color.Blue, "blue")); - TBMCChatAPI.RegisterChatChannel(new ChatRoom("§5PURPLE§f", Color.DarkPurple, "purple")); - try { - Files.write(new File("plugins", "plugins.txt").toPath(), Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(p -> (CharSequence) p.getDataFolder().getName())::iterator); - } catch (IOException e) { - TBMCCoreAPI.SendException("Failed to write plugin list!", e); - } - ess = Essentials.getPlugin(Essentials.class); - new RandomTP().onEnable(this); //It registers it's command - logger.info(pdf.getName() + " has been Enabled (V." + pdf.getVersion() + ") Test: " + Test + "."); - } - - @Override - public void onDisable() { - ComponentManager.disableComponents(); - logger.info("Saving player data..."); - TBMCPlayerBase.savePlayers(); - logger.info("Player data saved."); - new Thread(() -> { - File[] files = PluginUpdater.updatedir.listFiles(); - if (files == null) - return; - System.out.println("Updating " + files.length + " plugins..."); - for (File file : files) { - try { - Files.move(file.toPath(), new File("plugins", file.getName()).toPath(), StandardCopyOption.REPLACE_EXISTING); - System.out.println("Updated " + file.getName()); - } catch (IOException e) { - e.printStackTrace(); - } - } - System.out.println("Update complete!"); - }).start(); - } - - private boolean setupPermissions() { - RegisteredServiceProvider permissionProvider = getServer().getServicesManager() - .getRegistration(Permission.class); - if (permissionProvider != null) { - permission = permissionProvider.getProvider(); - } - return (permission != null); - } -} +package buttondevteam.core; + +import buttondevteam.component.restart.RestartComponent; +import buttondevteam.component.updater.PluginUpdater; +import buttondevteam.component.updater.PluginUpdaterComponent; +import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.architecture.Component; +import buttondevteam.lib.chat.Channel; +import buttondevteam.lib.chat.ChatRoom; +import buttondevteam.lib.chat.Color; +import buttondevteam.lib.chat.TBMCChatAPI; +import buttondevteam.lib.player.ChromaGamerBase; +import buttondevteam.lib.player.TBMCPlayer; +import buttondevteam.lib.player.TBMCPlayerBase; +import com.earth2me.essentials.Essentials; +import net.milkbowl.vault.permission.Permission; +import org.bukkit.Bukkit; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.bukkit.plugin.java.JavaPlugin; + +import javax.annotation.Nullable; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.Arrays; +import java.util.Optional; +import java.util.UUID; +import java.util.logging.Logger; + +public class MainPlugin extends JavaPlugin { + public static MainPlugin Instance; + @Nullable + public static Permission permission; + public static boolean Test; + public static Essentials ess; + + private Logger logger; + + @Override + public void onEnable() { + // Logs "Plugin Enabled", registers commands + Instance = this; + PluginDescriptionFile pdf = getDescription(); + logger = getLogger(); + setupPermissions(); + Test = getConfig().getBoolean("test", true); + saveConfig(); + Component.registerComponent(this, new PluginUpdaterComponent()); + Component.registerComponent(this, new RestartComponent()); + ComponentManager.enableComponents(); + TBMCChatAPI.AddCommand(this, MemberCommand.class); + TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this); + ChromaGamerBase.addConverter(commandSender -> Optional.ofNullable(commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender + ? TBMCPlayer.getPlayer(new UUID(0, 0), TBMCPlayer.class) : null)); //Console & cmdblocks + ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof Player + ? TBMCPlayer.getPlayer(((Player) sender).getUniqueId(), TBMCPlayer.class) : null)); //Players, has higher priority + TBMCCoreAPI.RegisterUserClass(TBMCPlayerBase.class); + TBMCChatAPI.RegisterChatChannel(Channel.GlobalChat = new Channel("§fOOC§f", Color.White, "ooc", null)); + Channel.GlobalChat.IDs = new String[]{"g"}; //Support /g as well + TBMCChatAPI.RegisterChatChannel( + Channel.AdminChat = new Channel("§cADMIN§f", Color.Red, "a", Channel.inGroupFilter(null))); + TBMCChatAPI.RegisterChatChannel( + Channel.ModChat = new Channel("§9MOD§f", Color.Blue, "mod", Channel.inGroupFilter("mod"))); + TBMCChatAPI.RegisterChatChannel(new Channel("§6DEV§f", Color.Gold, "dev", Channel.inGroupFilter("developer"))); + TBMCChatAPI.RegisterChatChannel(new ChatRoom("§cRED§f", Color.DarkRed, "red")); + TBMCChatAPI.RegisterChatChannel(new ChatRoom("§6ORANGE§f", Color.Gold, "orange")); + TBMCChatAPI.RegisterChatChannel(new ChatRoom("§eYELLOW§f", Color.Yellow, "yellow")); + TBMCChatAPI.RegisterChatChannel(new ChatRoom("§aGREEN§f", Color.Green, "green")); + TBMCChatAPI.RegisterChatChannel(new ChatRoom("§bBLUE§f", Color.Blue, "blue")); + TBMCChatAPI.RegisterChatChannel(new ChatRoom("§5PURPLE§f", Color.DarkPurple, "purple")); + try { + Files.write(new File("plugins", "plugins.txt").toPath(), Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(p -> (CharSequence) p.getDataFolder().getName())::iterator); + } catch (IOException e) { + TBMCCoreAPI.SendException("Failed to write plugin list!", e); + } + ess = Essentials.getPlugin(Essentials.class); + new RandomTP().onEnable(this); //It registers it's command + logger.info(pdf.getName() + " has been Enabled (V." + pdf.getVersion() + ") Test: " + Test + "."); + } + + @Override + public void onDisable() { + ComponentManager.disableComponents(); + logger.info("Saving player data..."); + TBMCPlayerBase.savePlayers(); + logger.info("Player data saved."); + new Thread(() -> { + File[] files = PluginUpdater.updatedir.listFiles(); + if (files == null) + return; + System.out.println("Updating " + files.length + " plugins..."); + for (File file : files) { + try { + Files.move(file.toPath(), new File("plugins", file.getName()).toPath(), StandardCopyOption.REPLACE_EXISTING); + System.out.println("Updated " + file.getName()); + } catch (IOException e) { + e.printStackTrace(); + } + } + System.out.println("Update complete!"); + }).start(); + } + + private boolean setupPermissions() { + RegisteredServiceProvider permissionProvider = getServer().getServicesManager() + .getRegistration(Permission.class); + if (permissionProvider != null) { + permission = permissionProvider.getProvider(); + } + return (permission != null); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + sender.sendMessage("§cThis command isn't available."); //In theory, unregistered commands use this method + return true; + } +} diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java index 292ac46..56e580d 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java @@ -1,6 +1,7 @@ package buttondevteam.lib.architecture; import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.chat.TBMCChatAPI; import lombok.AccessLevel; import lombok.Getter; import lombok.experimental.var; @@ -32,6 +33,7 @@ public abstract class ButtonPlugin extends JavaPlugin { pluginDisable(); saveConfig(); iConfig.resetConfigurationCache(); + TBMCChatAPI.RemoveCommands(this); } catch (Exception e) { TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e); } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java index 98e38d1..9a09483 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java @@ -5,7 +5,6 @@ import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException; import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.chat.TBMCCommandBase; -import lombok.AccessLevel; import lombok.Getter; import lombok.NonNull; import lombok.experimental.var; @@ -26,7 +25,7 @@ public abstract class Component { @Getter private boolean enabled = false; - @Getter(value = AccessLevel.PROTECTED) + @Getter @NonNull private JavaPlugin plugin; @NonNull @@ -131,6 +130,7 @@ public abstract class Component { component.disable(); component.plugin.saveConfig(); component.config.resetConfigurationCache(); + TBMCChatAPI.RemoveCommands(component); } } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java index b08a64f..ed61f53 100755 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java @@ -6,6 +6,7 @@ import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatPreprocessEvent; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCSystemChatEvent; +import buttondevteam.lib.architecture.Component; import buttondevteam.lib.chat.Channel.RecipientTestResult; import lombok.val; import org.bukkit.Bukkit; @@ -119,10 +120,8 @@ public class TBMCChatAPI { continue; TBMCCommandBase c = cmd.newInstance(); c.plugin = plugin; - if (HasNulls(plugin, c)) - continue; + CommandCaller.RegisterCommand(c); //Will check for nulls commands.put(c.GetCommandPath(), c); - CommandCaller.RegisterCommand(c); } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while registering command " + cmd.getName(), e); } @@ -155,55 +154,106 @@ public class TBMCChatAPI { else c = thecmdclass.newInstance(); c.plugin = plugin; - if (HasNulls(plugin, c)) - return; + CommandCaller.RegisterCommand(c); //Will check for nulls commands.put(c.GetCommandPath(), c); - CommandCaller.RegisterCommand(c); } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while registering command " + thecmdclass.getSimpleName(), e); } - } + } //TODO: onCommand(CommandSender sender, String alias, int arg1, String arg2) (planned for a while) /** *

- * This method adds a plugin's command to help and sets it's executor. + * This method adds a plugin's command to help and sets its executor. *

*

- * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a messsage to console. + * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a message to console. *

*

* Using this method after the server is done loading will have no effect. *

- * + * * @param plugin * The caller plugin * @param cmd * The command to add */ public static void AddCommand(JavaPlugin plugin, TBMCCommandBase cmd) { - if (HasNulls(plugin, cmd)) - return; - // plugin.getLogger().info("Registering command /" + cmd.GetCommandPath() + " for " + plugin.getName()); try { + if (plugin == null) throw new IllegalArgumentException("The plugin is null!"); + if (cmd == null) throw new IllegalArgumentException("The command is null!"); cmd.plugin = plugin; + CommandCaller.RegisterCommand(cmd); //Checks for other nulls commands.put(cmd.GetCommandPath(), cmd); - CommandCaller.RegisterCommand(cmd); } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while registering command " + cmd.GetCommandPath(), e); + TBMCCoreAPI.SendException("An error occured while registering command " + (cmd == null ? "n u l l" : cmd.GetCommandPath()), e); } } - private static boolean HasNulls(JavaPlugin plugin, TBMCCommandBase cmd) { - if (cmd == null) { - TBMCCoreAPI.SendException("An error occured while registering a command for plugin " + plugin.getName(), - new Exception("The command is null!")); - return true; - } else if (cmd.GetCommandPath() == null) { - TBMCCoreAPI.SendException("An error occured while registering command " + cmd.getClass().getSimpleName() - + " for plugin " + plugin.getName(), new Exception("The command path is null!")); - return true; + /** + *

+ * This method adds a plugin's command to help and sets its executor. + *

+ *

+ * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a message to console. + *

+ *

+ * Using this method after the server is done loading will have no effect. + *

+ * + * @param component The caller component + * @param cmd The command to add + */ + public static void AddCommand(Component component, TBMCCommandBase cmd) { + try { + if (component == null) throw new IllegalArgumentException("The component is null!"); + if (cmd == null) throw new IllegalArgumentException("The command is null!"); + cmd.plugin = component.getPlugin(); + cmd.component = component; + CommandCaller.RegisterCommand(cmd); //Checks for other nulls + commands.put(cmd.GetCommandPath(), cmd); + } catch (Exception e) { + TBMCCoreAPI.SendException("An error occured while registering command " + (cmd == null ? "n u l l" : cmd.GetCommandPath()), e); } - return false; + } + + /** + * Removes all commands from the plugin + * + * @param plugin The plugin to remove commands from + */ + public static void RemoveCommands(JavaPlugin plugin) { + commands.values().removeIf(c -> { + try { + if (c.plugin == plugin) { + CommandCaller.UnregisterCommand(c); + return true; //Remove + } + return false; + } catch (Exception e) { + TBMCCoreAPI.SendException("An error occured while unregistering commands for " + plugin.getName(), e); + return true; //Remove if it couldn't get the plugin command + } + }); + } + + /** + * Removes all commands from the component + * + * @param component The component to remove commands from + */ + public static void RemoveCommands(Component component) { + commands.values().removeIf(c -> { + try { + if (c.component == component) { + CommandCaller.UnregisterCommand(c); + return true; //Remove + } + return false; + } catch (Exception e) { + TBMCCoreAPI.SendException("An error occured while unregistering commands for " + component.getClass().getSimpleName(), e); + return true; //Remove if it couldn't get the plugin command + } + }); } /** diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java index de5fb14..dbd3b9f 100755 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java @@ -1,106 +1,111 @@ -package buttondevteam.lib.chat; - -import javassist.Modifier; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; - -import java.util.function.Function; - -/** - * Extend this class to create new TBMCCommand and use {@link TBMCChatAPI#AddCommand(org.bukkit.plugin.java.JavaPlugin, TBMCCommandBase)} to add it. Note: The command path (command name - * and subcommand arguments) will be the class name by default, removing any "command" from it. To change it (especially for subcommands), use the path field in the {@link CommandClass} annotation. - * - * @author Norbi - * - */ -@TBMCCommandEnforcer -public abstract class TBMCCommandBase { - - public TBMCCommandBase() { - path = getcmdpath(); - modonly = ismodonly(); - } - - public abstract boolean OnCommand(CommandSender sender, String alias, String[] args); - - public abstract String[] GetHelpText(String alias); - - private final String path; - - /** - * The command's path, or name if top-level command.
- * For example:
- * "u admin updateplugin" or "u" for the top level one
- * The path must be lowercase!
- * Abstract classes with no {@link CommandClass} annotations will be ignored. - * - * @return The command path, which is the command class name by default (removing any "command" from it) - Change via the {@link CommandClass} annotation - */ - public final String GetCommandPath() { - return path; - } - - private String getcmdpath() { - if (!getClass().isAnnotationPresent(CommandClass.class)) - throw new RuntimeException( - "No @CommandClass annotation on command class " + getClass().getSimpleName() + "!"); - Function, String> getFromClass = cl -> cl.getSimpleName().toLowerCase().replace("commandbase", "") // <-- ... - .replace("command", ""); - String path = getClass().getAnnotation(CommandClass.class).path(), - prevpath = path = path.length() == 0 ? getFromClass.apply(getClass()) : path; - for (Class cl = getClass().getSuperclass(); cl != null - && !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl - .getSuperclass()) { // - String newpath; - if (!cl.isAnnotationPresent(CommandClass.class) - || (newpath = cl.getAnnotation(CommandClass.class).path()).length() == 0 - || newpath.equals(prevpath)) { - if ((Modifier.isAbstract(cl.getModifiers()) && !cl.isAnnotationPresent(CommandClass.class)) - || cl.getAnnotation(CommandClass.class).excludeFromPath()) // <-- - continue; - newpath = getFromClass.apply(cl); - } - path = (prevpath = newpath) + " " + path; - } - return path; - } - - Plugin plugin; // Used By TBMCChatAPI - - public final Plugin getPlugin() { // Used by CommandCaller (ButtonChat) - return plugin; - } - - public final boolean isPlayerOnly() { - return this instanceof PlayerCommandBase || - (this instanceof OptionallyPlayerCommandBase && - (!getClass().isAnnotationPresent(OptionallyPlayerCommandClass.class) - || getClass().getAnnotation(OptionallyPlayerCommandClass.class).playerOnly())); - } - - private final boolean modonly; - - /** - * Returns true if this class' or any superclass' modOnly property is set to true. - */ - public final boolean isModOnly() { - return modonly; - } - - private boolean ismodonly() { - if (!getClass().isAnnotationPresent(CommandClass.class)) - throw new RuntimeException( - "No @CommandClass annotation on command class " + getClass().getSimpleName() + "!"); - boolean modOnly = getClass().getAnnotation(CommandClass.class).modOnly(); - for (Class cl = getClass().getSuperclass(); cl != null - && !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl - .getSuperclass()) { // - if (cl.isAnnotationPresent(CommandClass.class) && !modOnly - && cl.getAnnotation(CommandClass.class).modOnly()) { - modOnly = true; - break; - } - } - return modOnly; - } -} +package buttondevteam.lib.chat; + +import buttondevteam.lib.architecture.Component; +import javassist.Modifier; +import lombok.Getter; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; + +import java.util.function.Function; + +/** + * Extend this class to create new TBMCCommand and use {@link TBMCChatAPI#AddCommand(org.bukkit.plugin.java.JavaPlugin, TBMCCommandBase)} to add it. Note: The command path (command name + * and subcommand arguments) will be the class name by default, removing any "command" from it. To change it (especially for subcommands), use the path field in the {@link CommandClass} annotation. + * + * @author Norbi + * + */ +@TBMCCommandEnforcer +public abstract class TBMCCommandBase { + + public TBMCCommandBase() { + path = getcmdpath(); + modonly = ismodonly(); + } + + public abstract boolean OnCommand(CommandSender sender, String alias, String[] args); + + public abstract String[] GetHelpText(String alias); + + private final String path; + + /** + * The command's path, or name if top-level command.
+ * For example:
+ * "u admin updateplugin" or "u" for the top level one
+ * The path must be lowercase!
+ * Abstract classes with no {@link CommandClass} annotations will be ignored. + * + * @return The command path, which is the command class name by default (removing any "command" from it) - Change via the {@link CommandClass} annotation + */ + public final String GetCommandPath() { + return path; + } + + private String getcmdpath() { + if (!getClass().isAnnotationPresent(CommandClass.class)) + throw new RuntimeException( + "No @CommandClass annotation on command class " + getClass().getSimpleName() + "!"); + Function, String> getFromClass = cl -> cl.getSimpleName().toLowerCase().replace("commandbase", "") // <-- ... + .replace("command", ""); + String path = getClass().getAnnotation(CommandClass.class).path(), + prevpath = path = path.length() == 0 ? getFromClass.apply(getClass()) : path; + for (Class cl = getClass().getSuperclass(); cl != null + && !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl + .getSuperclass()) { // + String newpath; + if (!cl.isAnnotationPresent(CommandClass.class) + || (newpath = cl.getAnnotation(CommandClass.class).path()).length() == 0 + || newpath.equals(prevpath)) { + if ((Modifier.isAbstract(cl.getModifiers()) && !cl.isAnnotationPresent(CommandClass.class)) + || cl.getAnnotation(CommandClass.class).excludeFromPath()) // <-- + continue; + newpath = getFromClass.apply(cl); + } + path = (prevpath = newpath) + " " + path; + } + return path; + } + + Plugin plugin; // Used By TBMCChatAPI + + public final Plugin getPlugin() { // Used by CommandCaller (ButtonChat) + return plugin; + } + + public final boolean isPlayerOnly() { + return this instanceof PlayerCommandBase || + (this instanceof OptionallyPlayerCommandBase && + (!getClass().isAnnotationPresent(OptionallyPlayerCommandClass.class) + || getClass().getAnnotation(OptionallyPlayerCommandClass.class).playerOnly())); + } + + private final boolean modonly; + + /** + * Returns true if this class' or any superclass' modOnly property is set to true. + */ + public final boolean isModOnly() { + return modonly; + } + + private boolean ismodonly() { + if (!getClass().isAnnotationPresent(CommandClass.class)) + throw new RuntimeException( + "No @CommandClass annotation on command class " + getClass().getSimpleName() + "!"); + boolean modOnly = getClass().getAnnotation(CommandClass.class).modOnly(); + for (Class cl = getClass().getSuperclass(); cl != null + && !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl + .getSuperclass()) { // + if (cl.isAnnotationPresent(CommandClass.class) && !modOnly + && cl.getAnnotation(CommandClass.class).modOnly()) { + modOnly = true; + break; + } + } + return modOnly; + } + + @Getter + Component component; //May be null +}