From bb31f4e3783fcb3c03c7bc6a38cb9a298860794d Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Wed, 9 Jan 2019 18:52:24 +0100 Subject: [PATCH 1/7] Exclude plugins from syschat event --- .editorconfig | 15 + .../buttondevteam/core/PlayerListener.java | 123 ++-- .../lib/TBMCSystemChatEvent.java | 4 +- .../buttondevteam/lib/chat/TBMCChatAPI.java | 565 +++++++++--------- 4 files changed, 364 insertions(+), 343 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a4b334f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +[*] +charset=utf-8 +end_of_line=lf +insert_final_newline=false +indent_style=space +indent_size=4 + +[*.java] +indent_style=tab +tab_width=4 + +[{*.yml,*.yaml}] +indent_style=space +indent_size=2 + diff --git a/ButtonCore/src/main/java/buttondevteam/core/PlayerListener.java b/ButtonCore/src/main/java/buttondevteam/core/PlayerListener.java index be7c10b..c654d29 100755 --- a/ButtonCore/src/main/java/buttondevteam/core/PlayerListener.java +++ b/ButtonCore/src/main/java/buttondevteam/core/PlayerListener.java @@ -1,61 +1,64 @@ -package buttondevteam.core; - -import buttondevteam.lib.TBMCSystemChatEvent; -import buttondevteam.lib.chat.IFakePlayer; -import buttondevteam.lib.player.TBMCPlayerBase; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Statistic; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; - -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Date; - -import static buttondevteam.core.MainPlugin.permission; - -public class PlayerListener implements Listener { - - @EventHandler(priority = EventPriority.NORMAL) - public void OnPlayerJoin(PlayerJoinEvent event) { - TBMCPlayerBase.joinPlayer(event.getPlayer()); - if (permission != null && !permission.playerInGroup(event.getPlayer(), "member") - && (new Date(event.getPlayer().getFirstPlayed()).toInstant().plus(7, ChronoUnit.DAYS).isBefore(Instant.now()) - || event.getPlayer().getStatistic(Statistic.PLAY_ONE_TICK) > 20 * 3600 * 12)) { - permission.playerAddGroup(null, event.getPlayer(), "member"); - event.getPlayer().sendMessage("§bYou are a member now. YEEHAW"); - MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member."); - } - } - - private long lasttime = 0; - @EventHandler(priority = EventPriority.NORMAL) - public void OnPlayerLeave(PlayerQuitEvent event) { - TBMCPlayerBase.quitPlayer(event.getPlayer()); - if (PrimeRestartCommand.isPlsrestart() - && !event.getQuitMessage().equalsIgnoreCase("Server closed") - && !event.getQuitMessage().equalsIgnoreCase("Server is restarting")) { - if (Bukkit.getOnlinePlayers().size() <= 1) { - if (PrimeRestartCommand.isLoud()) - Bukkit.broadcastMessage("§cNobody is online anymore. Restarting."); - Bukkit.spigot().restart(); - } else if (!(event.getPlayer() instanceof IFakePlayer) && System.nanoTime() - 10 * 1000000000L - lasttime > 0) { //Ten seconds passed since last reminder - lasttime = System.nanoTime(); - if (PrimeRestartCommand.isLoud()) - Bukkit.broadcastMessage(ChatColor.DARK_RED + "The server will restart as soon as nobody is online."); - } - } - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onSystemChat(TBMCSystemChatEvent event) { - if (event.isHandled()) - return; // Only handle here if ButtonChat couldn't - Bukkit.getOnlinePlayers().stream().filter(event::shouldSendTo) - .forEach(p -> p.sendMessage(event.getChannel().DisplayName.substring(0, 2) + event.getMessage())); - } +package buttondevteam.core; + +import buttondevteam.lib.TBMCSystemChatEvent; +import buttondevteam.lib.chat.IFakePlayer; +import buttondevteam.lib.player.TBMCPlayerBase; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Statistic; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Date; + +import static buttondevteam.core.MainPlugin.permission; + +public class PlayerListener implements Listener { + + @EventHandler(priority = EventPriority.NORMAL) + public void OnPlayerJoin(PlayerJoinEvent event) { + TBMCPlayerBase.joinPlayer(event.getPlayer()); + if (permission != null && !permission.playerInGroup(event.getPlayer(), "member") + && (new Date(event.getPlayer().getFirstPlayed()).toInstant().plus(7, ChronoUnit.DAYS).isBefore(Instant.now()) + || event.getPlayer().getStatistic(Statistic.PLAY_ONE_TICK) > 20 * 3600 * 12)) { + permission.playerAddGroup(null, event.getPlayer(), "member"); + event.getPlayer().sendMessage("§bYou are a member now. YEEHAW"); + MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member."); + } + } + + private long lasttime = 0; + @EventHandler(priority = EventPriority.NORMAL) + public void OnPlayerLeave(PlayerQuitEvent event) { + TBMCPlayerBase.quitPlayer(event.getPlayer()); + if (PrimeRestartCommand.isPlsrestart() + && !event.getQuitMessage().equalsIgnoreCase("Server closed") + && !event.getQuitMessage().equalsIgnoreCase("Server is restarting")) { + if (Bukkit.getOnlinePlayers().size() <= 1) { + if (PrimeRestartCommand.isLoud()) + Bukkit.broadcastMessage("§cNobody is online anymore. Restarting."); + Bukkit.spigot().restart(); + } else if (!(event.getPlayer() instanceof IFakePlayer) && System.nanoTime() - 10 * 1000000000L - lasttime > 0) { //Ten seconds passed since last reminder + lasttime = System.nanoTime(); + if (PrimeRestartCommand.isLoud()) + Bukkit.broadcastMessage(ChatColor.DARK_RED + "The server will restart as soon as nobody is online."); + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onSystemChat(TBMCSystemChatEvent event) { + if (event.isHandled()) + return; // Only handle here if ButtonChat couldn't + if (Arrays.stream(event.getExceptions()).anyMatch("Minecraft"::equalsIgnoreCase)) + return; + Bukkit.getOnlinePlayers().stream().filter(event::shouldSendTo) + .forEach(p -> p.sendMessage(event.getChannel().DisplayName.substring(0, 2) + event.getMessage())); + } } \ No newline at end of file diff --git a/ButtonCore/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.java b/ButtonCore/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.java index c81c16e..0432054 100755 --- a/ButtonCore/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.java @@ -13,14 +13,16 @@ import org.bukkit.event.HandlerList; */ @Getter public class TBMCSystemChatEvent extends TBMCChatEventBase { + private final String[] exceptions; private boolean handled; public void setHandled() { handled = true; } - public TBMCSystemChatEvent(Channel channel, String message, int score, String groupid) { // TODO: Rich message + public TBMCSystemChatEvent(Channel channel, String message, int score, String groupid, String[] exceptions) { // TODO: Rich message super(channel, message, score, groupid); + this.exceptions = exceptions; } private static final HandlerList handlers = new HandlerList(); diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java index 86d1f10..b08a64f 100755 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java @@ -1,282 +1,283 @@ -package buttondevteam.lib.chat; - -import buttondevteam.core.CommandCaller; -import buttondevteam.core.MainPlugin; -import buttondevteam.lib.TBMCChatEvent; -import buttondevteam.lib.TBMCChatPreprocessEvent; -import buttondevteam.lib.TBMCCoreAPI; -import buttondevteam.lib.TBMCSystemChatEvent; -import buttondevteam.lib.chat.Channel.RecipientTestResult; -import lombok.val; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; -import org.reflections.Reflections; -import org.reflections.scanners.SubTypesScanner; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map.Entry; -import java.util.Set; -import java.util.function.Consumer; - -public class TBMCChatAPI { - - private static final HashMap commands = new HashMap<>(); - - public static HashMap GetCommands() { - return commands; - } - - /** - * Returns messages formatted for Minecraft chat listing the subcommands of the command. - * - * @param command - * The command which we want the subcommands of - * @param sender - * The sender for permissions - * @return The subcommands - */ - public static String[] GetSubCommands(TBMCCommandBase command, CommandSender sender) { - return GetSubCommands(command.GetCommandPath(), sender); - } - - /** - * Returns messages formatted for Minecraft chat listing the subcommands of the command.
- * Returns a header if subcommands were found, otherwise returns an empty array. - * - * @param command - * The command which we want the subcommands of - * @param sender - * The sender for permissions - * @return The subcommands - */ - public static String[] GetSubCommands(String command, CommandSender sender) { - ArrayList cmds = new ArrayList(); - Consumer addToCmds = cmd -> { - if (cmds.size() == 0) - cmds.add("§6---- Subcommands ----"); - cmds.add(cmd); - }; - for (Entry cmd : TBMCChatAPI.GetCommands().entrySet()) { - if (cmd.getKey().startsWith(command + " ")) { - if (cmd.getValue().isPlayerOnly() && !(sender instanceof Player)) - continue; - if (cmd.getValue().isModOnly() && (MainPlugin.permission != null ? !MainPlugin.permission.has(sender, "tbmc.admin") : !sender.isOp())) - continue; - int ind = cmd.getKey().indexOf(' ', command.length() + 2); - if (ind >= 0) { - String newcmd = cmd.getKey().substring(0, ind); - if (!cmds.contains("/" + newcmd)) - addToCmds.accept("/" + newcmd); - } else - addToCmds.accept("/" + cmd.getKey()); - } - } - return cmds.toArray(new String[0]); //Apparently it's faster to use an empty array in modern Java - } - - /** - *

- * This method adds a plugin's commands to help and sets their executor. - *

- *

- *

- * The command classes have to have a constructor each with no parameters - *

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

- *

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

- * - * @param plugin - * The caller plugin - * @param acmdclass - * A command's class to get the package name for commands. The provided class's package and subpackages are scanned for commands. - */ - public static synchronized void AddCommands(JavaPlugin plugin, Class acmdclass) { - plugin.getLogger().info("Registering commands from " + acmdclass.getPackage().getName()); - Reflections rf = new Reflections(new ConfigurationBuilder() - .setUrls(ClasspathHelper.forPackage(acmdclass.getPackage().getName(), - plugin.getClass().getClassLoader())) - .addUrls( - ClasspathHelper.forClass(OptionallyPlayerCommandBase.class, - OptionallyPlayerCommandBase.class.getClassLoader()), - ClasspathHelper.forClass(PlayerCommandBase.class, PlayerCommandBase.class.getClassLoader())) // http://stackoverflow.com/questions/12917417/using-reflections-for-finding-the-transitive-subtypes-of-a-class-when-not-all - .addClassLoader(plugin.getClass().getClassLoader()).addScanners(new SubTypesScanner())); - Set> cmds = rf.getSubTypesOf(TBMCCommandBase.class); - for (Class cmd : cmds) { - try { - if (!cmd.getPackage().getName().startsWith(acmdclass.getPackage().getName())) - continue; // It keeps including the commands from here - if (Modifier.isAbstract(cmd.getModifiers())) - continue; - TBMCCommandBase c = cmd.newInstance(); - c.plugin = plugin; - if (HasNulls(plugin, c)) - continue; - commands.put(c.GetCommandPath(), c); - CommandCaller.RegisterCommand(c); - } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while registering command " + cmd.getName(), e); - } - } - } - - /** - *

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

- *

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

- *

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

- * - * @param plugin - * The caller plugin - * @param thecmdclass - * The command's class to create it (because why let you create the command class) - */ - public static void AddCommand(JavaPlugin plugin, Class thecmdclass, Object... params) { - // plugin.getLogger().info("Registering command " + thecmdclass.getSimpleName() + " for " + plugin.getName()); - try { - TBMCCommandBase c; - if (params.length > 0) - c = thecmdclass.getConstructor(Arrays.stream(params).map(Object::getClass).toArray(Class[]::new)) - .newInstance(params); - else - c = thecmdclass.newInstance(); - c.plugin = plugin; - if (HasNulls(plugin, c)) - return; - commands.put(c.GetCommandPath(), c); - CommandCaller.RegisterCommand(c); - } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while registering command " + thecmdclass.getSimpleName(), e); - } - } - - /** - *

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

- *

- * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a messsage 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 { - cmd.plugin = plugin; - commands.put(cmd.GetCommandPath(), cmd); - CommandCaller.RegisterCommand(cmd); - } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while registering command " + 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; - } - return false; - } - - /** - * Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.
- * This will also send the error message to the sender, if they can't send the message. - * - * @param cm The message to send - * @return The event cancelled state - */ - public static boolean SendChatMessage(ChatMessage cm) { - return SendChatMessage(cm, cm.getUser().channel().get()); - } - - /** - * Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.
- * This will also send the error message to the sender, if they can't send the message. - * - * @param cm The message to send - * @param channel The MC channel to send in - * @return The event cancelled state - */ - public static boolean SendChatMessage(ChatMessage cm, Channel channel) { - if (!Channel.getChannels().contains(channel)) - throw new RuntimeException("Channel " + channel.DisplayName + " not registered!"); - val permcheck = cm.getPermCheck(); - RecipientTestResult rtr = getScoreOrSendError(channel, permcheck); - int score = rtr.score; - if (score == Channel.SCORE_SEND_NOPE || rtr.groupID == null) - return true; - TBMCChatPreprocessEvent eventPre = new TBMCChatPreprocessEvent(cm.getSender(), channel, cm.getMessage()); - Bukkit.getPluginManager().callEvent(eventPre); - if (eventPre.isCancelled()) - return true; - cm.setMessage(eventPre.getMessage()); - TBMCChatEvent event; - event = new TBMCChatEvent(channel, cm, rtr); - Bukkit.getPluginManager().callEvent(event); - return event.isCancelled(); - } - - /** - * Sends a regular message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}. - * - * @param channel - * The channel to send to - * @param rtr - * The score&group to use to find the group - use {@link RecipientTestResult#ALL} if the channel doesn't have scores - * @param message - * The message to send - * @return The event cancelled state - */ - public static boolean SendSystemMessage(Channel channel, RecipientTestResult rtr, String message) { - if (!Channel.getChannels().contains(channel)) - throw new RuntimeException("Channel " + channel.DisplayName + " not registered!"); - TBMCSystemChatEvent event = new TBMCSystemChatEvent(channel, message, rtr.score, rtr.groupID); - Bukkit.getPluginManager().callEvent(event); - return event.isCancelled(); - } - - private static RecipientTestResult getScoreOrSendError(Channel channel, CommandSender sender) { - RecipientTestResult result = channel.getRTR(sender); - if (result.errormessage != null) - sender.sendMessage("§c" + result.errormessage); - return result; - } - - /** - * Register a chat channel. See {@link Channel#Channel(String, Color, String, java.util.function.Function)} for details. - * - * @param channel - * A new {@link Channel} to register - */ - public static void RegisterChatChannel(Channel channel) { - Channel.RegisterChannel(channel); - } -} +package buttondevteam.lib.chat; + +import buttondevteam.core.CommandCaller; +import buttondevteam.core.MainPlugin; +import buttondevteam.lib.TBMCChatEvent; +import buttondevteam.lib.TBMCChatPreprocessEvent; +import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.TBMCSystemChatEvent; +import buttondevteam.lib.chat.Channel.RecipientTestResult; +import lombok.val; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import org.reflections.Reflections; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.Set; +import java.util.function.Consumer; + +public class TBMCChatAPI { + + private static final HashMap commands = new HashMap<>(); + + public static HashMap GetCommands() { + return commands; + } + + /** + * Returns messages formatted for Minecraft chat listing the subcommands of the command. + * + * @param command + * The command which we want the subcommands of + * @param sender + * The sender for permissions + * @return The subcommands + */ + public static String[] GetSubCommands(TBMCCommandBase command, CommandSender sender) { + return GetSubCommands(command.GetCommandPath(), sender); + } + + /** + * Returns messages formatted for Minecraft chat listing the subcommands of the command.
+ * Returns a header if subcommands were found, otherwise returns an empty array. + * + * @param command + * The command which we want the subcommands of + * @param sender + * The sender for permissions + * @return The subcommands + */ + public static String[] GetSubCommands(String command, CommandSender sender) { + ArrayList cmds = new ArrayList(); + Consumer addToCmds = cmd -> { + if (cmds.size() == 0) + cmds.add("§6---- Subcommands ----"); + cmds.add(cmd); + }; + for (Entry cmd : TBMCChatAPI.GetCommands().entrySet()) { + if (cmd.getKey().startsWith(command + " ")) { + if (cmd.getValue().isPlayerOnly() && !(sender instanceof Player)) + continue; + if (cmd.getValue().isModOnly() && (MainPlugin.permission != null ? !MainPlugin.permission.has(sender, "tbmc.admin") : !sender.isOp())) + continue; + int ind = cmd.getKey().indexOf(' ', command.length() + 2); + if (ind >= 0) { + String newcmd = cmd.getKey().substring(0, ind); + if (!cmds.contains("/" + newcmd)) + addToCmds.accept("/" + newcmd); + } else + addToCmds.accept("/" + cmd.getKey()); + } + } + return cmds.toArray(new String[0]); //Apparently it's faster to use an empty array in modern Java + } + + /** + *

+ * This method adds a plugin's commands to help and sets their executor. + *

+ *

+ *

+ * The command classes have to have a constructor each with no parameters + *

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

+ *

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

+ * + * @param plugin + * The caller plugin + * @param acmdclass + * A command's class to get the package name for commands. The provided class's package and subpackages are scanned for commands. + */ + public static synchronized void AddCommands(JavaPlugin plugin, Class acmdclass) { + plugin.getLogger().info("Registering commands from " + acmdclass.getPackage().getName()); + Reflections rf = new Reflections(new ConfigurationBuilder() + .setUrls(ClasspathHelper.forPackage(acmdclass.getPackage().getName(), + plugin.getClass().getClassLoader())) + .addUrls( + ClasspathHelper.forClass(OptionallyPlayerCommandBase.class, + OptionallyPlayerCommandBase.class.getClassLoader()), + ClasspathHelper.forClass(PlayerCommandBase.class, PlayerCommandBase.class.getClassLoader())) // http://stackoverflow.com/questions/12917417/using-reflections-for-finding-the-transitive-subtypes-of-a-class-when-not-all + .addClassLoader(plugin.getClass().getClassLoader()).addScanners(new SubTypesScanner())); + Set> cmds = rf.getSubTypesOf(TBMCCommandBase.class); + for (Class cmd : cmds) { + try { + if (!cmd.getPackage().getName().startsWith(acmdclass.getPackage().getName())) + continue; // It keeps including the commands from here + if (Modifier.isAbstract(cmd.getModifiers())) + continue; + TBMCCommandBase c = cmd.newInstance(); + c.plugin = plugin; + if (HasNulls(plugin, c)) + continue; + commands.put(c.GetCommandPath(), c); + CommandCaller.RegisterCommand(c); + } catch (Exception e) { + TBMCCoreAPI.SendException("An error occured while registering command " + cmd.getName(), e); + } + } + } + + /** + *

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

+ *

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

+ *

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

+ * + * @param plugin + * The caller plugin + * @param thecmdclass + * The command's class to create it (because why let you create the command class) + */ + public static void AddCommand(JavaPlugin plugin, Class thecmdclass, Object... params) { + // plugin.getLogger().info("Registering command " + thecmdclass.getSimpleName() + " for " + plugin.getName()); + try { + TBMCCommandBase c; + if (params.length > 0) + c = thecmdclass.getConstructor(Arrays.stream(params).map(Object::getClass).toArray(Class[]::new)) + .newInstance(params); + else + c = thecmdclass.newInstance(); + c.plugin = plugin; + if (HasNulls(plugin, c)) + return; + commands.put(c.GetCommandPath(), c); + CommandCaller.RegisterCommand(c); + } catch (Exception e) { + TBMCCoreAPI.SendException("An error occured while registering command " + thecmdclass.getSimpleName(), e); + } + } + + /** + *

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

+ *

+ * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a messsage 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 { + cmd.plugin = plugin; + commands.put(cmd.GetCommandPath(), cmd); + CommandCaller.RegisterCommand(cmd); + } catch (Exception e) { + TBMCCoreAPI.SendException("An error occured while registering command " + 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; + } + return false; + } + + /** + * Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.
+ * This will also send the error message to the sender, if they can't send the message. + * + * @param cm The message to send + * @return The event cancelled state + */ + public static boolean SendChatMessage(ChatMessage cm) { + return SendChatMessage(cm, cm.getUser().channel().get()); + } + + /** + * Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.
+ * This will also send the error message to the sender, if they can't send the message. + * + * @param cm The message to send + * @param channel The MC channel to send in + * @return The event cancelled state + */ + public static boolean SendChatMessage(ChatMessage cm, Channel channel) { + if (!Channel.getChannels().contains(channel)) + throw new RuntimeException("Channel " + channel.DisplayName + " not registered!"); + val permcheck = cm.getPermCheck(); + RecipientTestResult rtr = getScoreOrSendError(channel, permcheck); + int score = rtr.score; + if (score == Channel.SCORE_SEND_NOPE || rtr.groupID == null) + return true; + TBMCChatPreprocessEvent eventPre = new TBMCChatPreprocessEvent(cm.getSender(), channel, cm.getMessage()); + Bukkit.getPluginManager().callEvent(eventPre); + if (eventPre.isCancelled()) + return true; + cm.setMessage(eventPre.getMessage()); + TBMCChatEvent event; + event = new TBMCChatEvent(channel, cm, rtr); + Bukkit.getPluginManager().callEvent(event); + return event.isCancelled(); + } + + /** + * Sends a regular message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}. + * + * @param channel + * The channel to send to + * @param rtr + * The score&group to use to find the group - use {@link RecipientTestResult#ALL} if the channel doesn't have scores + * @param message + * The message to send + * @param exceptions Platforms where this message shouldn't be sent (same as {@link ChatMessage#getOrigin()} + * @return The event cancelled state + */ + public static boolean SendSystemMessage(Channel channel, RecipientTestResult rtr, String message, String... exceptions) { + if (!Channel.getChannels().contains(channel)) + throw new RuntimeException("Channel " + channel.DisplayName + " not registered!"); + TBMCSystemChatEvent event = new TBMCSystemChatEvent(channel, message, rtr.score, rtr.groupID, exceptions); + Bukkit.getPluginManager().callEvent(event); + return event.isCancelled(); + } + + private static RecipientTestResult getScoreOrSendError(Channel channel, CommandSender sender) { + RecipientTestResult result = channel.getRTR(sender); + if (result.errormessage != null) + sender.sendMessage("§c" + result.errormessage); + return result; + } + + /** + * Register a chat channel. See {@link Channel#Channel(String, Color, String, java.util.function.Function)} for details. + * + * @param channel + * A new {@link Channel} to register + */ + public static void RegisterChatChannel(Channel channel) { + Channel.RegisterChannel(channel); + } +} From 245f6bbf599783d34797ca84550b62056aa59266 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 10 Jan 2019 01:34:38 +0100 Subject: [PATCH 2/7] Lots of config improvements Removed redundant delegate methods by making the methods non-static Automatically saving config option to the yaml model when it's accessed for the first time Automatically saving yaml config on component/plugin disable Automatically resetting config cache on plugin/component disable Caching the config values so reading is cheaper (it still writes through) Correctly handling (non-)primitive types in configs Allowing to set either a primitive or non-primitive default value and the other is obtained from the provided value #48 --- .idea/misc.xml | 5 +++ .../lib/architecture/ButtonPlugin.java | 33 +++++--------- .../lib/architecture/Component.java | 42 +++++++---------- .../lib/architecture/ConfigData.java | 38 +++++++++++++--- .../lib/architecture/IHaveConfig.java | 45 ++++++++++++++++--- 5 files changed, 103 insertions(+), 60 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index dd45459..6db2058 100755 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,10 @@ + + + + + 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 +} From 1b152d8b4e0cb464f332ceca30d681e152d543a7 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sat, 12 Jan 2019 00:27:55 +0100 Subject: [PATCH 4/7] Put channels in a component Using the per-component AddCommand method CommandComponent got removed, no need for that Made channel properties configurable (DisplayName, Color) Made configs testable, it will only use the cached value in that case This was needed so channel registering continue to work during testing Made channels possible to disable (WIP) #48 --- .idea/inspectionProfiles/Project_Default.xml | 2 +- .../chat => component/channel}/Channel.java | 387 ++++++++++-------- .../component/channel/ChannelComponent.java | 26 ++ .../channel}/ChatChannelRegisterEvent.java | 2 +- .../chat => component/channel}/ChatRoom.java | 4 +- .../component/commands/CommandComponent.java | 15 - .../component/restart/RestartComponent.java | 4 +- .../updater/PluginUpdaterComponent.java | 4 +- .../java/buttondevteam/core/MainPlugin.java | 9 +- .../buttondevteam/core/PlayerListener.java | 2 +- .../java/buttondevteam/core/TestPrepare.java | 5 +- .../java/buttondevteam/lib/TBMCChatEvent.java | 2 +- .../buttondevteam/lib/TBMCChatEventBase.java | 2 +- .../lib/TBMCChatPreprocessEvent.java | 2 +- .../lib/TBMCSystemChatEvent.java | 2 +- .../lib/architecture/Component.java | 29 +- .../lib/architecture/ConfigData.java | 12 +- .../lib/architecture/IHaveConfig.java | 5 + .../buttondevteam/lib/chat/TBMCChatAPI.java | 13 +- .../lib/player/ChannelPlayerData.java | 2 +- .../lib/player/ChromaGamerBase.java | 2 +- 21 files changed, 298 insertions(+), 233 deletions(-) rename ButtonCore/src/main/java/buttondevteam/{lib/chat => component/channel}/Channel.java (77%) create mode 100644 ButtonCore/src/main/java/buttondevteam/component/channel/ChannelComponent.java rename ButtonCore/src/main/java/buttondevteam/{lib/chat => component/channel}/ChatChannelRegisterEvent.java (92%) rename ButtonCore/src/main/java/buttondevteam/{lib/chat => component/channel}/ChatRoom.java (87%) delete mode 100644 ButtonCore/src/main/java/buttondevteam/component/commands/CommandComponent.java diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 4f1aeda..14d4bba 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,7 +1,7 @@