From d12fe961c03e8e608b81714c53429be759277aee Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 22 Nov 2018 01:02:20 +0100 Subject: [PATCH 01/12] No Origins --- pom.xml | 2 +- .../java/buttondevteam/discordplugin/DiscordSenderBase.java | 4 ++-- .../buttondevteam/discordplugin/listeners/MCChatListener.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index f283fc7..c9f7680 100755 --- a/pom.xml +++ b/pom.xml @@ -173,7 +173,7 @@ com.github.TBMCPlugins.ButtonCore ButtonCore - master-SNAPSHOT + ${env.TRAVIS_BRANCH}-SNAPSHOT provided diff --git a/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java b/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java index 14c7fc4..ea2f1a7 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java @@ -1,13 +1,13 @@ package buttondevteam.discordplugin; import buttondevteam.lib.TBMCCoreAPI; -import buttondevteam.lib.chat.IDiscordSender; import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitTask; import sx.blah.discord.handle.obj.IChannel; import sx.blah.discord.handle.obj.IUser; -public abstract class DiscordSenderBase implements IDiscordSender { +public abstract class DiscordSenderBase implements CommandSender { /** * May be null. */ diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java index 4d73c83..5f1792d 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java @@ -81,7 +81,7 @@ public class MCChatListener implements Listener, IListener time = se.getValue(); final String authorPlayer = "[" + DPUtils.sanitizeStringNoEscape(e.getChannel().DisplayName) + "] " // - + (e.getSender() instanceof DiscordSenderBase ? "[D]" : "") // + + ("Minecraft".equals(e.getOrigin()) ? "" : "[" + e.getOrigin() + "]") // + (DPUtils.sanitizeStringNoEscape(e.getSender() instanceof Player // ? ((Player) e.getSender()).getDisplayName() // : e.getSender().getName())); From 9527be99d11d2dea0ece2e7d7a96393e8f307fe5 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 22 Nov 2018 23:11:19 +0100 Subject: [PATCH 02/12] Fixed 122 errors - by fixing the pom Also other fixes --- pom.xml | 18 +++++++++++++++++- .../discordplugin/DiscordSenderBase.java | 1 + .../listeners/MCChatListener.java | 4 ++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index c9f7680..030db19 100755 --- a/pom.xml +++ b/pom.xml @@ -106,6 +106,7 @@ UTF-8 + master @@ -173,7 +174,7 @@ com.github.TBMCPlugins.ButtonCore ButtonCore - ${env.TRAVIS_BRANCH}-SNAPSHOT + ${branch}-SNAPSHOT provided @@ -225,4 +226,19 @@ 4.0.0 + + + + ci + + + env.TRAVIS_BRANCH + + + + + ${env.TRAVIS_BRANCH} + + + diff --git a/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java b/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java index ea2f1a7..b031bcb 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java @@ -51,6 +51,7 @@ public abstract class DiscordSenderBase implements CommandSender { public void sendMessage(String message) { try { final boolean broadcast = new Exception().getStackTrace()[2].getMethodName().contains("broadcast"); + //if (broadcast && DiscordPlugin.hooked) - TODO: What should happen if unhooked if (broadcast) return; final String sendmsg = DPUtils.sanitizeString(message); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java index 5f1792d..98a0b75 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java @@ -39,8 +39,8 @@ import sx.blah.discord.util.MissingPermissionsException; import javax.annotation.Nullable; import java.awt.*; import java.time.Instant; -import java.util.*; import java.util.List; +import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; @@ -81,7 +81,7 @@ public class MCChatListener implements Listener, IListener time = se.getValue(); final String authorPlayer = "[" + DPUtils.sanitizeStringNoEscape(e.getChannel().DisplayName) + "] " // - + ("Minecraft".equals(e.getOrigin()) ? "" : "[" + e.getOrigin() + "]") // + + ("Minecraft".equals(e.getOrigin()) ? "" : "[" + e.getOrigin().substring(0, 1) + "]") // + (DPUtils.sanitizeStringNoEscape(e.getSender() instanceof Player // ? ((Player) e.getSender()).getDisplayName() // : e.getSender().getName())); From 38b45299c0fa6679315df6d63e4a406842de3fa9 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Fri, 14 Dec 2018 23:58:24 +0100 Subject: [PATCH 03/12] Adding two modules GeneralEventBroadcaster Minecraft chat #51 --- .../discordplugin/DiscordPlugin.java | 32 ++------- .../GeneralEventBroadcasterModule.java | 34 +++++++++ .../{ => broadcaster}/PlayerListWatcher.java | 71 ++++++++----------- .../discordplugin/commands/DebugCommand.java | 4 +- .../commands/DiscordCommandBase.java | 2 +- ...mandListener.java => CommonListeners.java} | 4 +- .../listeners/MCChatListener.java | 17 +++-- .../mcchat/MinecraftChatModule.java | 20 ++++++ 8 files changed, 107 insertions(+), 77 deletions(-) create mode 100644 src/main/java/buttondevteam/discordplugin/broadcaster/GeneralEventBroadcasterModule.java rename src/main/java/buttondevteam/discordplugin/{ => broadcaster}/PlayerListWatcher.java (82%) rename src/main/java/buttondevteam/discordplugin/listeners/{CommandListener.java => CommonListeners.java} (97%) create mode 100644 src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index be7e8a9..e486a5d 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -1,13 +1,16 @@ package buttondevteam.discordplugin; +import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule; import buttondevteam.discordplugin.commands.DiscordCommandBase; -import buttondevteam.discordplugin.listeners.CommandListener; +import buttondevteam.discordplugin.listeners.CommonListeners; import buttondevteam.discordplugin.listeners.ExceptionListener; import buttondevteam.discordplugin.listeners.MCChatListener; import buttondevteam.discordplugin.listeners.MCListener; +import buttondevteam.discordplugin.mcchat.MinecraftChatModule; import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase; import buttondevteam.discordplugin.mccommands.ResetMCCommand; import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.architecture.Component; import buttondevteam.lib.chat.Channel; import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.player.ChromaGamerBase; @@ -51,22 +54,12 @@ public class DiscordPlugin extends JavaPlugin implements IListener { public static DiscordPlugin plugin; public static boolean SafeMode = true; public static List GameRoles; - public static boolean hooked = false; - @SuppressWarnings("unchecked") @Override public void onEnable() { stop = false; //If not the first time try { Bukkit.getLogger().info("Initializing DiscordPlugin..."); - try { - PlayerListWatcher.hookUp(); - hooked = true; - Bukkit.getLogger().info("Finished hooking into the player list"); - } catch (Throwable e) { - e.printStackTrace(); - Bukkit.getLogger().warning("Couldn't hook into the player list!"); - } plugin = this; lastannouncementtime = getConfig().getLong("lastannouncementtime"); lastseentime = getConfig().getLong("lastseentime"); @@ -212,11 +205,10 @@ public class DiscordPlugin extends JavaPlugin implements IListener { }*/ } }, 0, 10); - for (IListener listener : CommandListener.getListeners()) + for (IListener listener : CommonListeners.getListeners()) dc.getDispatcher().registerListener(listener); - MCChatListener mcchat = new MCChatListener(); - dc.getDispatcher().registerListener(mcchat); - TBMCCoreAPI.RegisterEventsForExceptions(mcchat, this); + Component.registerComponent(this, new GeneralEventBroadcasterModule()); + Component.registerComponent(this, new MinecraftChatModule()); Bukkit.getPluginManager().registerEvents(new ExceptionListener(), this); TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this); TBMCChatAPI.AddCommands(this, DiscordMCCommandBase.class); @@ -299,16 +291,6 @@ public class DiscordPlugin extends JavaPlugin implements IListener { try { SafeMode = true; // Stop interacting with Discord MCChatListener.stop(true); - try { - if (PlayerListWatcher.hookDown()) - System.out.println("Finished unhooking the player list!"); - else - System.out.println("Didn't have the player list hooked."); - hooked = false; - } catch (Throwable e) { - e.printStackTrace(); - Bukkit.getLogger().warning("Couldn't unhook the player list!"); - } ChromaBot.delete(); dc.changePresence(StatusType.IDLE, ActivityType.PLAYING, "Chromacraft"); //No longer using the same account for testing dc.logout(); diff --git a/src/main/java/buttondevteam/discordplugin/broadcaster/GeneralEventBroadcasterModule.java b/src/main/java/buttondevteam/discordplugin/broadcaster/GeneralEventBroadcasterModule.java new file mode 100644 index 0000000..471a56f --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/broadcaster/GeneralEventBroadcasterModule.java @@ -0,0 +1,34 @@ +package buttondevteam.discordplugin.broadcaster; + +import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.architecture.Component; +import lombok.Getter; +import org.bukkit.Bukkit; + +public class GeneralEventBroadcasterModule extends Component { + private static @Getter boolean hooked = false; + + @Override + protected void enable() { + try { + PlayerListWatcher.hookUp(); + Bukkit.getLogger().info("Finished hooking into the player list"); + hooked = true; + } catch (Exception e) { + TBMCCoreAPI.SendException("Error while hacking the player list!", e); + } + } + + @Override + protected void disable() { + try { + if (PlayerListWatcher.hookDown()) + System.out.println("Finished unhooking the player list!"); + else + System.out.println("Didn't have the player list hooked."); + hooked = false; + } catch (Exception e) { + TBMCCoreAPI.SendException("Error while hacking the player list!", e); + } + } +} diff --git a/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java b/src/main/java/buttondevteam/discordplugin/broadcaster/PlayerListWatcher.java similarity index 82% rename from src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java rename to src/main/java/buttondevteam/discordplugin/broadcaster/PlayerListWatcher.java index 432b75c..1eb9a42 100755 --- a/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java +++ b/src/main/java/buttondevteam/discordplugin/broadcaster/PlayerListWatcher.java @@ -1,4 +1,4 @@ -package buttondevteam.discordplugin; +package buttondevteam.discordplugin.broadcaster; import buttondevteam.discordplugin.listeners.MCChatListener; import buttondevteam.lib.TBMCCoreAPI; @@ -53,52 +53,43 @@ public class PlayerListWatcher extends DedicatedPlayerList { } @Override - public void sendMessage(IChatBaseComponent[] iChatBaseComponents) { // Needed so it calls the overriden method + public void sendMessage(IChatBaseComponent[] iChatBaseComponents) { // Needed so it calls the overridden method for (IChatBaseComponent component : iChatBaseComponents) { sendMessage(component, true); } } - public static void hookUp() { - try { - Field conf = CraftServer.class.getDeclaredField("console"); - conf.setAccessible(true); - val server = (MinecraftServer) conf.get(Bukkit.getServer()); - val plw = new ObjenesisStd().newInstance(PlayerListWatcher.class); // Cannot call super constructor - plw.plist = (DedicatedPlayerList) server.getPlayerList(); - plw.maxPlayers = plw.plist.getMaxPlayers(); - Field plf = plw.getClass().getField("players"); - plf.setAccessible(true); - Field modf = plf.getClass().getDeclaredField("modifiers"); - modf.setAccessible(true); - modf.set(plf, plf.getModifiers() & ~Modifier.FINAL); - plf.set(plw, plw.plist.players); - server.a(plw); - Field pllf = CraftServer.class.getDeclaredField("playerList"); - pllf.setAccessible(true); - pllf.set(Bukkit.getServer(), plw); - } catch (Exception e) { - TBMCCoreAPI.SendException("Error while hacking the player list!", e); - } + static void hookUp() throws Exception { + Field conf = CraftServer.class.getDeclaredField("console"); + conf.setAccessible(true); + val server = (MinecraftServer) conf.get(Bukkit.getServer()); + val plw = new ObjenesisStd().newInstance(PlayerListWatcher.class); // Cannot call super constructor + plw.plist = (DedicatedPlayerList) server.getPlayerList(); + plw.maxPlayers = plw.plist.getMaxPlayers(); + Field plf = plw.getClass().getField("players"); + plf.setAccessible(true); + Field modf = plf.getClass().getDeclaredField("modifiers"); + modf.setAccessible(true); + modf.set(plf, plf.getModifiers() & ~Modifier.FINAL); + plf.set(plw, plw.plist.players); + server.a(plw); + Field pllf = CraftServer.class.getDeclaredField("playerList"); + pllf.setAccessible(true); + pllf.set(Bukkit.getServer(), plw); } - public static boolean hookDown() { - try { - Field conf = CraftServer.class.getDeclaredField("console"); - conf.setAccessible(true); - val server = (MinecraftServer) conf.get(Bukkit.getServer()); - val plist = (DedicatedPlayerList) server.getPlayerList(); - if (!(plist instanceof PlayerListWatcher)) - return false; - server.a(((PlayerListWatcher) plist).plist); - Field pllf = CraftServer.class.getDeclaredField("playerList"); - pllf.setAccessible(true); - pllf.set(Bukkit.getServer(), ((PlayerListWatcher) plist).plist); - return true; - } catch (Exception e) { - TBMCCoreAPI.SendException("Error while hacking the player list!", e); - return true; - } + static boolean hookDown() throws Exception { + Field conf = CraftServer.class.getDeclaredField("console"); + conf.setAccessible(true); + val server = (MinecraftServer) conf.get(Bukkit.getServer()); + val plist = (DedicatedPlayerList) server.getPlayerList(); + if (!(plist instanceof PlayerListWatcher)) + return false; + server.a(((PlayerListWatcher) plist).plist); + Field pllf = CraftServer.class.getDeclaredField("playerList"); + pllf.setAccessible(true); + pllf.set(Bukkit.getServer(), ((PlayerListWatcher) plist).plist); + return true; } public void a(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) { diff --git a/src/main/java/buttondevteam/discordplugin/commands/DebugCommand.java b/src/main/java/buttondevteam/discordplugin/commands/DebugCommand.java index 1b6a605..b37e2b8 100644 --- a/src/main/java/buttondevteam/discordplugin/commands/DebugCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/DebugCommand.java @@ -1,7 +1,7 @@ package buttondevteam.discordplugin.commands; import buttondevteam.discordplugin.DiscordPlugin; -import buttondevteam.discordplugin.listeners.CommandListener; +import buttondevteam.discordplugin.listeners.CommonListeners; import sx.blah.discord.handle.obj.IMessage; public class DebugCommand extends DiscordCommandBase { @@ -13,7 +13,7 @@ public class DebugCommand extends DiscordCommandBase { @Override public boolean run(IMessage message, String args) { if (message.getAuthor().hasRole(DiscordPlugin.mainServer.getRoleByID(126030201472811008L))) - message.reply("Debug " + (CommandListener.debug() ? "enabled" : "disabled")); + message.reply("Debug " + (CommonListeners.debug() ? "enabled" : "disabled")); else message.reply("You need to be a moderator to use this command."); return true; diff --git a/src/main/java/buttondevteam/discordplugin/commands/DiscordCommandBase.java b/src/main/java/buttondevteam/discordplugin/commands/DiscordCommandBase.java index 34790b6..a4da021 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/DiscordCommandBase.java +++ b/src/main/java/buttondevteam/discordplugin/commands/DiscordCommandBase.java @@ -8,7 +8,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.stream.Collectors; -import static buttondevteam.discordplugin.listeners.CommandListener.debug; +import static buttondevteam.discordplugin.listeners.CommonListeners.debug; public abstract class DiscordCommandBase { public abstract String getCommandName(); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java similarity index 97% rename from src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java rename to src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java index f46abff..ba5b6e0 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java @@ -23,7 +23,7 @@ import java.util.Calendar; import java.util.Random; import java.util.concurrent.TimeUnit; -public class CommandListener { +public class CommonListeners { private static final String[] serverReadyStrings = new String[]{"In one week from now", // Ali "Between now and the heat-death of the universe.", // Ghostise @@ -200,7 +200,7 @@ public class CommandListener { private static boolean debug = false; public static void debug(String debug) { - if (CommandListener.debug) //Debug + if (CommonListeners.debug) //Debug System.out.println(debug); } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java index 98a0b75..0860efd 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java @@ -1,6 +1,9 @@ package buttondevteam.discordplugin.listeners; +import buttondevteam.core.ComponentManager; import buttondevteam.discordplugin.*; +import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule; +import buttondevteam.discordplugin.mcchat.MinecraftChatModule; import buttondevteam.discordplugin.playerfaker.VanillaCommandListener; import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatPreprocessEvent; @@ -58,7 +61,7 @@ public class MCChatListener implements Listener, IListener @EventHandler // Minecraft public void onMCChat(TBMCChatEvent ev) { - if (DiscordPlugin.SafeMode || ev.isCancelled()) //SafeMode: Needed so it doesn't restart after server shutdown + if (!ComponentManager.isEnabled(MinecraftChatModule.class) || ev.isCancelled()) //SafeMode: Needed so it doesn't restart after server shutdown return; sendevents.add(new AbstractMap.SimpleEntry<>(ev, Instant.now())); if (sendtask != null) @@ -368,7 +371,7 @@ public class MCChatListener implements Listener, IListener * @param hookmsg Whether the message is also sent from the hook */ public static void forCustomAndAllMCChat(Consumer action, @Nullable ChannelconBroadcast toggle, boolean hookmsg) { - if (!DiscordPlugin.hooked || !hookmsg) + if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg) forAllMCChat(action); final Consumer customLMDConsumer = cc -> action.accept(cc.channel); if (toggle == null) @@ -404,7 +407,7 @@ public class MCChatListener implements Listener, IListener * @param hookmsg Whether the message is also sent from the hook */ public static void forAllowedCustomAndAllMCChat(Consumer action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle, boolean hookmsg) { - if (!DiscordPlugin.hooked || !hookmsg) + if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg) forAllMCChat(action); forAllowedCustomMCChat(action, sender, toggle); } @@ -463,9 +466,9 @@ public class MCChatListener implements Listener, IListener private Runnable recrun; private static Thread recthread; - @Override // Discord + @Override // Discord - TODO: Call from the common listener public void handle(MessageReceivedEvent ev) { - if (DiscordPlugin.SafeMode) + if (!ComponentManager.isEnabled(MinecraftChatModule.class)) return; val author = ev.getMessage().getAuthor(); if (author.isBot()) @@ -476,8 +479,8 @@ public class MCChatListener implements Listener, IListener && !hasCustomChat) return; if (ev.getMessage().getContent().equalsIgnoreCase("mcchat")) - return; // Race condition: If it gets here after it enabled mcchat it says it - I might as well allow disabling with this (CommandListener) - if (CommandListener.runCommand(ev.getMessage(), true)) + return; // Race condition: If it gets here after it enabled mcchat it says it - I might as well allow disabling with this (CommonListeners) + if (CommonListeners.runCommand(ev.getMessage(), true)) return; resetLastMessage(ev.getChannel()); lastlist++; diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java new file mode 100644 index 0000000..709b055 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java @@ -0,0 +1,20 @@ +package buttondevteam.discordplugin.mcchat; + +import buttondevteam.discordplugin.DiscordPlugin; +import buttondevteam.discordplugin.listeners.MCChatListener; +import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.architecture.Component; + +public class MinecraftChatModule extends Component { + @Override + protected void enable() { + MCChatListener mcchat = new MCChatListener(); + DiscordPlugin.dc.getDispatcher().registerListener(mcchat); + TBMCCoreAPI.RegisterEventsForExceptions(mcchat, getPlugin()); + } + + @Override + protected void disable() { + //These get undone if restarting/resetting - it will ignore events if disabled + } //TODO: Use ComponentManager.isEnabled() at other places too, instead of SafeMode +} From 1878a46041c57d01606720ee769050295ef9b8f5 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 17 Dec 2018 21:33:55 +0100 Subject: [PATCH 04/12] Cleanup, organizing (MCChatListener) Removed all sysouts Split MCChatListener into utils, private and custom (and the existing one) Using fixed version of Discord4J (fixes issues with local testing) --- pom.xml | 19 +- .../discordplugin/ChromaBot.java | 16 +- .../buttondevteam/discordplugin/DPUtils.java | 7 + .../discordplugin/DiscordPlayer.java | 6 +- .../discordplugin/DiscordPlugin.java | 24 +- .../GeneralEventBroadcasterModule.java | 5 +- .../broadcaster/PlayerListWatcher.java | 4 +- .../commands/ChannelconCommand.java | 10 +- .../discordplugin/commands/MCChatCommand.java | 4 +- .../listeners/CommonListeners.java | 9 +- .../discordplugin/listeners/MCListener.java | 27 +- .../discordplugin/mcchat/MCChatCustom.java | 59 ++++ .../{listeners => mcchat}/MCChatListener.java | 313 ++---------------- .../discordplugin/mcchat/MCChatPrivate.java | 55 +++ .../discordplugin/mcchat/MCChatUtils.java | 182 ++++++++++ .../mcchat/MinecraftChatModule.java | 1 - .../mccommands/AcceptMCCommand.java | 4 +- 17 files changed, 402 insertions(+), 343 deletions(-) create mode 100644 src/main/java/buttondevteam/discordplugin/mcchat/MCChatCustom.java rename src/main/java/buttondevteam/discordplugin/{listeners => mcchat}/MCChatListener.java (60%) create mode 100644 src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java create mode 100644 src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java diff --git a/pom.xml b/pom.xml index 030db19..0ccfe46 100755 --- a/pom.xml +++ b/pom.xml @@ -106,7 +106,9 @@ UTF-8 - master + + master + @@ -160,11 +162,16 @@ provided - - com.discord4j - Discord4J - 2.10.1 - + + + com.github.SizableShrimp + Discord4J + httprequestchange-SNAPSHOT + org.slf4j diff --git a/src/main/java/buttondevteam/discordplugin/ChromaBot.java b/src/main/java/buttondevteam/discordplugin/ChromaBot.java index 79a0514..90e5afb 100755 --- a/src/main/java/buttondevteam/discordplugin/ChromaBot.java +++ b/src/main/java/buttondevteam/discordplugin/ChromaBot.java @@ -1,6 +1,6 @@ package buttondevteam.discordplugin; -import buttondevteam.discordplugin.listeners.MCChatListener; +import buttondevteam.discordplugin.mcchat.MCChatUtils; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -43,7 +43,7 @@ public class ChromaBot { * The message to send, duh */ public void sendMessage(String message) { - MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message)); + MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message)); } /** @@ -55,7 +55,7 @@ public class ChromaBot { * Custom fancy stuff, use {@link EmbedBuilder} to create one */ public void sendMessage(String message, EmbedObject embed) { - MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, embed)); + MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, embed)); } /** @@ -66,7 +66,7 @@ public class ChromaBot { * @param toggle The toggle type for channelcon */ public void sendMessageCustomAsWell(String message, EmbedObject embed, @Nullable ChannelconBroadcast toggle) { - MCChatListener.forCustomAndAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, embed), toggle, false); + MCChatUtils.forCustomAndAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, embed), toggle, false); } /** @@ -92,7 +92,7 @@ public class ChromaBot { * The color of the line before the text */ public void sendMessage(String message, Color color) { - MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, + MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, new EmbedBuilder().withTitle(message).withColor(color).build())); } @@ -107,7 +107,7 @@ public class ChromaBot { * The name of the Minecraft player who is the author of this message */ public void sendMessage(String message, Color color, String mcauthor) { - MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, + MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, DPUtils.embedWithHead(new EmbedBuilder().withTitle(message).withColor(color), mcauthor).build())); } @@ -124,7 +124,7 @@ public class ChromaBot { * The URL of the avatar image for this message's author */ public void sendMessage(String message, Color color, String authorname, String authorimg) { - MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, new EmbedBuilder() + MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, new EmbedBuilder() .withTitle(message).withColor(color).withAuthorName(authorname).withAuthorIcon(authorimg).build())); } @@ -139,7 +139,7 @@ public class ChromaBot { * The player who sends this message */ public void sendMessage(String message, Color color, Player sender) { - MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, DPUtils + MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, DPUtils .embedWithHead(new EmbedBuilder().withTitle(message).withColor(color), sender.getName()).build())); } diff --git a/src/main/java/buttondevteam/discordplugin/DPUtils.java b/src/main/java/buttondevteam/discordplugin/DPUtils.java index ea4d14d..f68053a 100755 --- a/src/main/java/buttondevteam/discordplugin/DPUtils.java +++ b/src/main/java/buttondevteam/discordplugin/DPUtils.java @@ -9,6 +9,7 @@ import sx.blah.discord.util.RequestBuffer.IVoidRequest; import javax.annotation.Nullable; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.logging.Logger; import java.util.regex.Matcher; public final class DPUtils { @@ -96,4 +97,10 @@ public final class DPUtils { return message.replaceAll("([*_~])", Matcher.quoteReplacement("\\")+"$1"); } + public static Logger getLogger() { + if (DiscordPlugin.plugin == null || DiscordPlugin.plugin.getLogger() == null) + return Logger.getLogger("DiscordPlugin"); + return DiscordPlugin.plugin.getLogger(); + } + } diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlayer.java b/src/main/java/buttondevteam/discordplugin/DiscordPlayer.java index ec7863c..0055792 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlayer.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlayer.java @@ -1,6 +1,6 @@ package buttondevteam.discordplugin; -import buttondevteam.discordplugin.listeners.MCChatListener; +import buttondevteam.discordplugin.mcchat.MCChatPrivate; import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.player.UserClass; @@ -20,9 +20,9 @@ public class DiscordPlayer extends ChromaGamerBase { /** * Returns true if player has the private Minecraft chat enabled. For setting the value, see - * {@link MCChatListener#privateMCChat(sx.blah.discord.handle.obj.IChannel, boolean, sx.blah.discord.handle.obj.IUser, DiscordPlayer)} + * {@link MCChatPrivate#privateMCChat(sx.blah.discord.handle.obj.IChannel, boolean, sx.blah.discord.handle.obj.IUser, DiscordPlayer)} */ public boolean isMinecraftChatEnabled() { - return MCChatListener.isMinecraftChatEnabled(this); + return MCChatPrivate.isMinecraftChatEnabled(this); } } diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index e486a5d..02709d1 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -4,8 +4,10 @@ import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule; import buttondevteam.discordplugin.commands.DiscordCommandBase; import buttondevteam.discordplugin.listeners.CommonListeners; import buttondevteam.discordplugin.listeners.ExceptionListener; -import buttondevteam.discordplugin.listeners.MCChatListener; import buttondevteam.discordplugin.listeners.MCListener; +import buttondevteam.discordplugin.mcchat.MCChatCustom; +import buttondevteam.discordplugin.mcchat.MCChatListener; +import buttondevteam.discordplugin.mcchat.MCChatUtils; import buttondevteam.discordplugin.mcchat.MinecraftChatModule; import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase; import buttondevteam.discordplugin.mccommands.ResetMCCommand; @@ -149,7 +151,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { val toggles = chcon.getInt("toggles"); if (!mcch.isPresent() || ch == null || user == null || groupid == null) continue; - MCChatListener.addCustomChat(ch, groupid, mcch.get(), user, dcp, toggles); + MCChatCustom.addCustomChat(ch, groupid, mcch.get(), user, dcp, toggles); } } @@ -213,12 +215,8 @@ public class DiscordPlugin extends JavaPlugin implements IListener { TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this); TBMCChatAPI.AddCommands(this, DiscordMCCommandBase.class); TBMCCoreAPI.RegisterUserClass(DiscordPlayer.class); - ChromaGamerBase.addConverter(sender -> { - //System.out.println("Discord converter queried: "+sender+" "+sender.getName()); - TODO: Remove - //System.out.println(((DiscordSenderBase) sender).getChromaUser().channel().get().ID); //TODO: TMP - return Optional.ofNullable(sender instanceof DiscordSenderBase - ? ((DiscordSenderBase) sender).getChromaUser() : null); - }); + ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof DiscordSenderBase + ? ((DiscordSenderBase) sender).getChromaUser() : null)); new Thread(this::AnnouncementGetterThreadMethod).start(); setupProviders(); } catch (Exception e) { @@ -242,15 +240,15 @@ public class DiscordPlugin extends JavaPlugin implements IListener { @Override public void onDisable() { stop = true; - for (val entry : MCChatListener.ConnectedSenders.entrySet()) + for (val entry : MCChatUtils.ConnectedSenders.entrySet()) for (val valueEntry : entry.getValue().entrySet()) MCListener.callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); - MCChatListener.ConnectedSenders.clear(); + MCChatUtils.ConnectedSenders.clear(); getConfig().set("lastannouncementtime", lastannouncementtime); getConfig().set("lastseentime", lastseentime); getConfig().set("serverup", false); - val chcons = MCChatListener.getCustomChats(); + val chcons = MCChatCustom.getCustomChats(); val chconsc = getConfig().createSection("chcons"); for (val chcon : chcons) { val chconc = chconsc.createSection(chcon.channel.getStringID()); @@ -279,7 +277,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { + "kicked the hell out.") //TODO: Make configurable : "") //If 'restart' is disabled then this isn't shown even if joinleave is enabled .build(); - MCChatListener.forCustomAndAllMCChat(ch -> { + MCChatUtils.forCustomAndAllMCChat(ch -> { try { DiscordPlugin.sendMessageToChannelWait(ch, "", embed, 5, TimeUnit.SECONDS); @@ -406,7 +404,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { .warning("Message was too long to send to discord and got truncated. In " + channel.getName()); } try { - MCChatListener.resetLastMessage(channel); // If this is a chat message, it'll be set again + MCChatUtils.resetLastMessage(channel); // If this is a chat message, it'll be set again final String content = message; RequestBuffer.IRequest r = () -> embed == null ? channel.sendMessage(content) : channel.sendMessage(content, embed, false); diff --git a/src/main/java/buttondevteam/discordplugin/broadcaster/GeneralEventBroadcasterModule.java b/src/main/java/buttondevteam/discordplugin/broadcaster/GeneralEventBroadcasterModule.java index 471a56f..8830f37 100644 --- a/src/main/java/buttondevteam/discordplugin/broadcaster/GeneralEventBroadcasterModule.java +++ b/src/main/java/buttondevteam/discordplugin/broadcaster/GeneralEventBroadcasterModule.java @@ -1,5 +1,6 @@ package buttondevteam.discordplugin.broadcaster; +import buttondevteam.discordplugin.DPUtils; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.Component; import lombok.Getter; @@ -23,9 +24,9 @@ public class GeneralEventBroadcasterModule extends Component { protected void disable() { try { if (PlayerListWatcher.hookDown()) - System.out.println("Finished unhooking the player list!"); + DPUtils.getLogger().info("Finished unhooking the player list!"); else - System.out.println("Didn't have the player list hooked."); + DPUtils.getLogger().info("Didn't have the player list hooked."); hooked = false; } catch (Exception e) { TBMCCoreAPI.SendException("Error while hacking the player list!", e); diff --git a/src/main/java/buttondevteam/discordplugin/broadcaster/PlayerListWatcher.java b/src/main/java/buttondevteam/discordplugin/broadcaster/PlayerListWatcher.java index 1eb9a42..eafe7f5 100755 --- a/src/main/java/buttondevteam/discordplugin/broadcaster/PlayerListWatcher.java +++ b/src/main/java/buttondevteam/discordplugin/broadcaster/PlayerListWatcher.java @@ -1,6 +1,6 @@ package buttondevteam.discordplugin.broadcaster; -import buttondevteam.discordplugin.listeners.MCChatListener; +import buttondevteam.discordplugin.mcchat.MCChatUtils; import buttondevteam.lib.TBMCCoreAPI; import com.mojang.authlib.GameProfile; import lombok.val; @@ -30,7 +30,7 @@ public class PlayerListWatcher extends DedicatedPlayerList { if (packet instanceof PacketPlayOutChat) { Field msgf = PacketPlayOutChat.class.getDeclaredField("a"); msgf.setAccessible(true); - MCChatListener.forAllMCChat(MCChatListener.send(((IChatBaseComponent) msgf.get(packet)).toPlainText())); + MCChatUtils.forAllMCChat(MCChatUtils.send(((IChatBaseComponent) msgf.get(packet)).toPlainText())); } } catch (Exception e) { TBMCCoreAPI.SendException("Failed to broadcast message sent to all players - hacking failed.", e); diff --git a/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java b/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java index 73eefd1..a018a1e 100644 --- a/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java @@ -3,7 +3,7 @@ package buttondevteam.discordplugin.commands; import buttondevteam.discordplugin.ChannelconBroadcast; import buttondevteam.discordplugin.DiscordConnectedPlayer; import buttondevteam.discordplugin.DiscordPlayer; -import buttondevteam.discordplugin.listeners.MCChatListener; +import buttondevteam.discordplugin.mcchat.MCChatCustom; import buttondevteam.lib.chat.Channel; import buttondevteam.lib.player.TBMCPlayer; import lombok.val; @@ -30,16 +30,16 @@ public class ChannelconCommand extends DiscordCommandBase { message.reply("you need to have manage permissions for this channel!"); return true; } - if (MCChatListener.hasCustomChat(message.getChannel())) { + if (MCChatCustom.hasCustomChat(message.getChannel())) { if (args.toLowerCase().startsWith("remove")) { - if (MCChatListener.removeCustomChat(message.getChannel())) + if (MCChatCustom.removeCustomChat(message.getChannel())) message.reply("channel connection removed."); else message.reply("wait what, couldn't remove channel connection."); return true; } if (args.toLowerCase().startsWith("toggle")) { - val cc = MCChatListener.getCustomChat(message.getChannel()); + val cc = MCChatCustom.getCustomChat(message.getChannel()); Supplier togglesString = () -> Arrays.stream(ChannelconBroadcast.values()).map(t -> t.toString().toLowerCase() + ": " + ((cc.toggles & t.flag) == 0 ? "disabled" : "enabled")).collect(Collectors.joining("\n")); String[] argsa = args.split(" "); if (argsa.length < 2) { @@ -88,7 +88,7 @@ public class ChannelconCommand extends DiscordCommandBase { message.reply("sorry, this MC chat is already connected to a different channel, multiple channels are not supported atm."); return true; }*/ //TODO: "Channel admins" that can connect channels? - MCChatListener.addCustomChat(message.getChannel(), groupid, chan.get(), message.getAuthor(), dcp, 0); + MCChatCustom.addCustomChat(message.getChannel(), groupid, chan.get(), message.getAuthor(), dcp, 0); message.reply("alright, connection made to group `" + groupid + "`!"); return true; } diff --git a/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java b/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java index e2ca2ca..7a5b7c8 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java @@ -2,7 +2,7 @@ package buttondevteam.discordplugin.commands; import buttondevteam.discordplugin.DiscordPlayer; import buttondevteam.discordplugin.DiscordPlugin; -import buttondevteam.discordplugin.listeners.MCChatListener; +import buttondevteam.discordplugin.mcchat.MCChatPrivate; import buttondevteam.lib.TBMCCoreAPI; import sx.blah.discord.handle.obj.IMessage; @@ -22,7 +22,7 @@ public class MCChatCommand extends DiscordCommandBase { } try (final DiscordPlayer user = DiscordPlayer.getUser(message.getAuthor().getStringID(), DiscordPlayer.class)) { boolean mcchat = !user.isMinecraftChatEnabled(); - MCChatListener.privateMCChat(message.getChannel(), mcchat, message.getAuthor(), user); + MCChatPrivate.privateMCChat(message.getChannel(), mcchat, message.getAuthor(), user); DiscordPlugin.sendMessageToChannel(message.getChannel(), "Minecraft chat " + (mcchat // ? "enabled. Use '/mcchat' again to turn it off." // diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java index ba5b6e0..737e5cf 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java @@ -1,7 +1,10 @@ package buttondevteam.discordplugin.listeners; +import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.commands.DiscordCommandBase; +import buttondevteam.discordplugin.mcchat.MCChatCustom; +import buttondevteam.discordplugin.mcchat.MCChatPrivate; import buttondevteam.lib.TBMCCoreAPI; import lombok.val; import org.bukkit.Bukkit; @@ -72,7 +75,7 @@ public class CommonListeners { return; final IChannel channel = event.getMessage().getChannel(); if (!channel.getStringID().equals(DiscordPlugin.botchannel.getStringID()) - && (!event.getMessage().getContent().contains("channelcon") || MCChatListener.hasCustomChat(channel))) //Allow channelcon in other servers but avoid double handling when it's enabled + && (!event.getMessage().getContent().contains("channelcon") || MCChatCustom.hasCustomChat(channel))) //Allow channelcon in other servers but avoid double handling when it's enabled return; if (channel.getStringID().equals(DiscordPlugin.chatchannel.getStringID())) return; // The chat code already handles this - Right now while testing botchannel is the same as chatchannel @@ -98,7 +101,7 @@ public class CommonListeners { && !(event.getMessage().getContent().startsWith("/") && event.getChannel().getStringID().equals(DiscordPlugin.botchannel.getStringID()))) // return; - if (MCChatListener.isMinecraftChatEnabled(event.getAuthor().toString())) + if (MCChatPrivate.isMinecraftChatEnabled(event.getAuthor().toString())) if (!event.getMessage().getContent().equalsIgnoreCase("mcchat")) return; if (event.getMessage().getAuthor().isBot()) @@ -201,7 +204,7 @@ public class CommonListeners { public static void debug(String debug) { if (CommonListeners.debug) //Debug - System.out.println(debug); + DPUtils.getLogger().info(debug); } public static boolean debug() { diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java index 6f9b3c9..cd8a826 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java @@ -2,6 +2,8 @@ package buttondevteam.discordplugin.listeners; import buttondevteam.discordplugin.*; import buttondevteam.discordplugin.commands.ConnectCommand; +import buttondevteam.discordplugin.mcchat.MCChatListener; +import buttondevteam.discordplugin.mcchat.MCChatUtils; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCSystemChatEvent; import buttondevteam.lib.player.*; @@ -36,7 +38,7 @@ public class MCListener implements Listener { public void onPlayerLogin(PlayerLoginEvent e) { if (e.getResult() != Result.ALLOWED) return; - MCChatListener.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) //Only private mcchat should be in ConnectedSenders + MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) //Only private mcchat should be in ConnectedSenders .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() .ifPresent(dcp -> callEventExcludingSome(new PlayerQuitEvent(dcp, ""))); } @@ -50,9 +52,9 @@ public class MCListener implements Listener { DiscordPlayer dp = e.GetPlayer().getAs(DiscordPlayer.class); if (dp != null) { val user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID())); - MCChatListener.addSender(MCChatListener.OnlineSenders, dp.getDiscordID(), + MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(), new DiscordPlayerSender(user, user.getOrCreatePMChannel(), p)); - MCChatListener.addSender(MCChatListener.OnlineSenders, dp.getDiscordID(), + MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(), new DiscordPlayerSender(user, DiscordPlugin.chatchannel, p)); //Stored per-channel } if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) { @@ -63,8 +65,7 @@ public class MCListener implements Listener { p.sendMessage("§bIf it wasn't you, do /discord decline"); } final String message = e.GetPlayer().PlayerName().get() + " joined the game"; - MCChatListener.forAllowedCustomAndAllMCChat(MCChatListener.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true); - //System.out.println("Does this appear more than once?"); //No + MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true); MCChatListener.ListC = 0; ChromaBot.getInstance().updatePlayerList(); }); @@ -74,16 +75,16 @@ public class MCListener implements Listener { public void onPlayerLeave(TBMCPlayerQuitEvent e) { if (e.getPlayer() instanceof DiscordConnectedPlayer) return; // Only care about real users - MCChatListener.OnlineSenders.entrySet() + MCChatUtils.OnlineSenders.entrySet() .removeIf(entry -> entry.getValue().entrySet().stream().anyMatch(p -> p.getValue().getUniqueId().equals(e.getPlayer().getUniqueId()))); Bukkit.getScheduler().runTask(DiscordPlugin.plugin, - () -> MCChatListener.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) + () -> MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() .ifPresent(dcp -> callEventExcludingSome(new PlayerJoinEvent(dcp, "")))); Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, ChromaBot.getInstance()::updatePlayerList, 5); final String message = e.GetPlayer().PlayerName().get() + " left the game"; - MCChatListener.forAllowedCustomAndAllMCChat(MCChatListener.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true); + MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true); } @EventHandler(priority = EventPriority.HIGHEST) @@ -109,7 +110,7 @@ public class MCListener implements Listener { @EventHandler(priority = EventPriority.LOW) public void onPlayerDeath(PlayerDeathEvent e) { - MCChatListener.forAllowedCustomAndAllMCChat(MCChatListener.send(e.getDeathMessage()), e.getEntity(), ChannelconBroadcast.DEATH, true); + MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(e.getDeathMessage()), e.getEntity(), ChannelconBroadcast.DEATH, true); } @EventHandler @@ -119,7 +120,7 @@ public class MCListener implements Listener { return; final String msg = base.getDisplayName() + " is " + (e.getValue() ? "now" : "no longer") + " AFK."; - MCChatListener.forAllowedCustomAndAllMCChat(MCChatListener.send(msg), base, ChannelconBroadcast.AFK, false); + MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(msg), base, ChannelconBroadcast.AFK, false); } @EventHandler @@ -151,12 +152,12 @@ public class MCListener implements Listener { @EventHandler public void onChatSystemMessage(TBMCSystemChatEvent event) { - MCChatListener.forAllowedMCChat(MCChatListener.send(event.getMessage()), event); + MCChatUtils.forAllowedMCChat(MCChatUtils.send(event.getMessage()), event); } @EventHandler public void onBroadcastMessage(BroadcastMessageEvent event) { - MCChatListener.forCustomAndAllMCChat(MCChatListener.send(event.getMessage()), ChannelconBroadcast.BROADCAST, false); + MCChatUtils.forCustomAndAllMCChat(MCChatUtils.send(event.getMessage()), ChannelconBroadcast.BROADCAST, false); } @EventHandler @@ -164,7 +165,7 @@ public class MCListener implements Listener { String name = event.getSender() instanceof Player ? ((Player) event.getSender()).getDisplayName() : event.getSender().getName(); //Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO - MCChatListener.forAllMCChat(MCChatListener.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s")); + MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s")); } private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises"}; diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatCustom.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatCustom.java new file mode 100644 index 0000000..74979f8 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatCustom.java @@ -0,0 +1,59 @@ +package buttondevteam.discordplugin.mcchat; + +import buttondevteam.discordplugin.DiscordConnectedPlayer; +import buttondevteam.lib.chat.Channel; +import lombok.NonNull; +import lombok.val; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IUser; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class MCChatCustom { + /** + * Used for town or nation chats or anything else + */ + static ArrayList lastmsgCustom = new ArrayList<>(); + + public static void addCustomChat(IChannel channel, String groupid, Channel mcchannel, IUser user, DiscordConnectedPlayer dcp, int toggles) { + val lmd = new CustomLMD(channel, user, groupid, mcchannel, dcp, toggles); + lastmsgCustom.add(lmd); + } + + public static boolean hasCustomChat(IChannel channel) { + return lastmsgCustom.stream().anyMatch(lmd -> lmd.channel.getLongID() == channel.getLongID()); + } + + @Nullable + public static CustomLMD getCustomChat(IChannel channel) { + return lastmsgCustom.stream().filter(lmd -> lmd.channel.getLongID() == channel.getLongID()).findAny().orElse(null); + } + + public static boolean removeCustomChat(IChannel channel) { + MCChatUtils.lastmsgfromd.remove(channel.getLongID()); + return lastmsgCustom.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID()); + } + + public static List getCustomChats() { + return Collections.unmodifiableList(lastmsgCustom); + } + + public static class CustomLMD extends MCChatUtils.LastMsgData { + public final String groupID; + public final Channel mcchannel; + public final DiscordConnectedPlayer dcp; + public int toggles; + + private CustomLMD(@NonNull IChannel channel, @NonNull IUser user, + @NonNull String groupid, @NonNull Channel mcchannel, @NonNull DiscordConnectedPlayer dcp, int toggles) { + super(channel, user); + groupID = groupid; + this.mcchannel = mcchannel; + this.dcp = dcp; + this.toggles = toggles; + } + } +} diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java similarity index 60% rename from src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java rename to src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java index 0860efd..f81c01d 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java @@ -1,57 +1,47 @@ -package buttondevteam.discordplugin.listeners; +package buttondevteam.discordplugin.mcchat; import buttondevteam.core.ComponentManager; -import buttondevteam.discordplugin.*; -import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule; -import buttondevteam.discordplugin.mcchat.MinecraftChatModule; +import buttondevteam.discordplugin.DPUtils; +import buttondevteam.discordplugin.DiscordPlugin; +import buttondevteam.discordplugin.DiscordSender; +import buttondevteam.discordplugin.DiscordSenderBase; +import buttondevteam.discordplugin.listeners.CommonListeners; import buttondevteam.discordplugin.playerfaker.VanillaCommandListener; import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatPreprocessEvent; import buttondevteam.lib.TBMCCoreAPI; -import buttondevteam.lib.TBMCSystemChatEvent; import buttondevteam.lib.chat.Channel; import buttondevteam.lib.chat.ChatMessage; import buttondevteam.lib.chat.ChatRoom; import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.player.TBMCPlayer; import com.vdurmont.emoji.EmojiParser; -import io.netty.util.collection.LongObjectHashMap; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.var; import lombok.val; import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.scheduler.BukkitTask; import sx.blah.discord.api.events.IListener; import sx.blah.discord.api.internal.json.objects.EmbedObject; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; import sx.blah.discord.handle.obj.IChannel; import sx.blah.discord.handle.obj.IMessage; -import sx.blah.discord.handle.obj.IPrivateChannel; import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.util.DiscordException; import sx.blah.discord.util.EmbedBuilder; import sx.blah.discord.util.MissingPermissionsException; -import javax.annotation.Nullable; import java.awt.*; import java.time.Instant; -import java.util.List; -import java.util.*; +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.Optional; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeoutException; -import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; -import java.util.function.Supplier; import java.util.stream.Collectors; -import java.util.stream.Stream; public class MCChatListener implements Listener, IListener { private BukkitTask sendtask; @@ -105,7 +95,7 @@ public class MCChatListener implements Listener, IListener // embed.withFooterText(e.getChannel().DisplayName); embed.withTimestamp(time); final long nanoTime = System.nanoTime(); - InterruptibleConsumer doit = lastmsgdata -> { + InterruptibleConsumer doit = lastmsgdata -> { final EmbedObject embedObject = embed.build(); if (lastmsgdata.message == null || lastmsgdata.message.isDeleted() || !authorPlayer.equals(lastmsgdata.message.getEmbeds().get(0).getAuthor().getName()) @@ -120,7 +110,7 @@ public class MCChatListener implements Listener, IListener try { lastmsgdata.content = embedObject.description = lastmsgdata.content + "\n" + embedObject.description;// The message object doesn't get updated - final LastMsgData _lastmsgdata = lastmsgdata; + final MCChatUtils.LastMsgData _lastmsgdata = lastmsgdata; DPUtils.perform(() -> _lastmsgdata.message.edit("", embedObject)); } catch (MissingPermissionsException | DiscordException e1) { TBMCCoreAPI.SendException("An error occurred while editing chat message!", e1); @@ -133,17 +123,17 @@ public class MCChatListener implements Listener, IListener if (e.getChannel().isGlobal() && (e.isFromcmd() || isdifferentchannel.test(DiscordPlugin.chatchannel))) - doit.accept(lastmsgdata == null - ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null) - : lastmsgdata); + doit.accept(MCChatUtils.lastmsgdata == null + ? MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(DiscordPlugin.chatchannel, null) + : MCChatUtils.lastmsgdata); - for (LastMsgData data : lastmsgPerUser) { + for (MCChatUtils.LastMsgData data : MCChatPrivate.lastmsgPerUser) { if ((e.isFromcmd() || isdifferentchannel.test(data.channel)) - && e.shouldSendTo(getSender(data.channel, data.user))) + && e.shouldSendTo(MCChatUtils.getSender(data.channel, data.user))) doit.accept(data); } - val iterator = lastmsgCustom.iterator(); + val iterator = MCChatCustom.lastmsgCustom.iterator(); while (iterator.hasNext()) { val lmd = iterator.next(); if ((e.isFromcmd() || isdifferentchannel.test(lmd.channel)) //Test if msg is from Discord @@ -165,32 +155,6 @@ public class MCChatListener implements Listener, IListener } } - @RequiredArgsConstructor - public static class LastMsgData { - public IMessage message; - public long time; - public String content; - public final IChannel channel; - public Channel mcchannel; - public final IUser user; - } - - public static class CustomLMD extends LastMsgData { - public final String groupID; - public final Channel mcchannel; - public final DiscordConnectedPlayer dcp; - public int toggles; - - private CustomLMD(@NonNull IChannel channel, @NonNull IUser user, - @NonNull String groupid, @NonNull Channel mcchannel, @NonNull DiscordConnectedPlayer dcp, int toggles) { - super(channel, user); - groupID = groupid; - this.mcchannel = mcchannel; - this.dcp = dcp; - this.toggles = toggles; - } - } - @EventHandler public void onChatPreprocess(TBMCChatPreprocessEvent event) { int start = -1; @@ -214,72 +178,8 @@ public class MCChatListener implements Listener, IListener private static final String[] UnconnectedCmds = new String[]{"list", "u", "shrug", "tableflip", "unflip", "mwiki", "yeehaw", "lenny", "rp", "plugins"}; - private static LastMsgData lastmsgdata; private static short lastlist = 0; private static short lastlistp = 0; - /** - * Used for messages in PMs (mcchat). - */ - private static ArrayList lastmsgPerUser = new ArrayList(); - /** - * Used for town or nation chats or anything else - */ - private static ArrayList lastmsgCustom = new ArrayList<>(); - private static LongObjectHashMap lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks - - public static boolean privateMCChat(IChannel channel, boolean start, IUser user, DiscordPlayer dp) { - TBMCPlayer mcp = dp.getAs(TBMCPlayer.class); - if (mcp != null) { // If the accounts aren't connected, can't make a connected sender - val p = Bukkit.getPlayer(mcp.getUUID()); - val op = Bukkit.getOfflinePlayer(mcp.getUUID()); - if (start) { - val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName()); - addSender(ConnectedSenders, user, sender); - if (p == null)// Player is offline - If the player is online, that takes precedence - MCListener.callEventExcludingSome(new PlayerJoinEvent(sender, "")); - } else { - val sender = removeSender(ConnectedSenders, channel, user); - if (p == null)// Player is offline - If the player is online, that takes precedence - MCListener.callEventExcludingSome(new PlayerQuitEvent(sender, "")); - } - } - if (!start) - lastmsgfromd.remove(channel.getLongID()); - return start // - ? lastmsgPerUser.add(new LastMsgData(channel, user)) // Doesn't support group DMs - : lastmsgPerUser.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID()); - } - - public static T addSender(HashMap> senders, - IUser user, T sender) { - return addSender(senders, user.getStringID(), sender); - } - - public static T addSender(HashMap> senders, - String did, T sender) { - var map = senders.get(did); - if (map == null) - map = new HashMap<>(); - map.put(sender.getChannel(), sender); - senders.put(did, map); - return sender; - } - - public static T getSender(HashMap> senders, - IChannel channel, IUser user) { - var map = senders.get(user.getStringID()); - if (map != null) - return map.get(channel); - return null; - } - - public static T removeSender(HashMap> senders, - IChannel channel, IUser user) { - var map = senders.get(user.getStringID()); - if (map != null) - return map.remove(channel); - return null; - } // ......................DiscordSender....DiscordConnectedPlayer.DiscordPlayerSender // Offline public chat......x............................................ @@ -292,143 +192,8 @@ public class MCChatListener implements Listener, IListener // If online and disabling private chat, don't logout // The maps may not contain the senders for UnconnectedSenders - public static boolean isMinecraftChatEnabled(DiscordPlayer dp) { - return isMinecraftChatEnabled(dp.getDiscordID()); - } - - public static boolean isMinecraftChatEnabled(String did) { // Don't load the player data just for this - return lastmsgPerUser.stream() - .anyMatch(lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(did)); - } - - public static void addCustomChat(IChannel channel, String groupid, Channel mcchannel, IUser user, DiscordConnectedPlayer dcp, int toggles) { - val lmd = new CustomLMD(channel, user, groupid, mcchannel, dcp, toggles); - lastmsgCustom.add(lmd); - } - - public static boolean hasCustomChat(IChannel channel) { - return lastmsgCustom.stream().anyMatch(lmd -> lmd.channel.getLongID() == channel.getLongID()); - } - - @Nullable - public static CustomLMD getCustomChat(IChannel channel) { - return lastmsgCustom.stream().filter(lmd -> lmd.channel.getLongID() == channel.getLongID()).findAny().orElse(null); - } - - public static boolean removeCustomChat(IChannel channel) { - lastmsgfromd.remove(channel.getLongID()); - return lastmsgCustom.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID()); - } - - public static List getCustomChats() { - return Collections.unmodifiableList(lastmsgCustom); - } - - /** - * May contain P<DiscordID> as key for public chat - */ - public static final HashMap> UnconnectedSenders = new HashMap<>(); - public static final HashMap> ConnectedSenders = new HashMap<>(); - /** - * May contain P<DiscordID> as key for public chat - */ - public static final HashMap> OnlineSenders = new HashMap<>(); public static short ListC = 0; - /** - * Resets the last message, so it will start a new one instead of appending to it. - * This is used when someone (even the bot) sends a message to the channel. - * - * @param channel The channel to reset in - the process is slightly different for the public, private and custom chats - */ - public static void resetLastMessage(IChannel channel) { - if (channel.getLongID() == DiscordPlugin.chatchannel.getLongID()) { - (lastmsgdata == null ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null) - : lastmsgdata).message = null; - return; - } // Don't set the whole object to null, the player and channel information should be preserved - for (LastMsgData data : channel.isPrivate() ? lastmsgPerUser : lastmsgCustom) { - if (data.channel.getLongID() == channel.getLongID()) { - data.message = null; - return; - } - } - //If it gets here, it's sending a message to a non-chat channel - } - - public static void forAllMCChat(Consumer action) { - action.accept(DiscordPlugin.chatchannel); - for (LastMsgData data : lastmsgPerUser) - action.accept(data.channel); - // lastmsgCustom.forEach(cc -> action.accept(cc.channel)); - Only send relevant messages to custom chat - } - - /** - * For custom and all MC chat - * - * @param action The action to act - * @param toggle The toggle to check - * @param hookmsg Whether the message is also sent from the hook - */ - public static void forCustomAndAllMCChat(Consumer action, @Nullable ChannelconBroadcast toggle, boolean hookmsg) { - if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg) - forAllMCChat(action); - final Consumer customLMDConsumer = cc -> action.accept(cc.channel); - if (toggle == null) - lastmsgCustom.forEach(customLMDConsumer); - else - lastmsgCustom.stream().filter(cc -> (cc.toggles & toggle.flag) != 0).forEach(customLMDConsumer); - } - - /** - * Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled. - * - * @param action The action to do - * @param sender The sender to check perms of or null to send to all that has it toggled - * @param toggle The toggle to check or null to send to all allowed - */ - public static void forAllowedCustomMCChat(Consumer action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle) { - lastmsgCustom.stream().filter(clmd -> { - //new TBMCChannelConnectFakeEvent(sender, clmd.mcchannel).shouldSendTo(clmd.dcp) - Thought it was this simple hehe - Wait, it *should* be this simple - if (toggle != null && (clmd.toggles & toggle.flag) == 0) - return false; //If null then allow - if (sender == null) - return true; - return clmd.groupID.equals(clmd.mcchannel.getGroupID(sender)); - }).forEach(cc -> action.accept(cc.channel)); //TODO: Send error messages on channel connect - } - - /** - * Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled. - * - * @param action The action to do - * @param sender The sender to check perms of or null to send to all that has it toggled - * @param toggle The toggle to check or null to send to all allowed - * @param hookmsg Whether the message is also sent from the hook - */ - public static void forAllowedCustomAndAllMCChat(Consumer action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle, boolean hookmsg) { - if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg) - forAllMCChat(action); - forAllowedCustomMCChat(action, sender, toggle); - } - - public static Consumer send(String message) { - return ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(message)); - } - - public static void forAllowedMCChat(Consumer action, TBMCSystemChatEvent event) { - if (event.getChannel().isGlobal()) - action.accept(DiscordPlugin.chatchannel); - for (LastMsgData data : lastmsgPerUser) - if (event.shouldSendTo(getSender(data.channel, data.user))) - action.accept(data.channel); - lastmsgCustom.stream().filter(clmd -> { - if ((clmd.toggles & ChannelconBroadcast.BROADCAST.flag) == 0) - return false; - return event.shouldSendTo(clmd.dcp); - }).map(clmd -> clmd.channel).forEach(action); - } - /** * Stop the listener. Any calls to onMCChat will restart it as long as we're not in safe mode. * @@ -448,13 +213,13 @@ public class MCChatListener implements Listener, IListener if (wait) recthread.join(5000); } - lastmsgdata = null; - lastmsgPerUser.clear(); - lastmsgCustom.clear(); - lastmsgfromd.clear(); - ConnectedSenders.clear(); + MCChatUtils.lastmsgdata = null; + MCChatPrivate.lastmsgPerUser.clear(); + MCChatCustom.lastmsgCustom.clear(); + MCChatUtils.lastmsgfromd.clear(); + MCChatUtils.ConnectedSenders.clear(); lastlist = lastlistp = ListC = 0; - UnconnectedSenders.clear(); + MCChatUtils.UnconnectedSenders.clear(); recthread = sendthread = null; } catch (InterruptedException e) { e.printStackTrace(); //This thread shouldn't be interrupted @@ -473,16 +238,16 @@ public class MCChatListener implements Listener, IListener val author = ev.getMessage().getAuthor(); if (author.isBot()) return; - final boolean hasCustomChat = hasCustomChat(ev.getChannel()); + final boolean hasCustomChat = MCChatCustom.hasCustomChat(ev.getChannel()); if (!ev.getMessage().getChannel().getStringID().equals(DiscordPlugin.chatchannel.getStringID()) - && !(ev.getMessage().getChannel().isPrivate() && isMinecraftChatEnabled(author.getStringID())) + && !(ev.getMessage().getChannel().isPrivate() && MCChatPrivate.isMinecraftChatEnabled(author.getStringID())) && !hasCustomChat) return; if (ev.getMessage().getContent().equalsIgnoreCase("mcchat")) return; // Race condition: If it gets here after it enabled mcchat it says it - I might as well allow disabling with this (CommonListeners) if (CommonListeners.runCommand(ev.getMessage(), true)) return; - resetLastMessage(ev.getChannel()); + MCChatUtils.resetLastMessage(ev.getChannel()); lastlist++; recevents.add(ev); if (rectask != null) @@ -508,7 +273,7 @@ public class MCChatListener implements Listener, IListener val sender = event.getMessage().getAuthor(); String dmessage = event.getMessage().getContent(); try { - final DiscordSenderBase dsender = getSender(event.getMessage().getChannel(), sender); + final DiscordSenderBase dsender = MCChatUtils.getSender(event.getMessage().getChannel(), sender); val user = dsender.getChromaUser(); for (IUser u : event.getMessage().getMentions()) { @@ -528,7 +293,7 @@ public class MCChatListener implements Listener, IListener .getAttachments().stream().map(IMessage.Attachment::getUrl).collect(Collectors.joining("\n")) : ""); - CustomLMD clmd = getCustomChat(event.getChannel()); + MCChatCustom.CustomLMD clmd = MCChatCustom.getCustomChat(event.getChannel()); boolean react = false; @@ -573,18 +338,13 @@ public class MCChatListener implements Listener, IListener () -> { //TODO: Better handling... val channel = user.channel(); val chtmp = channel.get(); - //System.out.println("1: "+chtmp.ID); - //System.out.println("clmd: "+clmd); if (clmd != null) { channel.set(clmd.mcchannel); //Hack to send command in the channel - //System.out.println("clmd chan: "+clmd.mcchannel.ID); } //TODO: Permcheck isn't implemented for commands - //System.out.println("2: "+channel.get().ID); VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd); Bukkit.getLogger().info(dsender.getName() + " issued command from Discord: /" + cmdlowercased); if (clmd != null) channel.set(chtmp); - //System.out.println("3: "+channel.get().ID); - TODO: Remove }); else { Channel chc = ch.get(); @@ -638,7 +398,7 @@ public class MCChatListener implements Listener, IListener } if (react) { try { - val lmfd = lastmsgfromd.get(event.getChannel().getLongID()); + val lmfd = MCChatUtils.lastmsgfromd.get(event.getChannel().getLongID()); if (lmfd != null) { DPUtils.perform(() -> lmfd.removeReaction(DiscordPlugin.dc.getOurUser(), DiscordPlugin.DELIVERED_REACTION)); // Remove it no matter what, we know it's there 99.99% of the time @@ -646,7 +406,7 @@ public class MCChatListener implements Listener, IListener } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while removing reactions from chat!", e); } - lastmsgfromd.put(event.getChannel().getLongID(), event.getMessage()); + MCChatUtils.lastmsgfromd.put(event.getChannel().getLongID(), event.getMessage()); DPUtils.perform(() -> event.getMessage().addReaction(DiscordPlugin.DELIVERED_REACTION)); } } catch (Exception e) { @@ -654,19 +414,6 @@ public class MCChatListener implements Listener, IListener } } - /** - * This method will find the best sender to use: if the player is online, use that, if not but connected then use that etc. - */ - private static DiscordSenderBase getSender(IChannel channel, final IUser author) { - //noinspection OptionalGetWithoutIsPresent - return Stream.>>of( // https://stackoverflow.com/a/28833677/2703239 - () -> Optional.ofNullable(getSender(OnlineSenders, channel, author)), // Find first non-null - () -> Optional.ofNullable(getSender(ConnectedSenders, channel, author)), // This doesn't support the public chat, but it'll always return null for it - () -> Optional.ofNullable(getSender(OnlineSenders, channel, author)), // - () -> Optional.of(addSender(UnconnectedSenders, author, - new DiscordSender(author, channel)))).map(Supplier::get).filter(Optional::isPresent).map(Optional::get).findFirst().get(); - } - @FunctionalInterface private interface InterruptibleConsumer { void accept(T value) throws TimeoutException, InterruptedException; diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java new file mode 100644 index 0000000..3afdd18 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java @@ -0,0 +1,55 @@ +package buttondevteam.discordplugin.mcchat; + +import buttondevteam.discordplugin.DiscordConnectedPlayer; +import buttondevteam.discordplugin.DiscordPlayer; +import buttondevteam.discordplugin.listeners.MCListener; +import buttondevteam.lib.player.TBMCPlayer; +import lombok.val; +import org.bukkit.Bukkit; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IPrivateChannel; +import sx.blah.discord.handle.obj.IUser; + +import java.util.ArrayList; + +public class MCChatPrivate { + + /** + * Used for messages in PMs (mcchat). + */ + static ArrayList lastmsgPerUser = new ArrayList<>(); + + public static boolean privateMCChat(IChannel channel, boolean start, IUser user, DiscordPlayer dp) { + TBMCPlayer mcp = dp.getAs(TBMCPlayer.class); + if (mcp != null) { // If the accounts aren't connected, can't make a connected sender + val p = Bukkit.getPlayer(mcp.getUUID()); + val op = Bukkit.getOfflinePlayer(mcp.getUUID()); + if (start) { + val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName()); + MCChatUtils.addSender(MCChatUtils.ConnectedSenders, user, sender); + if (p == null)// Player is offline - If the player is online, that takes precedence + MCListener.callEventExcludingSome(new PlayerJoinEvent(sender, "")); + } else { + val sender = MCChatUtils.removeSender(MCChatUtils.ConnectedSenders, channel, user); + if (p == null)// Player is offline - If the player is online, that takes precedence + MCListener.callEventExcludingSome(new PlayerQuitEvent(sender, "")); + } + } + if (!start) + MCChatUtils.lastmsgfromd.remove(channel.getLongID()); + return start // + ? lastmsgPerUser.add(new MCChatUtils.LastMsgData(channel, user)) // Doesn't support group DMs + : lastmsgPerUser.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID()); + } + + public static boolean isMinecraftChatEnabled(DiscordPlayer dp) { + return isMinecraftChatEnabled(dp.getDiscordID()); + } + + public static boolean isMinecraftChatEnabled(String did) { // Don't load the player data just for this + return lastmsgPerUser.stream() + .anyMatch(lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(did)); + } +} diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java new file mode 100644 index 0000000..e700b9a --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java @@ -0,0 +1,182 @@ +package buttondevteam.discordplugin.mcchat; + +import buttondevteam.discordplugin.*; +import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule; +import buttondevteam.lib.TBMCSystemChatEvent; +import buttondevteam.lib.chat.Channel; +import io.netty.util.collection.LongObjectHashMap; +import lombok.RequiredArgsConstructor; +import lombok.experimental.var; +import org.bukkit.command.CommandSender; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IMessage; +import sx.blah.discord.handle.obj.IUser; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Stream; + +public class MCChatUtils { + /** + * May contain P<DiscordID> as key for public chat + */ + public static final HashMap> UnconnectedSenders = new HashMap<>(); + public static final HashMap> ConnectedSenders = new HashMap<>(); + /** + * May contain P<DiscordID> as key for public chat + */ + public static final HashMap> OnlineSenders = new HashMap<>(); + static LastMsgData lastmsgdata; + static LongObjectHashMap lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks + + public static T addSender(HashMap> senders, + IUser user, T sender) { + return addSender(senders, user.getStringID(), sender); + } + + public static T addSender(HashMap> senders, + String did, T sender) { + var map = senders.get(did); + if (map == null) + map = new HashMap<>(); + map.put(sender.getChannel(), sender); + senders.put(did, map); + return sender; + } + + public static T getSender(HashMap> senders, + IChannel channel, IUser user) { + var map = senders.get(user.getStringID()); + if (map != null) + return map.get(channel); + return null; + } + + public static T removeSender(HashMap> senders, + IChannel channel, IUser user) { + var map = senders.get(user.getStringID()); + if (map != null) + return map.remove(channel); + return null; + } + + public static void forAllMCChat(Consumer action) { + action.accept(DiscordPlugin.chatchannel); + for (LastMsgData data : MCChatPrivate.lastmsgPerUser) + action.accept(data.channel); + // lastmsgCustom.forEach(cc -> action.accept(cc.channel)); - Only send relevant messages to custom chat + } + + /** + * For custom and all MC chat + * + * @param action The action to act + * @param toggle The toggle to check + * @param hookmsg Whether the message is also sent from the hook + */ + public static void forCustomAndAllMCChat(Consumer action, @Nullable ChannelconBroadcast toggle, boolean hookmsg) { + if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg) + forAllMCChat(action); + final Consumer customLMDConsumer = cc -> action.accept(cc.channel); + if (toggle == null) + MCChatCustom.lastmsgCustom.forEach(customLMDConsumer); + else + MCChatCustom.lastmsgCustom.stream().filter(cc -> (cc.toggles & toggle.flag) != 0).forEach(customLMDConsumer); + } + + /** + * Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled. + * + * @param action The action to do + * @param sender The sender to check perms of or null to send to all that has it toggled + * @param toggle The toggle to check or null to send to all allowed + */ + public static void forAllowedCustomMCChat(Consumer action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle) { + MCChatCustom.lastmsgCustom.stream().filter(clmd -> { + //new TBMCChannelConnectFakeEvent(sender, clmd.mcchannel).shouldSendTo(clmd.dcp) - Thought it was this simple hehe - Wait, it *should* be this simple + if (toggle != null && (clmd.toggles & toggle.flag) == 0) + return false; //If null then allow + if (sender == null) + return true; + return clmd.groupID.equals(clmd.mcchannel.getGroupID(sender)); + }).forEach(cc -> action.accept(cc.channel)); //TODO: Send error messages on channel connect + } + + /** + * Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled. + * + * @param action The action to do + * @param sender The sender to check perms of or null to send to all that has it toggled + * @param toggle The toggle to check or null to send to all allowed + * @param hookmsg Whether the message is also sent from the hook + */ + public static void forAllowedCustomAndAllMCChat(Consumer action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle, boolean hookmsg) { + if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg) + forAllMCChat(action); + forAllowedCustomMCChat(action, sender, toggle); + } + + public static Consumer send(String message) { + return ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(message)); + } + + public static void forAllowedMCChat(Consumer action, TBMCSystemChatEvent event) { + if (event.getChannel().isGlobal()) + action.accept(DiscordPlugin.chatchannel); + for (LastMsgData data : MCChatPrivate.lastmsgPerUser) + if (event.shouldSendTo(getSender(data.channel, data.user))) + action.accept(data.channel); + MCChatCustom.lastmsgCustom.stream().filter(clmd -> { + if ((clmd.toggles & ChannelconBroadcast.BROADCAST.flag) == 0) + return false; + return event.shouldSendTo(clmd.dcp); + }).map(clmd -> clmd.channel).forEach(action); + } + + /** + * This method will find the best sender to use: if the player is online, use that, if not but connected then use that etc. + */ + static DiscordSenderBase getSender(IChannel channel, final IUser author) { + //noinspection OptionalGetWithoutIsPresent + return Stream.>>of( // https://stackoverflow.com/a/28833677/2703239 + () -> Optional.ofNullable(getSender(OnlineSenders, channel, author)), // Find first non-null + () -> Optional.ofNullable(getSender(ConnectedSenders, channel, author)), // This doesn't support the public chat, but it'll always return null for it + () -> Optional.ofNullable(getSender(UnconnectedSenders, channel, author)), // + () -> Optional.of(addSender(UnconnectedSenders, author, + new DiscordSender(author, channel)))).map(Supplier::get).filter(Optional::isPresent).map(Optional::get).findFirst().get(); + } + + /** + * Resets the last message, so it will start a new one instead of appending to it. + * This is used when someone (even the bot) sends a message to the channel. + * + * @param channel The channel to reset in - the process is slightly different for the public, private and custom chats + */ + public static void resetLastMessage(IChannel channel) { + if (channel.getLongID() == DiscordPlugin.chatchannel.getLongID()) { + (lastmsgdata == null ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null) + : lastmsgdata).message = null; + return; + } // Don't set the whole object to null, the player and channel information should be preserved + for (LastMsgData data : channel.isPrivate() ? MCChatPrivate.lastmsgPerUser : MCChatCustom.lastmsgCustom) { + if (data.channel.getLongID() == channel.getLongID()) { + data.message = null; + return; + } + } + //If it gets here, it's sending a message to a non-chat channel + } + + @RequiredArgsConstructor + public static class LastMsgData { + public IMessage message; + public long time; + public String content; + public final IChannel channel; + public Channel mcchannel; + public final IUser user; + } +} diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java index 709b055..4c84bdf 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java @@ -1,7 +1,6 @@ package buttondevteam.discordplugin.mcchat; import buttondevteam.discordplugin.DiscordPlugin; -import buttondevteam.discordplugin.listeners.MCChatListener; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.Component; diff --git a/src/main/java/buttondevteam/discordplugin/mccommands/AcceptMCCommand.java b/src/main/java/buttondevteam/discordplugin/mccommands/AcceptMCCommand.java index f695dba..2f2ad21 100755 --- a/src/main/java/buttondevteam/discordplugin/mccommands/AcceptMCCommand.java +++ b/src/main/java/buttondevteam/discordplugin/mccommands/AcceptMCCommand.java @@ -2,7 +2,7 @@ package buttondevteam.discordplugin.mccommands; import buttondevteam.discordplugin.DiscordPlayer; import buttondevteam.discordplugin.commands.ConnectCommand; -import buttondevteam.discordplugin.listeners.MCChatListener; +import buttondevteam.discordplugin.mcchat.MCChatUtils; import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.player.TBMCPlayer; @@ -35,7 +35,7 @@ public class AcceptMCCommand extends DiscordMCCommandBase { dp.save(); mcp.save(); ConnectCommand.WaitingToConnect.remove(player.getName()); - MCChatListener.UnconnectedSenders.remove(did); //Remove all unconnected, will be recreated where needed + MCChatUtils.UnconnectedSenders.remove(did); //Remove all unconnected, will be recreated where needed player.sendMessage("§bAccounts connected."); return true; } From 21221dfeeb147cf5e78b7e6caff507c4430d04cb Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 18 Dec 2018 00:52:02 +0100 Subject: [PATCH 05/12] NPE fix, prefix --- .../discordplugin/DiscordPlugin.java | 18 ++++++++++++++---- .../discordplugin/commands/ConnectCommand.java | 6 +++--- .../discordplugin/commands/HelpCommand.java | 7 +++---- .../discordplugin/commands/MCChatCommand.java | 7 ++++--- .../discordplugin/commands/RoleCommand.java | 2 +- .../commands/UserinfoCommand.java | 3 ++- .../discordplugin/mcchat/MCChatListener.java | 5 +++-- 7 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 02709d1..8c4856a 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -12,7 +12,9 @@ import buttondevteam.discordplugin.mcchat.MinecraftChatModule; import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase; import buttondevteam.discordplugin.mccommands.ResetMCCommand; import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.architecture.ButtonPlugin; import buttondevteam.lib.architecture.Component; +import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.chat.Channel; import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.player.ChromaGamerBase; @@ -27,7 +29,6 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.RegisteredServiceProvider; -import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitTask; import sx.blah.discord.api.ClientBuilder; import sx.blah.discord.api.IDiscordClient; @@ -49,7 +50,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; -public class DiscordPlugin extends JavaPlugin implements IListener { +public class DiscordPlugin extends ButtonPlugin implements IListener { private static final String SubredditURL = "https://www.reddit.com/r/ChromaGamers"; private static boolean stop = false; public static IDiscordClient dc; @@ -57,8 +58,17 @@ public class DiscordPlugin extends JavaPlugin implements IListener { public static boolean SafeMode = true; public static List GameRoles; + public ConfigData Prefix() { + return getData("prefix", '/'); + } + + public static char getPrefix() { + if (plugin == null) return '/'; + return plugin.Prefix().get(); + } + @Override - public void onEnable() { + public void pluginEnable() { stop = false; //If not the first time try { Bukkit.getLogger().info("Initializing DiscordPlugin..."); @@ -238,7 +248,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { public static boolean Restart; @Override - public void onDisable() { + public void pluginDisable() { stop = true; for (val entry : MCChatUtils.ConnectedSenders.entrySet()) for (val valueEntry : entry.getValue().entrySet()) diff --git a/src/main/java/buttondevteam/discordplugin/commands/ConnectCommand.java b/src/main/java/buttondevteam/discordplugin/commands/ConnectCommand.java index a339c4d..6e16c09 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/ConnectCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/ConnectCommand.java @@ -30,7 +30,7 @@ public class ConnectCommand extends DiscordCommandBase { return false; if (args.contains(" ")) { DiscordPlugin.sendMessageToChannel(message.getChannel(), - "Too many arguments.\nUsage: connect "); + "Too many arguments.\nUsage: " + DiscordPlugin.getPrefix() + "connect "); return true; } if (WaitingToConnect.inverse().containsKey(message.getAuthor().getStringID())) { @@ -68,8 +68,8 @@ public class ConnectCommand extends DiscordCommandBase { public String[] getHelpText() { return new String[] { // "---- Connect command ----", // - "This commands let's you connect your acoount with a Minecraft account. This'd allow using the Minecraft chat and other things.", // - "Usage: connect " // + "This command lets you connect your account with a Minecraft account. This allows using the Minecraft chat and other things.", // + "Usage: /connect " // }; } diff --git a/src/main/java/buttondevteam/discordplugin/commands/HelpCommand.java b/src/main/java/buttondevteam/discordplugin/commands/HelpCommand.java index 29aff28..bcef6ea 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/HelpCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/HelpCommand.java @@ -3,7 +3,6 @@ package buttondevteam.discordplugin.commands; import buttondevteam.discordplugin.DiscordPlugin; import sx.blah.discord.handle.obj.IMessage; -import java.util.Arrays; import java.util.stream.Collectors; public class HelpCommand extends DiscordCommandBase { @@ -19,11 +18,11 @@ public class HelpCommand extends DiscordCommandBase { if (args.length() == 0) DiscordPlugin.sendMessageToChannel(message.getChannel(), "Available commands:\n" + DiscordCommandBase.commands.values().stream() - .map(dc -> dc.getCommandName()).collect(Collectors.joining("\n"))); + .map(dc -> DiscordPlugin.getPrefix() + dc.getCommandName()).collect(Collectors.joining("\n"))); else DiscordPlugin.sendMessageToChannel(message.getChannel(), (argdc = DiscordCommandBase.commands.get(args)) == null ? "Command not found: " + args - : Arrays.stream(argdc.getHelpText()).collect(Collectors.joining("\n"))); + : String.join("\n", argdc.getHelpText())); return true; } @@ -32,7 +31,7 @@ public class HelpCommand extends DiscordCommandBase { return new String[] { // "---- Help command ----", // "Shows some info about a command or lists the available commands.", // - "Usage: help [command]"// + "Usage: " + DiscordPlugin.getPrefix() + "help [command]"// }; } diff --git a/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java b/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java index 7a5b7c8..24c6390 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java @@ -25,7 +25,7 @@ public class MCChatCommand extends DiscordCommandBase { MCChatPrivate.privateMCChat(message.getChannel(), mcchat, message.getAuthor(), user); DiscordPlugin.sendMessageToChannel(message.getChannel(), "Minecraft chat " + (mcchat // - ? "enabled. Use '/mcchat' again to turn it off." // + ? "enabled. Use '" + DiscordPlugin.getPrefix() + "mcchat' again to turn it off." // : "disabled.")); } catch (Exception e) { TBMCCoreAPI.SendException("Error while setting mcchat for user" + message.getAuthor().getName(), e); @@ -36,8 +36,9 @@ public class MCChatCommand extends DiscordCommandBase { @Override public String[] getHelpText() { return new String[] { // - "mcchat enables or disables the Minecraft chat in private messages.", // - "It can be useful if you don't want your messages to be visible, for example when talking a private channel." // + DiscordPlugin.getPrefix() + "mcchat enables or disables the Minecraft chat in private messages.", // + "It can be useful if you don't want your messages to be visible, for example when talking in a private channel.", // + "You can also run all of the ingame commands you have access to using this command, if you have your accounts connected." // }; // TODO: Pin channel switching to indicate the current channel } diff --git a/src/main/java/buttondevteam/discordplugin/commands/RoleCommand.java b/src/main/java/buttondevteam/discordplugin/commands/RoleCommand.java index 3978c6a..a7f2bf5 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/RoleCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/RoleCommand.java @@ -86,7 +86,7 @@ public class RoleCommand extends DiscordCommandBase { public String[] getHelpText() { return new String[]{ // "Add or remove game roles from yourself.", // - "Usage: role add|remove or role list", // + "Usage: " + DiscordPlugin.getPrefix() + "role add|remove or role list", // }; } diff --git a/src/main/java/buttondevteam/discordplugin/commands/UserinfoCommand.java b/src/main/java/buttondevteam/discordplugin/commands/UserinfoCommand.java index b0608ed..b1dbf8b 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/UserinfoCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/UserinfoCommand.java @@ -91,7 +91,8 @@ public class UserinfoCommand extends DiscordCommandBase { "---- User information ----", // "Shows some information about users, from Discord, from Minecraft or from Reddit if they have these accounts connected.", // "If used without args, shows your info.", // - "Usage: userinfo [username/nickname[#tag]/ping]\nExamples:\nuserinfo ChromaBot\nuserinfo ChromaBot#6338\nuserinfo @ChromaBot#6338" // + "Usage: " + DiscordPlugin.getPrefix() + "userinfo [username/nickname[#tag]/ping]", // + "Examples:\n" + DiscordPlugin.getPrefix() + "userinfo ChromaBot\n" + DiscordPlugin.getPrefix() + "userinfo ChromaBot#6338\n" + DiscordPlugin.getPrefix() + "userinfo @ChromaBot#6338" // }; } diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java index f81c01d..15489e5 100755 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java @@ -382,8 +382,9 @@ public class MCChatListener implements Listener, IListener } else {// Not a command if (dmessage.length() == 0 && event.getMessage().getAttachments().size() == 0 && !event.getChannel().isPrivate() && event.getMessage().isSystemMessage()) { - val rtr = clmd != null ? clmd.mcchannel.filteranderrormsg.apply(clmd.dcp) : dsender.getChromaUser().channel().get().filteranderrormsg.apply(dsender); - TBMCChatAPI.SendSystemMessage(clmd != null ? clmd.mcchannel : dsender.getChromaUser().channel().get(), rtr.score, rtr.groupID, + val rtr = clmd != null ? clmd.mcchannel.getRTR(clmd.dcp) + : dsender.getChromaUser().channel().get().getRTR(dsender); + TBMCChatAPI.SendSystemMessage(clmd != null ? clmd.mcchannel : dsender.getChromaUser().channel().get(), rtr, (dsender instanceof Player ? ((Player) dsender).getDisplayName() : dsender.getName()) + " pinned a message on Discord."); } From 5ff433f3bbaa2809233910eb8bf2fb2bdd506f26 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sat, 22 Dec 2018 16:20:20 +0100 Subject: [PATCH 06/12] Code organization Moved part of MCListener Added support for custom chat player list --- .../discordplugin/ChromaBot.java | 14 +- .../discordplugin/DiscordPlugin.java | 11 +- .../discordplugin/listeners/MCListener.java | 174 ++--------------- .../discordplugin/mcchat/MCChatPrivate.java | 8 +- .../discordplugin/mcchat/MCChatUtils.java | 38 +++- .../discordplugin/mcchat/MCListener.java | 184 ++++++++++++++++++ .../mcchat/MinecraftChatModule.java | 1 + 7 files changed, 247 insertions(+), 183 deletions(-) create mode 100644 src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java diff --git a/src/main/java/buttondevteam/discordplugin/ChromaBot.java b/src/main/java/buttondevteam/discordplugin/ChromaBot.java index 90e5afb..56a6fb9 100755 --- a/src/main/java/buttondevteam/discordplugin/ChromaBot.java +++ b/src/main/java/buttondevteam/discordplugin/ChromaBot.java @@ -2,7 +2,6 @@ package buttondevteam.discordplugin; import buttondevteam.discordplugin.mcchat.MCChatUtils; import lombok.Getter; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitScheduler; import sx.blah.discord.api.internal.json.objects.EmbedObject; @@ -11,8 +10,6 @@ import sx.blah.discord.util.EmbedBuilder; import javax.annotation.Nullable; import java.awt.*; -import java.util.Arrays; -import java.util.stream.Collectors; public class ChromaBot { /** @@ -144,15 +141,6 @@ public class ChromaBot { } public void updatePlayerList() { - DPUtils.performNoWait(() -> { - String[] s = DiscordPlugin.chatchannel.getTopic().split("\\n----\\n"); - if (s.length < 3) - return; - s[0] = Bukkit.getOnlinePlayers().size() + " player" + (Bukkit.getOnlinePlayers().size() != 1 ? "s" : "") - + " online"; - s[s.length - 1] = "Players: " + Bukkit.getOnlinePlayers().stream() - .map(p -> DPUtils.sanitizeString(p.getDisplayName())).collect(Collectors.joining(", ")); - DiscordPlugin.chatchannel.changeTopic(Arrays.stream(s).collect(Collectors.joining("\n----\n"))); - }); + MCChatUtils.updatePlayerList(); } } diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 8c4856a..da87790 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -5,10 +5,7 @@ import buttondevteam.discordplugin.commands.DiscordCommandBase; import buttondevteam.discordplugin.listeners.CommonListeners; import buttondevteam.discordplugin.listeners.ExceptionListener; import buttondevteam.discordplugin.listeners.MCListener; -import buttondevteam.discordplugin.mcchat.MCChatCustom; -import buttondevteam.discordplugin.mcchat.MCChatListener; -import buttondevteam.discordplugin.mcchat.MCChatUtils; -import buttondevteam.discordplugin.mcchat.MinecraftChatModule; +import buttondevteam.discordplugin.mcchat.*; import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase; import buttondevteam.discordplugin.mccommands.ResetMCCommand; import buttondevteam.lib.TBMCCoreAPI; @@ -27,7 +24,6 @@ import lombok.val; import net.milkbowl.vault.permission.Permission; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.scheduler.BukkitTask; import sx.blah.discord.api.ClientBuilder; @@ -250,10 +246,7 @@ public class DiscordPlugin extends ButtonPlugin implements IListener @Override public void pluginDisable() { stop = true; - for (val entry : MCChatUtils.ConnectedSenders.entrySet()) - for (val valueEntry : entry.getValue().entrySet()) - MCListener.callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); - MCChatUtils.ConnectedSenders.clear(); + MCChatPrivate.logoutAll(); getConfig().set("lastannouncementtime", lastannouncementtime); getConfig().set("lastseentime", lastseentime); getConfig().set("serverup", false); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java index cd8a826..89b4e17 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java @@ -1,99 +1,29 @@ package buttondevteam.discordplugin.listeners; -import buttondevteam.discordplugin.*; -import buttondevteam.discordplugin.commands.ConnectCommand; -import buttondevteam.discordplugin.mcchat.MCChatListener; +import buttondevteam.discordplugin.ChannelconBroadcast; +import buttondevteam.discordplugin.DPUtils; +import buttondevteam.discordplugin.DiscordPlayer; +import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.mcchat.MCChatUtils; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCSystemChatEvent; -import buttondevteam.lib.player.*; +import buttondevteam.lib.player.TBMCPlayer; +import buttondevteam.lib.player.TBMCPlayerBase; +import buttondevteam.lib.player.TBMCPlayerGetInfoEvent; +import buttondevteam.lib.player.TBMCYEEHAWEvent; import com.earth2me.essentials.CommandSource; -import lombok.val; -import net.ess3.api.events.AfkStatusChangeEvent; import net.ess3.api.events.MuteStatusChangeEvent; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.event.*; -import org.bukkit.event.entity.PlayerDeathEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerKickEvent; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerLoginEvent.Result; -import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.event.server.BroadcastMessageEvent; import org.bukkit.event.server.ServerCommandEvent; -import org.bukkit.plugin.AuthorNagException; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.RegisteredListener; import sx.blah.discord.handle.obj.IRole; import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.util.DiscordException; import sx.blah.discord.util.MissingPermissionsException; -import java.util.Arrays; -import java.util.logging.Level; - public class MCListener implements Listener { - @EventHandler(priority = EventPriority.HIGHEST) - public void onPlayerLogin(PlayerLoginEvent e) { - if (e.getResult() != Result.ALLOWED) - return; - MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) //Only private mcchat should be in ConnectedSenders - .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() - .ifPresent(dcp -> callEventExcludingSome(new PlayerQuitEvent(dcp, ""))); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerJoin(TBMCPlayerJoinEvent e) { - if (e.getPlayer() instanceof DiscordConnectedPlayer) - return; // Don't show the joined message for the fake player - Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> { - final Player p = e.getPlayer(); - DiscordPlayer dp = e.GetPlayer().getAs(DiscordPlayer.class); - if (dp != null) { - val user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID())); - MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(), - new DiscordPlayerSender(user, user.getOrCreatePMChannel(), p)); - MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(), - new DiscordPlayerSender(user, DiscordPlugin.chatchannel, p)); //Stored per-channel - } - if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) { - IUser user = DiscordPlugin.dc - .getUserByID(Long.parseLong(ConnectCommand.WaitingToConnect.get(e.GetPlayer().PlayerName().get()))); - p.sendMessage("§bTo connect with the Discord account @" + user.getName() + "#" + user.getDiscriminator() - + " do /discord accept"); - p.sendMessage("§bIf it wasn't you, do /discord decline"); - } - final String message = e.GetPlayer().PlayerName().get() + " joined the game"; - MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true); - MCChatListener.ListC = 0; - ChromaBot.getInstance().updatePlayerList(); - }); - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onPlayerLeave(TBMCPlayerQuitEvent e) { - if (e.getPlayer() instanceof DiscordConnectedPlayer) - return; // Only care about real users - MCChatUtils.OnlineSenders.entrySet() - .removeIf(entry -> entry.getValue().entrySet().stream().anyMatch(p -> p.getValue().getUniqueId().equals(e.getPlayer().getUniqueId()))); - Bukkit.getScheduler().runTask(DiscordPlugin.plugin, - () -> MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) - .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() - .ifPresent(dcp -> callEventExcludingSome(new PlayerJoinEvent(dcp, "")))); - Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, - ChromaBot.getInstance()::updatePlayerList, 5); - final String message = e.GetPlayer().PlayerName().get() + " left the game"; - MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true); - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onPlayerKick(PlayerKickEvent e) { - /*if (!DiscordPlugin.hooked && !e.getReason().equals("The server is restarting") - && !e.getReason().equals("Server closed")) // The leave messages errored with the previous setup, I could make it wait since I moved it here, but instead I have a special - MCChatListener.forAllowedCustomAndAllMCChat(e.getPlayer().getName() + " left the game"); // message for this - Oh wait this doesn't even send normally because of the hook*/ - } - @EventHandler public void onGetInfo(TBMCPlayerGetInfoEvent e) { if (DiscordPlugin.SafeMode) @@ -108,21 +38,6 @@ public class MCListener implements Listener { e.addInfo(user.getPresence().getActivity().get() + ": " + user.getPresence().getText().get()); } - @EventHandler(priority = EventPriority.LOW) - public void onPlayerDeath(PlayerDeathEvent e) { - MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(e.getDeathMessage()), e.getEntity(), ChannelconBroadcast.DEATH, true); - } - - @EventHandler - public void onPlayerAFK(AfkStatusChangeEvent e) { - final Player base = e.getAffected().getBase(); - if (e.isCancelled() || !base.isOnline()) - return; - final String msg = base.getDisplayName() - + " is " + (e.getValue() ? "now" : "no longer") + " AFK."; - MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(msg), base, ChannelconBroadcast.AFK, false); - } - @EventHandler public void onServerCommand(ServerCommandEvent e) { DiscordPlugin.Restart = !e.getCommand().equalsIgnoreCase("stop"); // The variable is always true except if stopped @@ -136,13 +51,16 @@ public class MCListener implements Listener { final CommandSource source = e.getAffected().getSource(); if (!source.isPlayer()) return; + final DiscordPlayer p = TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class) + .getAs(DiscordPlayer.class); + if (p == null) return; final IUser user = DiscordPlugin.dc.getUserByID( - Long.parseLong(TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class) - .getAs(DiscordPlayer.class).getDiscordID())); + Long.parseLong(p.getDiscordID())); if (e.getValue()) user.addRole(role); else user.removeRole(role); + DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, (e.getValue() ? "M" : "Unm") + "uted user: " + user.getName()); }); } catch (DiscordException | MissingPermissionsException ex) { TBMCCoreAPI.SendException("Failed to give/take Muted role to player " + e.getAffected().getName() + "!", @@ -167,66 +85,4 @@ public class MCListener implements Listener { //Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s")); } - - private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises"}; - - public static void callEventExcludingSome(Event event) { - callEventExcluding(event, EXCLUDED_PLUGINS); - } - - /** - * Calls an event with the given details. - *

- * This method only synchronizes when the event is not asynchronous. - * - * @param event Event details - * @param plugins The plugins to exclude. Not case sensitive. - */ - private static void callEventExcluding(Event event, String... plugins) { // Copied from Spigot-API and modified a bit - if (event.isAsynchronous()) { - if (Thread.holdsLock(Bukkit.getPluginManager())) { - throw new IllegalStateException( - event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); - } - if (Bukkit.getServer().isPrimaryThread()) { - throw new IllegalStateException( - event.getEventName() + " cannot be triggered asynchronously from primary server thread."); - } - fireEventExcluding(event, plugins); - } else { - synchronized (Bukkit.getPluginManager()) { - fireEventExcluding(event, plugins); - } - } - } - - private static void fireEventExcluding(Event event, String... plugins) { - HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API - RegisteredListener[] listeners = handlers.getRegisteredListeners(); - val server = Bukkit.getServer(); - - for (RegisteredListener registration : listeners) { - if (!registration.getPlugin().isEnabled() - || Arrays.stream(plugins).anyMatch(p -> p.equalsIgnoreCase(registration.getPlugin().getName()))) - continue; // Modified to exclude plugins - - try { - registration.callEvent(event); - } catch (AuthorNagException ex) { - Plugin plugin = registration.getPlugin(); - - if (plugin.isNaggable()) { - plugin.setNaggable(false); - - server.getLogger().log(Level.SEVERE, - String.format("Nag author(s): '%s' of '%s' about the following: %s", - plugin.getDescription().getAuthors(), plugin.getDescription().getFullName(), - ex.getMessage())); - } - } catch (Throwable ex) { - server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " - + registration.getPlugin().getDescription().getFullName(), ex); - } - } - } } diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java index 3afdd18..5edcfa0 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java @@ -2,7 +2,6 @@ package buttondevteam.discordplugin.mcchat; import buttondevteam.discordplugin.DiscordConnectedPlayer; import buttondevteam.discordplugin.DiscordPlayer; -import buttondevteam.discordplugin.listeners.MCListener; import buttondevteam.lib.player.TBMCPlayer; import lombok.val; import org.bukkit.Bukkit; @@ -52,4 +51,11 @@ public class MCChatPrivate { return lastmsgPerUser.stream() .anyMatch(lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(did)); } + + public static void logoutAll() { + for (val entry : MCChatUtils.ConnectedSenders.entrySet()) + for (val valueEntry : entry.getValue().entrySet()) + MCListener.callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); + MCChatUtils.ConnectedSenders.clear(); + } } diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java index e700b9a..cb476a2 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java @@ -1,5 +1,6 @@ package buttondevteam.discordplugin.mcchat; +import buttondevteam.core.ComponentManager; import buttondevteam.discordplugin.*; import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule; import buttondevteam.lib.TBMCSystemChatEvent; @@ -7,6 +8,7 @@ import buttondevteam.lib.chat.Channel; import io.netty.util.collection.LongObjectHashMap; import lombok.RequiredArgsConstructor; import lombok.experimental.var; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import sx.blah.discord.handle.obj.IChannel; import sx.blah.discord.handle.obj.IMessage; @@ -17,6 +19,7 @@ import java.util.HashMap; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Supplier; +import java.util.stream.Collectors; import java.util.stream.Stream; public class MCChatUtils { @@ -29,9 +32,36 @@ public class MCChatUtils { * May contain P<DiscordID> as key for public chat */ public static final HashMap> OnlineSenders = new HashMap<>(); - static LastMsgData lastmsgdata; + static @Nullable LastMsgData lastmsgdata; static LongObjectHashMap lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks + public static void updatePlayerList() { + if (notEnabled()) return; + DPUtils.performNoWait(() -> { + if (lastmsgdata != null) + updatePL(lastmsgdata); + MCChatCustom.lastmsgCustom.forEach(MCChatUtils::updatePL); + }); + } + + private static boolean notEnabled() { + return !ComponentManager.isEnabled(MinecraftChatModule.class); + } + + private static void updatePL(LastMsgData lmd) { + String topic = lmd.channel.getTopic(); + if (topic.length() == 0) + topic = ".\n----\nMinecraft chat\n----\n."; + String[] s = topic.split("\\n----\\n"); + if (s.length < 3) + return; + s[0] = Bukkit.getOnlinePlayers().size() + " player" + (Bukkit.getOnlinePlayers().size() != 1 ? "s" : "") + + " online"; + s[s.length - 1] = "Players: " + Bukkit.getOnlinePlayers().stream() + .map(p -> DPUtils.sanitizeString(p.getDisplayName())).collect(Collectors.joining(", ")); + lmd.channel.changeTopic(String.join("\n----\n", s)); + } + public static T addSender(HashMap> senders, IUser user, T sender) { return addSender(senders, user.getStringID(), sender); @@ -64,6 +94,7 @@ public class MCChatUtils { } public static void forAllMCChat(Consumer action) { + if (notEnabled()) return; action.accept(DiscordPlugin.chatchannel); for (LastMsgData data : MCChatPrivate.lastmsgPerUser) action.accept(data.channel); @@ -78,6 +109,7 @@ public class MCChatUtils { * @param hookmsg Whether the message is also sent from the hook */ public static void forCustomAndAllMCChat(Consumer action, @Nullable ChannelconBroadcast toggle, boolean hookmsg) { + if (notEnabled()) return; if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg) forAllMCChat(action); final Consumer customLMDConsumer = cc -> action.accept(cc.channel); @@ -95,6 +127,7 @@ public class MCChatUtils { * @param toggle The toggle to check or null to send to all allowed */ public static void forAllowedCustomMCChat(Consumer action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle) { + if (notEnabled()) return; MCChatCustom.lastmsgCustom.stream().filter(clmd -> { //new TBMCChannelConnectFakeEvent(sender, clmd.mcchannel).shouldSendTo(clmd.dcp) - Thought it was this simple hehe - Wait, it *should* be this simple if (toggle != null && (clmd.toggles & toggle.flag) == 0) @@ -114,6 +147,7 @@ public class MCChatUtils { * @param hookmsg Whether the message is also sent from the hook */ public static void forAllowedCustomAndAllMCChat(Consumer action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle, boolean hookmsg) { + if (notEnabled()) return; if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg) forAllMCChat(action); forAllowedCustomMCChat(action, sender, toggle); @@ -124,6 +158,7 @@ public class MCChatUtils { } public static void forAllowedMCChat(Consumer action, TBMCSystemChatEvent event) { + if (notEnabled()) return; if (event.getChannel().isGlobal()) action.accept(DiscordPlugin.chatchannel); for (LastMsgData data : MCChatPrivate.lastmsgPerUser) @@ -156,6 +191,7 @@ public class MCChatUtils { * @param channel The channel to reset in - the process is slightly different for the public, private and custom chats */ public static void resetLastMessage(IChannel channel) { + if (notEnabled()) return; if (channel.getLongID() == DiscordPlugin.chatchannel.getLongID()) { (lastmsgdata == null ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null) : lastmsgdata).message = null; diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java new file mode 100644 index 0000000..1824ef8 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java @@ -0,0 +1,184 @@ +package buttondevteam.discordplugin.mcchat; + +import buttondevteam.discordplugin.*; +import buttondevteam.discordplugin.commands.ConnectCommand; +import buttondevteam.lib.TBMCSystemChatEvent; +import buttondevteam.lib.player.TBMCPlayerJoinEvent; +import buttondevteam.lib.player.TBMCPlayerQuitEvent; +import buttondevteam.lib.player.TBMCYEEHAWEvent; +import lombok.val; +import net.ess3.api.events.AfkStatusChangeEvent; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.*; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerLoginEvent.Result; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.server.BroadcastMessageEvent; +import org.bukkit.plugin.AuthorNagException; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.RegisteredListener; +import sx.blah.discord.handle.obj.IUser; + +import java.util.Arrays; +import java.util.logging.Level; + +class MCListener implements Listener { + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerLogin(PlayerLoginEvent e) { + if (e.getResult() != Result.ALLOWED) + return; + MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) //Only private mcchat should be in ConnectedSenders + .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() + .ifPresent(dcp -> callEventExcludingSome(new PlayerQuitEvent(dcp, ""))); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerJoin(TBMCPlayerJoinEvent e) { + if (e.getPlayer() instanceof DiscordConnectedPlayer) + return; // Don't show the joined message for the fake player + Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> { + final Player p = e.getPlayer(); + DiscordPlayer dp = e.GetPlayer().getAs(DiscordPlayer.class); + if (dp != null) { + val user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID())); + MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(), + new DiscordPlayerSender(user, user.getOrCreatePMChannel(), p)); + MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(), + new DiscordPlayerSender(user, DiscordPlugin.chatchannel, p)); //Stored per-channel + } + if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) { + IUser user = DiscordPlugin.dc + .getUserByID(Long.parseLong(ConnectCommand.WaitingToConnect.get(e.GetPlayer().PlayerName().get()))); + p.sendMessage("§bTo connect with the Discord account @" + user.getName() + "#" + user.getDiscriminator() + + " do /discord accept"); + p.sendMessage("§bIf it wasn't you, do /discord decline"); + } + final String message = e.GetPlayer().PlayerName().get() + " joined the game"; + MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true); + MCChatListener.ListC = 0; + ChromaBot.getInstance().updatePlayerList(); + }); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerLeave(TBMCPlayerQuitEvent e) { + if (e.getPlayer() instanceof DiscordConnectedPlayer) + return; // Only care about real users + MCChatUtils.OnlineSenders.entrySet() + .removeIf(entry -> entry.getValue().entrySet().stream().anyMatch(p -> p.getValue().getUniqueId().equals(e.getPlayer().getUniqueId()))); + Bukkit.getScheduler().runTask(DiscordPlugin.plugin, + () -> MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) + .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() + .ifPresent(dcp -> callEventExcludingSome(new PlayerJoinEvent(dcp, "")))); + Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, + ChromaBot.getInstance()::updatePlayerList, 5); + final String message = e.GetPlayer().PlayerName().get() + " left the game"; + MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerKick(PlayerKickEvent e) { + /*if (!DiscordPlugin.hooked && !e.getReason().equals("The server is restarting") + && !e.getReason().equals("Server closed")) // The leave messages errored with the previous setup, I could make it wait since I moved it here, but instead I have a special + MCChatListener.forAllowedCustomAndAllMCChat(e.getPlayer().getName() + " left the game"); // message for this - Oh wait this doesn't even send normally because of the hook*/ + } + + @EventHandler(priority = EventPriority.LOW) + public void onPlayerDeath(PlayerDeathEvent e) { + MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(e.getDeathMessage()), e.getEntity(), ChannelconBroadcast.DEATH, true); + } + + @EventHandler + public void onPlayerAFK(AfkStatusChangeEvent e) { + final Player base = e.getAffected().getBase(); + if (e.isCancelled() || !base.isOnline()) + return; + final String msg = base.getDisplayName() + + " is " + (e.getValue() ? "now" : "no longer") + " AFK."; + MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(msg), base, ChannelconBroadcast.AFK, false); + } + + @EventHandler + public void onChatSystemMessage(TBMCSystemChatEvent event) { + MCChatUtils.forAllowedMCChat(MCChatUtils.send(event.getMessage()), event); + } + + @EventHandler + public void onBroadcastMessage(BroadcastMessageEvent event) { + MCChatUtils.forCustomAndAllMCChat(MCChatUtils.send(event.getMessage()), ChannelconBroadcast.BROADCAST, false); + } + + @EventHandler + public void onYEEHAW(TBMCYEEHAWEvent event) { //TODO: Inherit from the chat event base to have channel support + String name = event.getSender() instanceof Player ? ((Player) event.getSender()).getDisplayName() + : event.getSender().getName(); + //Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO + MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s")); + } + + private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises"}; + + static void callEventExcludingSome(Event event) { + callEventExcluding(event, EXCLUDED_PLUGINS); + } + + /** + * Calls an event with the given details. + *

+ * This method only synchronizes when the event is not asynchronous. + * + * @param event Event details + * @param plugins The plugins to exclude. Not case sensitive. + */ + private static void callEventExcluding(Event event, String... plugins) { // Copied from Spigot-API and modified a bit + if (event.isAsynchronous()) { + if (Thread.holdsLock(Bukkit.getPluginManager())) { + throw new IllegalStateException( + event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); + } + if (Bukkit.getServer().isPrimaryThread()) { + throw new IllegalStateException( + event.getEventName() + " cannot be triggered asynchronously from primary server thread."); + } + fireEventExcluding(event, plugins); + } else { + synchronized (Bukkit.getPluginManager()) { + fireEventExcluding(event, plugins); + } + } + } + + private static void fireEventExcluding(Event event, String... plugins) { + HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API + RegisteredListener[] listeners = handlers.getRegisteredListeners(); + val server = Bukkit.getServer(); + + for (RegisteredListener registration : listeners) { + if (!registration.getPlugin().isEnabled() + || Arrays.stream(plugins).anyMatch(p -> p.equalsIgnoreCase(registration.getPlugin().getName()))) + continue; // Modified to exclude plugins + + try { + registration.callEvent(event); + } catch (AuthorNagException ex) { + Plugin plugin = registration.getPlugin(); + + if (plugin.isNaggable()) { + plugin.setNaggable(false); + + server.getLogger().log(Level.SEVERE, + String.format("Nag author(s): '%s' of '%s' about the following: %s", + plugin.getDescription().getAuthors(), plugin.getDescription().getFullName(), + ex.getMessage())); + } + } catch (Throwable ex) { + server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + + registration.getPlugin().getDescription().getFullName(), ex); + } + } + } +} diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java index 4c84bdf..12ddb78 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java @@ -10,6 +10,7 @@ public class MinecraftChatModule extends Component { MCChatListener mcchat = new MCChatListener(); DiscordPlugin.dc.getDispatcher().registerListener(mcchat); TBMCCoreAPI.RegisterEventsForExceptions(mcchat, getPlugin()); + TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), getPlugin()); } @Override From e29e6f1682dd9a092070d96baf2ffe7da26bb9b8 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 23 Dec 2018 00:39:27 +0100 Subject: [PATCH 07/12] First version of new events stuff Actually registered the debug message listener --- .../discordplugin/AsyncDiscordEvent.java | 27 +++++++ .../discordplugin/DiscordPlugin.java | 4 +- .../DebugMessageListener.java | 2 +- .../ExceptionListenerModule.java} | 20 ++++- .../listeners/CommandListener.java | 27 +++++++ .../listeners/CommonListeners.java | 7 ++ .../discordplugin/listeners/MCListener.java | 73 ++++++++++++++++++ .../discordplugin/mcchat/MCListener.java | 76 ++----------------- 8 files changed, 159 insertions(+), 77 deletions(-) create mode 100644 src/main/java/buttondevteam/discordplugin/AsyncDiscordEvent.java rename src/main/java/buttondevteam/discordplugin/{listeners => exceptions}/DebugMessageListener.java (91%) rename src/main/java/buttondevteam/discordplugin/{listeners/ExceptionListener.java => exceptions/ExceptionListenerModule.java} (79%) create mode 100644 src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java diff --git a/src/main/java/buttondevteam/discordplugin/AsyncDiscordEvent.java b/src/main/java/buttondevteam/discordplugin/AsyncDiscordEvent.java new file mode 100644 index 0000000..c4479f3 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/AsyncDiscordEvent.java @@ -0,0 +1,27 @@ +package buttondevteam.discordplugin; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +@RequiredArgsConstructor +public class AsyncDiscordEvent extends Event implements Cancellable { + private final @Getter T event; + @Getter + @Setter + private boolean cancelled; + + private static final HandlerList handlers = new HandlerList(); + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index da87790..9870d99 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -2,8 +2,8 @@ package buttondevteam.discordplugin; import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule; import buttondevteam.discordplugin.commands.DiscordCommandBase; +import buttondevteam.discordplugin.exceptions.ExceptionListenerModule; import buttondevteam.discordplugin.listeners.CommonListeners; -import buttondevteam.discordplugin.listeners.ExceptionListener; import buttondevteam.discordplugin.listeners.MCListener; import buttondevteam.discordplugin.mcchat.*; import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase; @@ -217,7 +217,7 @@ public class DiscordPlugin extends ButtonPlugin implements IListener dc.getDispatcher().registerListener(listener); Component.registerComponent(this, new GeneralEventBroadcasterModule()); Component.registerComponent(this, new MinecraftChatModule()); - Bukkit.getPluginManager().registerEvents(new ExceptionListener(), this); + Component.registerComponent(this, new ExceptionListenerModule()); TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this); TBMCChatAPI.AddCommands(this, DiscordMCCommandBase.class); TBMCCoreAPI.RegisterUserClass(DiscordPlayer.class); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/DebugMessageListener.java b/src/main/java/buttondevteam/discordplugin/exceptions/DebugMessageListener.java similarity index 91% rename from src/main/java/buttondevteam/discordplugin/listeners/DebugMessageListener.java rename to src/main/java/buttondevteam/discordplugin/exceptions/DebugMessageListener.java index 1e163c4..cca3e98 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/DebugMessageListener.java +++ b/src/main/java/buttondevteam/discordplugin/exceptions/DebugMessageListener.java @@ -1,4 +1,4 @@ -package buttondevteam.discordplugin.listeners; +package buttondevteam.discordplugin.exceptions; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.lib.TBMCDebugMessageEvent; diff --git a/src/main/java/buttondevteam/discordplugin/listeners/ExceptionListener.java b/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java similarity index 79% rename from src/main/java/buttondevteam/discordplugin/listeners/ExceptionListener.java rename to src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java index 549bb97..f491a24 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/ExceptionListener.java +++ b/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java @@ -1,9 +1,12 @@ -package buttondevteam.discordplugin.listeners; +package buttondevteam.discordplugin.exceptions; +import buttondevteam.core.ComponentManager; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCExceptionEvent; +import buttondevteam.lib.architecture.Component; import org.apache.commons.lang.exception.ExceptionUtils; +import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import sx.blah.discord.handle.obj.IRole; @@ -13,13 +16,13 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -public class ExceptionListener implements Listener { +public class ExceptionListenerModule extends Component implements Listener { private List lastthrown = new ArrayList<>(); private List lastsourcemsg = new ArrayList<>(); @EventHandler public void onException(TBMCExceptionEvent e) { - if (DiscordPlugin.SafeMode) + if (DiscordPlugin.SafeMode || !ComponentManager.isEnabled(getClass())) return; if (lastthrown.stream() .anyMatch(ex -> Arrays.equals(e.getException().getStackTrace(), ex.getStackTrace()) @@ -59,4 +62,15 @@ public class ExceptionListener implements Listener { ex.printStackTrace(); } } + + @Override + protected void enable() { + Bukkit.getPluginManager().registerEvents(new ExceptionListenerModule(), getPlugin()); + TBMCCoreAPI.RegisterEventsForExceptions(new DebugMessageListener(), getPlugin()); + } + + @Override + protected void disable() { + + } } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java new file mode 100644 index 0000000..891edf5 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java @@ -0,0 +1,27 @@ +package buttondevteam.discordplugin.listeners; + +import buttondevteam.discordplugin.AsyncDiscordEvent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import sx.blah.discord.api.events.Event; +import sx.blah.discord.handle.impl.events.guild.channel.message.MentionEvent; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; + +public class CommandListener implements Listener { + @SuppressWarnings("unchecked") + @EventHandler + public void onEvent(AsyncDiscordEvent event_) { + if (event_.getEvent() instanceof MentionEvent) + onMention((AsyncDiscordEvent) event_); + else if (event_.getEvent() instanceof MessageReceivedEvent) + onMessageReceived((AsyncDiscordEvent) event_); + } + + private void onMention(AsyncDiscordEvent event) { + //TODO: Can't use priorities with this + } + + private void onMessageReceived(AsyncDiscordEvent event) { + + } +} diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java index 737e5cf..800c40d 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java @@ -1,5 +1,6 @@ package buttondevteam.discordplugin.listeners; +import buttondevteam.discordplugin.AsyncDiscordEvent; import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.commands.DiscordCommandBase; @@ -8,6 +9,7 @@ import buttondevteam.discordplugin.mcchat.MCChatPrivate; import buttondevteam.lib.TBMCCoreAPI; import lombok.val; import org.bukkit.Bukkit; +import sx.blah.discord.api.events.Event; import sx.blah.discord.api.events.IListener; import sx.blah.discord.handle.impl.events.guild.channel.message.MentionEvent; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; @@ -63,6 +65,10 @@ public class CommonListeners { list.add(i); } + private static void callDiscordEvent(Event event) { + MCListener.callEventExcluding(new AsyncDiscordEvent(event), true, "DiscordPlugin"); + } + private static long lasttime = 0; public static IListener[] getListeners() { @@ -71,6 +77,7 @@ public class CommonListeners { public void handle(MentionEvent event) { if (DiscordPlugin.SafeMode) return; + callDiscordEvent(event); if (event.getMessage().getAuthor().isBot()) return; final IChannel channel = event.getMessage().getChannel(); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java index 89b4e17..a01e727 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java @@ -12,17 +12,27 @@ import buttondevteam.lib.player.TBMCPlayerBase; import buttondevteam.lib.player.TBMCPlayerGetInfoEvent; import buttondevteam.lib.player.TBMCYEEHAWEvent; import com.earth2me.essentials.CommandSource; +import lombok.val; import net.ess3.api.events.MuteStatusChangeEvent; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.event.Event; import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.server.BroadcastMessageEvent; import org.bukkit.event.server.ServerCommandEvent; +import org.bukkit.plugin.AuthorNagException; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.RegisteredListener; import sx.blah.discord.handle.obj.IRole; import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.util.DiscordException; import sx.blah.discord.util.MissingPermissionsException; +import java.util.Arrays; +import java.util.logging.Level; + public class MCListener implements Listener { @EventHandler public void onGetInfo(TBMCPlayerGetInfoEvent e) { @@ -85,4 +95,67 @@ public class MCListener implements Listener { //Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s")); } + + private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises"}; + + public static void callEventExcludingSome(Event event) { + callEventExcluding(event, false, EXCLUDED_PLUGINS); + } + + /** + * Calls an event with the given details. + *

+ * This method only synchronizes when the event is not asynchronous. + * + * @param event Event details + * @param only Flips the operation and includes the listed plugins + * @param plugins The plugins to exclude. Not case sensitive. + */ + public static void callEventExcluding(Event event, boolean only, String... plugins) { // Copied from Spigot-API and modified a bit + if (event.isAsynchronous()) { + if (Thread.holdsLock(Bukkit.getPluginManager())) { + throw new IllegalStateException( + event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); + } + if (Bukkit.getServer().isPrimaryThread()) { + throw new IllegalStateException( + event.getEventName() + " cannot be triggered asynchronously from primary server thread."); + } + fireEventExcluding(event, only, plugins); + } else { + synchronized (Bukkit.getPluginManager()) { + fireEventExcluding(event, only, plugins); + } + } + } + + private static void fireEventExcluding(Event event, boolean only, String... plugins) { + HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API + RegisteredListener[] listeners = handlers.getRegisteredListeners(); + val server = Bukkit.getServer(); + + for (RegisteredListener registration : listeners) { + if (!registration.getPlugin().isEnabled() + || Arrays.stream(plugins).anyMatch(p -> only ^ p.equalsIgnoreCase(registration.getPlugin().getName()))) + continue; // Modified to exclude plugins + + try { + registration.callEvent(event); + } catch (AuthorNagException ex) { + Plugin plugin = registration.getPlugin(); + + if (plugin.isNaggable()) { + plugin.setNaggable(false); + + server.getLogger().log(Level.SEVERE, + String.format("Nag author(s): '%s' of '%s' about the following: %s", + plugin.getDescription().getAuthors(), plugin.getDescription().getFullName(), + ex.getMessage())); + } + } catch (Throwable ex) { + server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + + registration.getPlugin().getDescription().getFullName(), ex); + } + } + } } diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java index 1824ef8..9b419e9 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java @@ -10,7 +10,9 @@ import lombok.val; import net.ess3.api.events.AfkStatusChangeEvent; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.event.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerKickEvent; @@ -18,14 +20,8 @@ import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent.Result; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.server.BroadcastMessageEvent; -import org.bukkit.plugin.AuthorNagException; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.RegisteredListener; import sx.blah.discord.handle.obj.IUser; -import java.util.Arrays; -import java.util.logging.Level; - class MCListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerLogin(PlayerLoginEvent e) { @@ -33,7 +29,7 @@ class MCListener implements Listener { return; MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) //Only private mcchat should be in ConnectedSenders .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() - .ifPresent(dcp -> callEventExcludingSome(new PlayerQuitEvent(dcp, ""))); + .ifPresent(dcp -> buttondevteam.discordplugin.listeners.MCListener.callEventExcludingSome(new PlayerQuitEvent(dcp, ""))); } @EventHandler(priority = EventPriority.LOWEST) @@ -73,7 +69,7 @@ class MCListener implements Listener { Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() - .ifPresent(dcp -> callEventExcludingSome(new PlayerJoinEvent(dcp, "")))); + .ifPresent(dcp -> buttondevteam.discordplugin.listeners.MCListener.callEventExcludingSome(new PlayerJoinEvent(dcp, "")))); Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, ChromaBot.getInstance()::updatePlayerList, 5); final String message = e.GetPlayer().PlayerName().get() + " left the game"; @@ -119,66 +115,4 @@ class MCListener implements Listener { //Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s")); } - - private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises"}; - - static void callEventExcludingSome(Event event) { - callEventExcluding(event, EXCLUDED_PLUGINS); - } - - /** - * Calls an event with the given details. - *

- * This method only synchronizes when the event is not asynchronous. - * - * @param event Event details - * @param plugins The plugins to exclude. Not case sensitive. - */ - private static void callEventExcluding(Event event, String... plugins) { // Copied from Spigot-API and modified a bit - if (event.isAsynchronous()) { - if (Thread.holdsLock(Bukkit.getPluginManager())) { - throw new IllegalStateException( - event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); - } - if (Bukkit.getServer().isPrimaryThread()) { - throw new IllegalStateException( - event.getEventName() + " cannot be triggered asynchronously from primary server thread."); - } - fireEventExcluding(event, plugins); - } else { - synchronized (Bukkit.getPluginManager()) { - fireEventExcluding(event, plugins); - } - } - } - - private static void fireEventExcluding(Event event, String... plugins) { - HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API - RegisteredListener[] listeners = handlers.getRegisteredListeners(); - val server = Bukkit.getServer(); - - for (RegisteredListener registration : listeners) { - if (!registration.getPlugin().isEnabled() - || Arrays.stream(plugins).anyMatch(p -> p.equalsIgnoreCase(registration.getPlugin().getName()))) - continue; // Modified to exclude plugins - - try { - registration.callEvent(event); - } catch (AuthorNagException ex) { - Plugin plugin = registration.getPlugin(); - - if (plugin.isNaggable()) { - plugin.setNaggable(false); - - server.getLogger().log(Level.SEVERE, - String.format("Nag author(s): '%s' of '%s' about the following: %s", - plugin.getDescription().getAuthors(), plugin.getDescription().getFullName(), - ex.getMessage())); - } - } catch (Throwable ex) { - server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " - + registration.getPlugin().getDescription().getFullName(), ex); - } - } - } } From 7a6b79365fb0bab7199261458718d9c8c031df9a Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 23 Dec 2018 03:22:50 +0100 Subject: [PATCH 08/12] Another version of the events stuff It directly calls the methods in the modules Also made a fun module --- .../commands/DiscordCommandBase.java | 1 + .../discordplugin/fun/FunModule.java | 86 ++++++ .../listeners/CommandListener.java | 86 ++++-- .../listeners/CommonListeners.java | 288 ++++++------------ .../listeners/DiscordListener.java | 4 + .../{commands => mcchat}/MCChatCommand.java | 6 +- .../discordplugin/mcchat/MCChatListener.java | 27 +- .../mcchat/MinecraftChatModule.java | 12 +- 8 files changed, 273 insertions(+), 237 deletions(-) create mode 100644 src/main/java/buttondevteam/discordplugin/fun/FunModule.java create mode 100644 src/main/java/buttondevteam/discordplugin/listeners/DiscordListener.java rename src/main/java/buttondevteam/discordplugin/{commands => mcchat}/MCChatCommand.java (91%) diff --git a/src/main/java/buttondevteam/discordplugin/commands/DiscordCommandBase.java b/src/main/java/buttondevteam/discordplugin/commands/DiscordCommandBase.java index a4da021..45f175f 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/DiscordCommandBase.java +++ b/src/main/java/buttondevteam/discordplugin/commands/DiscordCommandBase.java @@ -1,6 +1,7 @@ package buttondevteam.discordplugin.commands; import buttondevteam.discordplugin.DiscordPlugin; +import buttondevteam.discordplugin.mcchat.MCChatCommand; import buttondevteam.lib.TBMCCoreAPI; import sx.blah.discord.handle.obj.IMessage; diff --git a/src/main/java/buttondevteam/discordplugin/fun/FunModule.java b/src/main/java/buttondevteam/discordplugin/fun/FunModule.java new file mode 100644 index 0000000..5dea2d3 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/fun/FunModule.java @@ -0,0 +1,86 @@ +package buttondevteam.discordplugin.fun; + +import buttondevteam.core.ComponentManager; +import buttondevteam.discordplugin.DiscordPlugin; +import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.architecture.Component; +import buttondevteam.lib.architecture.ConfigData; +import sx.blah.discord.handle.obj.IMessage; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +public class FunModule extends Component { + private static FunModule mod; + + private static final String[] serverReadyStrings = new String[]{"In one week from now", // Ali + "Between now and the heat-death of the universe.", // Ghostise + "Soon™", "Ask again this time next month", // Ghostise + "In about 3 seconds", // Nicolai + "After we finish 8 plugins", // Ali + "Tomorrow.", // Ali + "After one tiiiny feature", // Ali + "Next commit", // Ali + "After we finish strangling Towny", // Ali + "When we kill every *fucking* bug", // Ali + "Once the server stops screaming.", // Ali + "After HL3 comes out", // Ali + "Next time you ask", // Ali + "When will *you* be open?" // Ali + }; + + private ConfigData serverReady() { + return getData("serverReady", true); + } + + private ConfigData> serverReadyAnswers() { + return getData("serverReadyAnswers", Arrays.asList(serverReadyStrings), + data -> (List) data, data -> data); //TODO: Test + } + + private static final String[] serverReadyQuestions = new String[]{"when will the server be open", + "when will the server be ready", "when will the server be done", "when will the server be complete", + "when will the server be finished", "when's the server ready", "when's the server open", + "Vhen vill ze server be open?"}; + + private static final Random serverReadyRandom = new Random(); + private static final ArrayList usableServerReadyStrings = new ArrayList(serverReadyStrings.length) { + private static final long serialVersionUID = 2213771460909848770L; + + { + createUsableServerReadyStrings(this); + } + }; + + private static void createUsableServerReadyStrings(ArrayList list) { + for (short i = 0; i < serverReadyStrings.length; i++) + list.add(i); + } + + @Override + protected void enable() { + mod = this; + } + + @Override + protected void disable() { + } + + public static boolean executeMemes(IMessage message) { + if (!ComponentManager.isEnabled(FunModule.class)) return false; + if (mod.serverReady().get()) { + if (!TBMCCoreAPI.IsTestServer() + && Arrays.stream(serverReadyQuestions).anyMatch(s -> message.getContent().toLowerCase().contains(s))) { + int next; + if (usableServerReadyStrings.size() == 0) + createUsableServerReadyStrings(usableServerReadyStrings); + next = usableServerReadyStrings.remove(serverReadyRandom.nextInt(usableServerReadyStrings.size())); + DiscordPlugin.sendMessageToChannel(message.getChannel(), serverReadyStrings[next]); + return true; + } + } + return false; + } +} diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java index 891edf5..d1d9386 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java @@ -1,27 +1,73 @@ package buttondevteam.discordplugin.listeners; -import buttondevteam.discordplugin.AsyncDiscordEvent; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import sx.blah.discord.api.events.Event; -import sx.blah.discord.handle.impl.events.guild.channel.message.MentionEvent; -import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import buttondevteam.discordplugin.DiscordPlugin; +import buttondevteam.discordplugin.commands.DiscordCommandBase; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IMessage; -public class CommandListener implements Listener { - @SuppressWarnings("unchecked") - @EventHandler - public void onEvent(AsyncDiscordEvent event_) { - if (event_.getEvent() instanceof MentionEvent) - onMention((AsyncDiscordEvent) event_); - else if (event_.getEvent() instanceof MessageReceivedEvent) - onMessageReceived((AsyncDiscordEvent) event_); +public class CommandListener { + /** + * Runs a ChromaBot command. If mentionedonly is false, it will only execute the command if it was in #bot with the correct prefix or in private. + * + * @param message The Discord message + * @param mentionedonly Only run the command if ChromaBot is mentioned at the start of the message + * @return Whether it ran the command + */ + public static boolean runCommand(IMessage message, boolean mentionedonly) { + final IChannel channel = message.getChannel(); + if (mentionedonly) { + if (!channel.getStringID().equals(DiscordPlugin.botchannel.getStringID()) + && !message.getContent().contains("channelcon")) //Allow channelcon in other servers + return false; //Private chat is handled without mentions + } else { + if (!message.getChannel().isPrivate() + && !(message.getContent().startsWith("/") + && channel.getStringID().equals(DiscordPlugin.botchannel.getStringID()))) // + return false; + } + message.getChannel().setTypingStatus(true); // Fun + final StringBuilder cmdwithargs = new StringBuilder(message.getContent()); + final String mention = DiscordPlugin.dc.getOurUser().mention(false); + final String mentionNick = DiscordPlugin.dc.getOurUser().mention(true); + boolean gotmention = checkanddeletemention(cmdwithargs, mention, message); + gotmention = checkanddeletemention(cmdwithargs, mentionNick, message) || gotmention; + for (String mentionRole : (Iterable) message.getRoleMentions().stream().filter(r -> DiscordPlugin.dc.getOurUser().hasRole(r)).map(r -> r.mention())::iterator) + gotmention = checkanddeletemention(cmdwithargs, mentionRole, message) || gotmention; // Delete all mentions + if (mentionedonly && !gotmention) { + message.getChannel().setTypingStatus(false); + return false; + } + message.getChannel().setTypingStatus(true); + String cmdwithargsString = cmdwithargs.toString().trim(); //Remove spaces between mention and command + int index = cmdwithargsString.indexOf(" "); + String cmd; + String args; + if (index == -1) { + cmd = cmdwithargsString; + args = ""; + } else { + cmd = cmdwithargsString.substring(0, index); + args = cmdwithargsString.substring(index + 1).trim(); //In case there are multiple spaces + } + DiscordCommandBase.runCommand(cmd.toLowerCase(), args, message); + message.getChannel().setTypingStatus(false); + return true; } - private void onMention(AsyncDiscordEvent event) { - //TODO: Can't use priorities with this - } - - private void onMessageReceived(AsyncDiscordEvent event) { - + private static boolean checkanddeletemention(StringBuilder cmdwithargs, String mention, IMessage message) { + if (message.getContent().startsWith(mention)) // TODO: Resolve mentions: Compound arguments, either a mention or text + if (cmdwithargs.length() > mention.length() + 1) + cmdwithargs.delete(0, + cmdwithargs.charAt(mention.length()) == ' ' ? mention.length() + 1 : mention.length()); + else + cmdwithargs.replace(0, cmdwithargs.length(), "help"); + else { + if (cmdwithargs.length() > 0 && cmdwithargs.charAt(0) == '/') + cmdwithargs.deleteCharAt(0); //Don't treat / as mention, mentions can be used in public mcchat + return false; + } + if (cmdwithargs.length() == 0) + cmdwithargs.replace(0, cmdwithargs.length(), "help"); + return true; } } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java index 800c40d..92cf74b 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java @@ -1,15 +1,11 @@ package buttondevteam.discordplugin.listeners; -import buttondevteam.discordplugin.AsyncDiscordEvent; import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordPlugin; -import buttondevteam.discordplugin.commands.DiscordCommandBase; -import buttondevteam.discordplugin.mcchat.MCChatCustom; -import buttondevteam.discordplugin.mcchat.MCChatPrivate; -import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.discordplugin.mcchat.MinecraftChatModule; +import buttondevteam.lib.architecture.Component; import lombok.val; import org.bukkit.Bukkit; -import sx.blah.discord.api.events.Event; import sx.blah.discord.api.events.IListener; import sx.blah.discord.handle.impl.events.guild.channel.message.MentionEvent; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; @@ -17,195 +13,112 @@ import sx.blah.discord.handle.impl.events.guild.role.RoleCreateEvent; import sx.blah.discord.handle.impl.events.guild.role.RoleDeleteEvent; import sx.blah.discord.handle.impl.events.guild.role.RoleUpdateEvent; import sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent; -import sx.blah.discord.handle.obj.IChannel; -import sx.blah.discord.handle.obj.IMessage; import sx.blah.discord.handle.obj.StatusType; import sx.blah.discord.util.EmbedBuilder; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; -import java.util.Random; import java.util.concurrent.TimeUnit; public class CommonListeners { - private static final String[] serverReadyStrings = new String[]{"In one week from now", // Ali - "Between now and the heat-death of the universe.", // Ghostise - "Soon™", "Ask again this time next month", // Ghostise - "In about 3 seconds", // Nicolai - "After we finish 8 plugins", // Ali - "Tomorrow.", // Ali - "After one tiiiny feature", // Ali - "Next commit", // Ali - "After we finish strangling Towny", // Ali - "When we kill every *fucking* bug", // Ali - "Once the server stops screaming.", // Ali - "After HL3 comes out", // Ali - "Next time you ask", // Ali - "When will *you* be open?" // Ali - }; + /*private static ArrayList dcListeners=new ArrayList<>(); - private static final String[] serverReadyQuestions = new String[]{"when will the server be open", - "when will the server be ready", "when will the server be done", "when will the server be complete", - "when will the server be finished", "when's the server ready", "when's the server open", - "Vhen vill ze server be open?"}; - - private static final Random serverReadyRandom = new Random(); - private static final ArrayList usableServerReadyStrings = new ArrayList(serverReadyStrings.length) { - private static final long serialVersionUID = 2213771460909848770L; - - { - createUsableServerReadyStrings(this); - } - }; - - private static void createUsableServerReadyStrings(ArrayList list) { - for (short i = 0; i < serverReadyStrings.length; i++) - list.add(i); + public static void registerDiscordListener(DiscordListener listener) { + //Step 1: Get all events that are handled by us + //Step 2: Find methods that handle these + //...or just simply call the methods in the right order } private static void callDiscordEvent(Event event) { - MCListener.callEventExcluding(new AsyncDiscordEvent(event), true, "DiscordPlugin"); - } + String name=event.getClass().getSimpleName(); + name=Character.toLowerCase(name.charAt(0))+name.substring(1); + for (Object listener : dcListeners) { + listener.getClass().getMethods(name, AsyncDiscordEvent.class); + } + }*/ private static long lasttime = 0; - public static IListener[] getListeners() { - return new IListener[]{new IListener() { - @Override - public void handle(MentionEvent event) { - if (DiscordPlugin.SafeMode) - return; - callDiscordEvent(event); - if (event.getMessage().getAuthor().isBot()) - return; - final IChannel channel = event.getMessage().getChannel(); - if (!channel.getStringID().equals(DiscordPlugin.botchannel.getStringID()) - && (!event.getMessage().getContent().contains("channelcon") || MCChatCustom.hasCustomChat(channel))) //Allow channelcon in other servers but avoid double handling when it's enabled - return; - if (channel.getStringID().equals(DiscordPlugin.chatchannel.getStringID())) - return; // The chat code already handles this - Right now while testing botchannel is the same as chatchannel - event.getMessage().getChannel().setTypingStatus(true); // Fun - runCommand(event.getMessage(), true); - } - }, new IListener() { - @Override - public void handle(MessageReceivedEvent event) { - if (DiscordPlugin.SafeMode) - return; - final String msglowercase = event.getMessage().getContent().toLowerCase(); - if (!TBMCCoreAPI.IsTestServer() - && Arrays.stream(serverReadyQuestions).anyMatch(s -> msglowercase.contains(s))) { - int next; - if (usableServerReadyStrings.size() == 0) - createUsableServerReadyStrings(usableServerReadyStrings); - next = usableServerReadyStrings.remove(serverReadyRandom.nextInt(usableServerReadyStrings.size())); - DiscordPlugin.sendMessageToChannel(event.getMessage().getChannel(), serverReadyStrings[next]); - return; - } - if (!event.getMessage().getChannel().isPrivate() - && !(event.getMessage().getContent().startsWith("/") - && event.getChannel().getStringID().equals(DiscordPlugin.botchannel.getStringID()))) // - return; - if (MCChatPrivate.isMinecraftChatEnabled(event.getAuthor().toString())) - if (!event.getMessage().getContent().equalsIgnoreCase("mcchat")) - return; - if (event.getMessage().getAuthor().isBot()) - return; - runCommand(event.getMessage(), false); - } - }, new IListener() { - @Override - public void handle(PresenceUpdateEvent event) { - if (DiscordPlugin.SafeMode) - return; - val devrole = DiscordPlugin.devServer.getRolesByName("Developer").get(0); - if (event.getOldPresence().getStatus().equals(StatusType.OFFLINE) - && !event.getNewPresence().getStatus().equals(StatusType.OFFLINE) - && event.getUser().getRolesForGuild(DiscordPlugin.devServer).stream() - .anyMatch(r -> r.getLongID() == devrole.getLongID()) - && DiscordPlugin.devServer.getUsersByRole(devrole).stream() - .noneMatch(u -> u.getPresence().getStatus().equals(StatusType.OFFLINE)) - && lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime()) - && Calendar.getInstance().get(Calendar.DAY_OF_MONTH) % 5 == 0) { - DiscordPlugin.sendMessageToChannel(DiscordPlugin.devofficechannel, "Full house!", - new EmbedBuilder() - .withImage( - "https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png") - .build()); - lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime()); - } - } - }, (IListener) event -> { - Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> { - if (event.getRole().isDeleted() || !DiscordPlugin.plugin.isGameRole(event.getRole())) - return; //Deleted or not a game role - DiscordPlugin.GameRoles.add(event.getRole().getName()); - DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getRole().getName() + " as game role. If you don't want this, change the role's color from the default."); - }, 100); - }, (IListener) event -> { - if (DiscordPlugin.GameRoles.remove(event.getRole().getName())) - DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getRole().getName() + " as a game role."); - }, (IListener) event -> { //Role update event - if (!DiscordPlugin.plugin.isGameRole(event.getNewRole())) { - if (DiscordPlugin.GameRoles.remove(event.getOldRole().getName())) - DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getOldRole().getName() + " as a game role because it's color changed."); - } else { - if (DiscordPlugin.GameRoles.contains(event.getOldRole().getName()) && event.getOldRole().getName().equals(event.getNewRole().getName())) - return; - boolean removed = DiscordPlugin.GameRoles.remove(event.getOldRole().getName()); //Regardless of whether it was a game role - DiscordPlugin.GameRoles.add(event.getNewRole().getName()); //Add it because it has no color - if (removed) - DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Changed game role from " + event.getOldRole().getName() + " to " + event.getNewRole().getName() + "."); - else - DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getNewRole().getName() + " as game role because it has the default color."); - } - }}; - } + /* + MentionEvent: + - CommandListener (starts with mention, in #bot unless 'channelcon') - /** - * Runs a ChromaBot command. - * - * @param message The Discord message - * @param mentionedonly Only run the command if ChromaBot is mentioned at the start of the message - * @return Whether it ran the command (always true if mentionedonly is false) - */ - public static boolean runCommand(IMessage message, boolean mentionedonly) { - debug("A"); - if (DiscordPlugin.SafeMode) - return true; - debug("B"); - final StringBuilder cmdwithargs = new StringBuilder(message.getContent()); - final String mention = DiscordPlugin.dc.getOurUser().mention(false); - final String mentionNick = DiscordPlugin.dc.getOurUser().mention(true); - boolean gotmention = checkanddeletemention(cmdwithargs, mention, message); - gotmention = checkanddeletemention(cmdwithargs, mentionNick, message) || gotmention; - for (String mentionRole : (Iterable) message.getRoleMentions().stream().filter(r -> DiscordPlugin.dc.getOurUser().hasRole(r)).map(r -> r.mention())::iterator) - gotmention = checkanddeletemention(cmdwithargs, mentionRole, message) || gotmention; // Delete all mentions - debug("C"); - if (mentionedonly && !gotmention) { - message.getChannel().setTypingStatus(false); - return false; - } - debug("D"); - message.getChannel().setTypingStatus(true); - String cmdwithargsString = cmdwithargs.toString().trim(); //Remove spaces between mention and command - int index = cmdwithargsString.indexOf(" "); - String cmd; - String args; - if (index == -1) { - cmd = cmdwithargsString; - args = ""; - } else { - cmd = cmdwithargsString.substring(0, index); - args = cmdwithargsString.substring(index + 1).trim(); //In case there are multiple spaces - } - debug("E"); - DiscordCommandBase.runCommand(cmd.toLowerCase(), args, message); - message.getChannel().setTypingStatus(false); - return true; - } + MessageReceivedEvent: + - Minecraft chat (is enabled in the channel and message isn't [/]mcchat) + - CommandListener (with the correct prefix in #bot, or in private) + */ + public static IListener[] getListeners() { + return new IListener[]{new IListener() { + @Override + public void handle(MentionEvent event) { + if (DiscordPlugin.SafeMode) + return; + if (event.getMessage().getAuthor().isBot()) + return; + CommandListener.runCommand(event.getMessage(), true); + } + }, new IListener() { + @Override + public void handle(MessageReceivedEvent event) { + if (DiscordPlugin.SafeMode) + return; + if (event.getMessage().getAuthor().isBot()) + return; + boolean handled = false; + val mcchat = Component.getComponents().get(MinecraftChatModule.class); + if (mcchat != null && mcchat.isEnabled()) + handled = ((MinecraftChatModule) mcchat).getListener().handleDiscord(event); + if (!handled) + handled = CommandListener.runCommand(event.getMessage(), false); + } + }, new IListener() { + @Override + public void handle(PresenceUpdateEvent event) { + if (DiscordPlugin.SafeMode) + return; + val devrole = DiscordPlugin.devServer.getRolesByName("Developer").get(0); + if (event.getOldPresence().getStatus().equals(StatusType.OFFLINE) + && !event.getNewPresence().getStatus().equals(StatusType.OFFLINE) + && event.getUser().getRolesForGuild(DiscordPlugin.devServer).stream() + .anyMatch(r -> r.getLongID() == devrole.getLongID()) + && DiscordPlugin.devServer.getUsersByRole(devrole).stream() + .noneMatch(u -> u.getPresence().getStatus().equals(StatusType.OFFLINE)) + && lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime()) + && Calendar.getInstance().get(Calendar.DAY_OF_MONTH) % 5 == 0) { + DiscordPlugin.sendMessageToChannel(DiscordPlugin.devofficechannel, "Full house!", + new EmbedBuilder() + .withImage( + "https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png") + .build()); + lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime()); + } + } + }, (IListener) event -> { + Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> { + if (event.getRole().isDeleted() || !DiscordPlugin.plugin.isGameRole(event.getRole())) + return; //Deleted or not a game role + DiscordPlugin.GameRoles.add(event.getRole().getName()); + DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getRole().getName() + " as game role. If you don't want this, change the role's color from the default."); + }, 100); + }, (IListener) event -> { + if (DiscordPlugin.GameRoles.remove(event.getRole().getName())) + DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getRole().getName() + " as a game role."); + }, (IListener) event -> { //Role update event + if (!DiscordPlugin.plugin.isGameRole(event.getNewRole())) { + if (DiscordPlugin.GameRoles.remove(event.getOldRole().getName())) + DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getOldRole().getName() + " as a game role because it's color changed."); + } else { + if (DiscordPlugin.GameRoles.contains(event.getOldRole().getName()) && event.getOldRole().getName().equals(event.getNewRole().getName())) + return; + boolean removed = DiscordPlugin.GameRoles.remove(event.getOldRole().getName()); //Regardless of whether it was a game role + DiscordPlugin.GameRoles.add(event.getNewRole().getName()); //Add it because it has no color + if (removed) + DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Changed game role from " + event.getOldRole().getName() + " to " + event.getNewRole().getName() + "."); + else + DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getNewRole().getName() + " as game role because it has the default color."); + } + }}; + } private static boolean debug = false; @@ -217,21 +130,4 @@ public class CommonListeners { public static boolean debug() { return debug = !debug; } - - private static boolean checkanddeletemention(StringBuilder cmdwithargs, String mention, IMessage message) { - if (message.getContent().startsWith(mention)) // TODO: Resolve mentions: Compound arguments, either a mention or text - if (cmdwithargs.length() > mention.length() + 1) - cmdwithargs.delete(0, - cmdwithargs.charAt(mention.length()) == ' ' ? mention.length() + 1 : mention.length()); - else - cmdwithargs.replace(0, cmdwithargs.length(), "help"); - else { - if (cmdwithargs.length() > 0 && cmdwithargs.charAt(0) == '/') - cmdwithargs.deleteCharAt(0); //Don't treat / as mention, mentions can be used in public mcchat - return false; - } - if (cmdwithargs.length() == 0) - cmdwithargs.replace(0, cmdwithargs.length(), "help"); - return true; - } } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/DiscordListener.java b/src/main/java/buttondevteam/discordplugin/listeners/DiscordListener.java new file mode 100644 index 0000000..292a1a1 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/listeners/DiscordListener.java @@ -0,0 +1,4 @@ +package buttondevteam.discordplugin.listeners; + +public interface DiscordListener { +} diff --git a/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatCommand.java similarity index 91% rename from src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java rename to src/main/java/buttondevteam/discordplugin/mcchat/MCChatCommand.java index 24c6390..3c05f02 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/MCChatCommand.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatCommand.java @@ -1,8 +1,8 @@ -package buttondevteam.discordplugin.commands; +package buttondevteam.discordplugin.mcchat; import buttondevteam.discordplugin.DiscordPlayer; import buttondevteam.discordplugin.DiscordPlugin; -import buttondevteam.discordplugin.mcchat.MCChatPrivate; +import buttondevteam.discordplugin.commands.DiscordCommandBase; import buttondevteam.lib.TBMCCoreAPI; import sx.blah.discord.handle.obj.IMessage; @@ -13,7 +13,7 @@ public class MCChatCommand extends DiscordCommandBase { return "mcchat"; } - @Override + @Override //TODO: Only register if module is enabled public boolean run(IMessage message, String args) { if (!message.getChannel().isPrivate()) { DiscordPlugin.sendMessageToChannel(message.getChannel(), diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java index 15489e5..67c7b0a 100755 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java @@ -5,7 +5,6 @@ import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.DiscordSender; import buttondevteam.discordplugin.DiscordSenderBase; -import buttondevteam.discordplugin.listeners.CommonListeners; import buttondevteam.discordplugin.playerfaker.VanillaCommandListener; import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatPreprocessEvent; @@ -22,7 +21,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitTask; -import sx.blah.discord.api.events.IListener; import sx.blah.discord.api.internal.json.objects.EmbedObject; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; import sx.blah.discord.handle.obj.IChannel; @@ -43,7 +41,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; -public class MCChatListener implements Listener, IListener { +public class MCChatListener implements Listener { private BukkitTask sendtask; private LinkedBlockingQueue> sendevents = new LinkedBlockingQueue<>(); private Runnable sendrunnable; @@ -231,27 +229,25 @@ public class MCChatListener implements Listener, IListener private Runnable recrun; private static Thread recthread; - @Override // Discord - TODO: Call from the common listener - public void handle(MessageReceivedEvent ev) { + // Discord + public boolean handleDiscord(MessageReceivedEvent ev) { if (!ComponentManager.isEnabled(MinecraftChatModule.class)) - return; + return false; val author = ev.getMessage().getAuthor(); - if (author.isBot()) - return; final boolean hasCustomChat = MCChatCustom.hasCustomChat(ev.getChannel()); - if (!ev.getMessage().getChannel().getStringID().equals(DiscordPlugin.chatchannel.getStringID()) + if (ev.getMessage().getChannel().getLongID() != DiscordPlugin.chatchannel.getLongID() && !(ev.getMessage().getChannel().isPrivate() && MCChatPrivate.isMinecraftChatEnabled(author.getStringID())) && !hasCustomChat) - return; - if (ev.getMessage().getContent().equalsIgnoreCase("mcchat")) - return; // Race condition: If it gets here after it enabled mcchat it says it - I might as well allow disabling with this (CommonListeners) - if (CommonListeners.runCommand(ev.getMessage(), true)) - return; + return false; //Chat isn't enabled on this channel + if (hasCustomChat && ev.getMessage().getContent().length() < "/mcchat<>".length() + && ev.getMessage().getContent().replace("/", "") + .equalsIgnoreCase("mcchat")) //Either mcchat or /mcchat + return false; //Allow disabling the chat if needed MCChatUtils.resetLastMessage(ev.getChannel()); lastlist++; recevents.add(ev); if (rectask != null) - return; + return true; recrun = () -> { //Don't return in a while loop next time recthread = Thread.currentThread(); processDiscordToMC(); @@ -259,6 +255,7 @@ public class MCChatListener implements Listener, IListener rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Continue message processing }; rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Start message processing + return true; } private void processDiscordToMC() { diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java index 12ddb78..9af7a5e 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java @@ -3,13 +3,19 @@ package buttondevteam.discordplugin.mcchat; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.Component; +import lombok.Getter; public class MinecraftChatModule extends Component { + private @Getter MCChatListener listener; + + public MCChatListener getListener() { //It doesn't want to generate + return listener; + } @Override protected void enable() { - MCChatListener mcchat = new MCChatListener(); - DiscordPlugin.dc.getDispatcher().registerListener(mcchat); - TBMCCoreAPI.RegisterEventsForExceptions(mcchat, getPlugin()); + listener = new MCChatListener(); + DiscordPlugin.dc.getDispatcher().registerListener(listener); + TBMCCoreAPI.RegisterEventsForExceptions(listener, getPlugin()); TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), getPlugin()); } From 040373280ee44ad6ed934e562f9749cbf23a44f9 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 23 Dec 2018 22:34:26 +0100 Subject: [PATCH 09/12] Everything seems to work Removed double handling of certain events in MCListeners Removed MentionEvent handling completely Some mcchat fixes --- .../commands/ChannelconCommand.java | 9 ++- .../listeners/CommandListener.java | 10 +--- .../listeners/CommonListeners.java | 23 +++----- .../discordplugin/listeners/MCListener.java | 58 ------------------- .../discordplugin/mcchat/MCChatListener.java | 3 + .../discordplugin/mcchat/MCChatPrivate.java | 8 ++- .../discordplugin/mcchat/MCChatUtils.java | 2 +- .../discordplugin/mcchat/MCListener.java | 35 ++++++++++- 8 files changed, 59 insertions(+), 89 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java b/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java index a018a1e..c89baab 100644 --- a/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java @@ -3,6 +3,7 @@ package buttondevteam.discordplugin.commands; import buttondevteam.discordplugin.ChannelconBroadcast; import buttondevteam.discordplugin.DiscordConnectedPlayer; import buttondevteam.discordplugin.DiscordPlayer; +import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.mcchat.MCChatCustom; import buttondevteam.lib.chat.Channel; import buttondevteam.lib.player.TBMCPlayer; @@ -99,10 +100,12 @@ public class ChannelconCommand extends DiscordCommandBase { "---- Channel connect ---", // "This command allows you to connect a Minecraft channel to a Discord channel (just like how the global chat is connected to #minecraft-chat).", // "You need to have access to the MC channel and have manage permissions on the Discord channel.", // - "You also need to have your Minecraft account connected. In #bot use /connect .", // - "Call this command from the channel you want to use. Usage: @ChromaBot channelcon ", // + "You also need to have your Minecraft account connected. In #bot use " + DiscordPlugin.getPrefix() + "connect .", // + "Call this command from the channel you want to use.", // + "Usage: @" + DiscordPlugin.dc.getOurUser().getName() + " channelcon ", // + "Use the ID (command) of the channel, for example `g` for the global chat.", // "To remove a connection use @ChromaBot channelcon remove in the channel.", // - "Mentioning the bot is needed in this case because the / prefix only works in #bot.", // + "Mentioning the bot is needed in this case because the " + DiscordPlugin.getPrefix() + " prefix only works in #bot.", // "Invite link: " // }; } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java index d1d9386..85f0fd4 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java @@ -15,17 +15,13 @@ public class CommandListener { */ public static boolean runCommand(IMessage message, boolean mentionedonly) { final IChannel channel = message.getChannel(); - if (mentionedonly) { - if (!channel.getStringID().equals(DiscordPlugin.botchannel.getStringID()) - && !message.getContent().contains("channelcon")) //Allow channelcon in other servers - return false; //Private chat is handled without mentions - } else { + if (!mentionedonly) { //mentionedonly conditions are in CommonListeners if (!message.getChannel().isPrivate() - && !(message.getContent().startsWith("/") + && !(message.getContent().charAt(0) == DiscordPlugin.getPrefix() && channel.getStringID().equals(DiscordPlugin.botchannel.getStringID()))) // return false; + message.getChannel().setTypingStatus(true); // Fun } - message.getChannel().setTypingStatus(true); // Fun final StringBuilder cmdwithargs = new StringBuilder(message.getContent()); final String mention = DiscordPlugin.dc.getOurUser().mention(false); final String mentionNick = DiscordPlugin.dc.getOurUser().mention(true); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java index 92cf74b..7cc3dcc 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java @@ -7,7 +7,6 @@ import buttondevteam.lib.architecture.Component; import lombok.val; import org.bukkit.Bukkit; import sx.blah.discord.api.events.IListener; -import sx.blah.discord.handle.impl.events.guild.channel.message.MentionEvent; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; import sx.blah.discord.handle.impl.events.guild.role.RoleCreateEvent; import sx.blah.discord.handle.impl.events.guild.role.RoleDeleteEvent; @@ -41,23 +40,15 @@ public class CommonListeners { /* MentionEvent: - - CommandListener (starts with mention, in #bot unless 'channelcon') + - CommandListener (starts with mention, only 'channelcon' and not in #bot) MessageReceivedEvent: + - v CommandListener (starts with mention, in #bot or a connected chat) - Minecraft chat (is enabled in the channel and message isn't [/]mcchat) - CommandListener (with the correct prefix in #bot, or in private) */ public static IListener[] getListeners() { - return new IListener[]{new IListener() { - @Override - public void handle(MentionEvent event) { - if (DiscordPlugin.SafeMode) - return; - if (event.getMessage().getAuthor().isBot()) - return; - CommandListener.runCommand(event.getMessage(), true); - } - }, new IListener() { + return new IListener[]{new IListener() { @Override public void handle(MessageReceivedEvent event) { if (DiscordPlugin.SafeMode) @@ -65,9 +56,13 @@ public class CommonListeners { if (event.getMessage().getAuthor().isBot()) return; boolean handled = false; + if (event.getChannel().getLongID() == DiscordPlugin.botchannel.getLongID() //If mentioned, that's higher than chat + || event.getMessage().getContent().contains("channelcon")) //Only 'channelcon' is allowed in other channels + handled = CommandListener.runCommand(event.getMessage(), true); //#bot is handled here + if (handled) return; val mcchat = Component.getComponents().get(MinecraftChatModule.class); - if (mcchat != null && mcchat.isEnabled()) - handled = ((MinecraftChatModule) mcchat).getListener().handleDiscord(event); + if (mcchat != null && mcchat.isEnabled()) //ComponentManager.isEnabled() searches the component again + handled = ((MinecraftChatModule) mcchat).getListener().handleDiscord(event); //Also runs Discord commands in chat channels if (!handled) handled = CommandListener.runCommand(event.getMessage(), false); } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java index a01e727..b36414d 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java @@ -1,34 +1,19 @@ package buttondevteam.discordplugin.listeners; -import buttondevteam.discordplugin.ChannelconBroadcast; -import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordPlayer; import buttondevteam.discordplugin.DiscordPlugin; -import buttondevteam.discordplugin.mcchat.MCChatUtils; -import buttondevteam.lib.TBMCCoreAPI; -import buttondevteam.lib.TBMCSystemChatEvent; -import buttondevteam.lib.player.TBMCPlayer; -import buttondevteam.lib.player.TBMCPlayerBase; import buttondevteam.lib.player.TBMCPlayerGetInfoEvent; -import buttondevteam.lib.player.TBMCYEEHAWEvent; -import com.earth2me.essentials.CommandSource; import lombok.val; -import net.ess3.api.events.MuteStatusChangeEvent; import org.bukkit.Bukkit; -import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; -import org.bukkit.event.server.BroadcastMessageEvent; import org.bukkit.event.server.ServerCommandEvent; import org.bukkit.plugin.AuthorNagException; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.RegisteredListener; -import sx.blah.discord.handle.obj.IRole; import sx.blah.discord.handle.obj.IUser; -import sx.blah.discord.util.DiscordException; -import sx.blah.discord.util.MissingPermissionsException; import java.util.Arrays; import java.util.logging.Level; @@ -53,49 +38,6 @@ public class MCListener implements Listener { DiscordPlugin.Restart = !e.getCommand().equalsIgnoreCase("stop"); // The variable is always true except if stopped } - @EventHandler - public void onPlayerMute(MuteStatusChangeEvent e) { - try { - DPUtils.performNoWait(() -> { - final IRole role = DiscordPlugin.dc.getRoleByID(164090010461667328L); - final CommandSource source = e.getAffected().getSource(); - if (!source.isPlayer()) - return; - final DiscordPlayer p = TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class) - .getAs(DiscordPlayer.class); - if (p == null) return; - final IUser user = DiscordPlugin.dc.getUserByID( - Long.parseLong(p.getDiscordID())); - if (e.getValue()) - user.addRole(role); - else - user.removeRole(role); - DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, (e.getValue() ? "M" : "Unm") + "uted user: " + user.getName()); - }); - } catch (DiscordException | MissingPermissionsException ex) { - TBMCCoreAPI.SendException("Failed to give/take Muted role to player " + e.getAffected().getName() + "!", - ex); - } - } - - @EventHandler - public void onChatSystemMessage(TBMCSystemChatEvent event) { - MCChatUtils.forAllowedMCChat(MCChatUtils.send(event.getMessage()), event); - } - - @EventHandler - public void onBroadcastMessage(BroadcastMessageEvent event) { - MCChatUtils.forCustomAndAllMCChat(MCChatUtils.send(event.getMessage()), ChannelconBroadcast.BROADCAST, false); - } - - @EventHandler - public void onYEEHAW(TBMCYEEHAWEvent event) { //TODO: Inherit from the chat event base to have channel support - String name = event.getSender() instanceof Player ? ((Player) event.getSender()).getDisplayName() - : event.getSender().getName(); - //Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO - MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s")); - } - private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises"}; public static void callEventExcludingSome(Event event) { diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java index 67c7b0a..98eb523 100755 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java @@ -5,6 +5,7 @@ import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.DiscordSender; import buttondevteam.discordplugin.DiscordSenderBase; +import buttondevteam.discordplugin.listeners.CommandListener; import buttondevteam.discordplugin.playerfaker.VanillaCommandListener; import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatPreprocessEvent; @@ -243,6 +244,8 @@ public class MCChatListener implements Listener { && ev.getMessage().getContent().replace("/", "") .equalsIgnoreCase("mcchat")) //Either mcchat or /mcchat return false; //Allow disabling the chat if needed + if (CommandListener.runCommand(ev.getMessage(), true)) + return true; //Allow running commands in chat channels MCChatUtils.resetLastMessage(ev.getChannel()); lastlist++; recevents.add(ev); diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java index 5edcfa0..8356b44 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java @@ -13,6 +13,8 @@ import sx.blah.discord.handle.obj.IUser; import java.util.ArrayList; +import static buttondevteam.discordplugin.listeners.MCListener.callEventExcludingSome; + public class MCChatPrivate { /** @@ -29,11 +31,11 @@ public class MCChatPrivate { val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName()); MCChatUtils.addSender(MCChatUtils.ConnectedSenders, user, sender); if (p == null)// Player is offline - If the player is online, that takes precedence - MCListener.callEventExcludingSome(new PlayerJoinEvent(sender, "")); + callEventExcludingSome(new PlayerJoinEvent(sender, "")); } else { val sender = MCChatUtils.removeSender(MCChatUtils.ConnectedSenders, channel, user); if (p == null)// Player is offline - If the player is online, that takes precedence - MCListener.callEventExcludingSome(new PlayerQuitEvent(sender, "")); + callEventExcludingSome(new PlayerQuitEvent(sender, "")); } } if (!start) @@ -55,7 +57,7 @@ public class MCChatPrivate { public static void logoutAll() { for (val entry : MCChatUtils.ConnectedSenders.entrySet()) for (val valueEntry : entry.getValue().entrySet()) - MCListener.callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); + callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); MCChatUtils.ConnectedSenders.clear(); } } diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java index cb476a2..6826f6e 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java @@ -50,7 +50,7 @@ public class MCChatUtils { private static void updatePL(LastMsgData lmd) { String topic = lmd.channel.getTopic(); - if (topic.length() == 0) + if (topic == null || topic.length() == 0) topic = ".\n----\nMinecraft chat\n----\n."; String[] s = topic.split("\\n----\\n"); if (s.length < 3) diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java index 9b419e9..2e2d089 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java @@ -2,12 +2,13 @@ package buttondevteam.discordplugin.mcchat; import buttondevteam.discordplugin.*; import buttondevteam.discordplugin.commands.ConnectCommand; +import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCSystemChatEvent; -import buttondevteam.lib.player.TBMCPlayerJoinEvent; -import buttondevteam.lib.player.TBMCPlayerQuitEvent; -import buttondevteam.lib.player.TBMCYEEHAWEvent; +import buttondevteam.lib.player.*; +import com.earth2me.essentials.CommandSource; import lombok.val; import net.ess3.api.events.AfkStatusChangeEvent; +import net.ess3.api.events.MuteStatusChangeEvent; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -20,7 +21,10 @@ import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent.Result; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.server.BroadcastMessageEvent; +import sx.blah.discord.handle.obj.IRole; import sx.blah.discord.handle.obj.IUser; +import sx.blah.discord.util.DiscordException; +import sx.blah.discord.util.MissingPermissionsException; class MCListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST) @@ -98,6 +102,31 @@ class MCListener implements Listener { MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(msg), base, ChannelconBroadcast.AFK, false); } + @EventHandler + public void onPlayerMute(MuteStatusChangeEvent e) { + try { + DPUtils.performNoWait(() -> { + final IRole role = DiscordPlugin.dc.getRoleByID(164090010461667328L); + final CommandSource source = e.getAffected().getSource(); + if (!source.isPlayer()) + return; + final DiscordPlayer p = TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class) + .getAs(DiscordPlayer.class); + if (p == null) return; + final IUser user = DiscordPlugin.dc.getUserByID( + Long.parseLong(p.getDiscordID())); + if (e.getValue()) + user.addRole(role); + else + user.removeRole(role); + DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, (e.getValue() ? "M" : "Unm") + "uted user: " + user.getName()); + }); + } catch (DiscordException | MissingPermissionsException ex) { + TBMCCoreAPI.SendException("Failed to give/take Muted role to player " + e.getAffected().getName() + "!", + ex); + } + } + @EventHandler public void onChatSystemMessage(TBMCSystemChatEvent event) { MCChatUtils.forAllowedMCChat(MCChatUtils.send(event.getMessage()), event); From 68e69782ee022f531967955c042f14042e94cdad Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 23 Dec 2018 23:50:13 +0100 Subject: [PATCH 10/12] Well, not everything Fixed some private mcchat issues Fixed #85 --- .../discordplugin/listeners/MCListener.java | 2 +- .../discordplugin/mcchat/MCChatListener.java | 3 ++- .../discordplugin/mcchat/MCChatPrivate.java | 14 ++++++++++---- .../discordplugin/mcchat/MCListener.java | 6 ++++++ 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java index b36414d..a39d5fc 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java @@ -38,7 +38,7 @@ public class MCListener implements Listener { DiscordPlugin.Restart = !e.getCommand().equalsIgnoreCase("stop"); // The variable is always true except if stopped } - private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises"}; + private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises", "JourneyMapServer"}; //TODO: Make configurable public static void callEventExcludingSome(Event event) { callEventExcluding(event, false, EXCLUDED_PLUGINS); diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java index 98eb523..882921b 100755 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java @@ -240,7 +240,8 @@ public class MCChatListener implements Listener { && !(ev.getMessage().getChannel().isPrivate() && MCChatPrivate.isMinecraftChatEnabled(author.getStringID())) && !hasCustomChat) return false; //Chat isn't enabled on this channel - if (hasCustomChat && ev.getMessage().getContent().length() < "/mcchat<>".length() + if (ev.getMessage().getChannel().isPrivate() //Only in private chat + && ev.getMessage().getContent().length() < "/mcchat<>".length() && ev.getMessage().getContent().replace("/", "") .equalsIgnoreCase("mcchat")) //Either mcchat or /mcchat return false; //Allow disabling the chat if needed diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java index 8356b44..99c1740 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java @@ -2,9 +2,11 @@ package buttondevteam.discordplugin.mcchat; import buttondevteam.discordplugin.DiscordConnectedPlayer; import buttondevteam.discordplugin.DiscordPlayer; +import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.lib.player.TBMCPlayer; import lombok.val; import org.bukkit.Bukkit; +import org.bukkit.event.Event; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import sx.blah.discord.handle.obj.IChannel; @@ -31,13 +33,13 @@ public class MCChatPrivate { val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName()); MCChatUtils.addSender(MCChatUtils.ConnectedSenders, user, sender); if (p == null)// Player is offline - If the player is online, that takes precedence - callEventExcludingSome(new PlayerJoinEvent(sender, "")); + callEventSync(new PlayerJoinEvent(sender, "")); } else { val sender = MCChatUtils.removeSender(MCChatUtils.ConnectedSenders, channel, user); if (p == null)// Player is offline - If the player is online, that takes precedence - callEventExcludingSome(new PlayerQuitEvent(sender, "")); + callEventSync(new PlayerQuitEvent(sender, "")); } - } + } // ---- PermissionsEx warning is normal on logout ---- if (!start) MCChatUtils.lastmsgfromd.remove(channel.getLongID()); return start // @@ -57,7 +59,11 @@ public class MCChatPrivate { public static void logoutAll() { for (val entry : MCChatUtils.ConnectedSenders.entrySet()) for (val valueEntry : entry.getValue().entrySet()) - callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); + callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); //This is sync MCChatUtils.ConnectedSenders.clear(); } + + private static void callEventSync(Event event) { + Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> callEventExcludingSome(event)); + } } diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java index 2e2d089..2c5fdb0 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java @@ -9,6 +9,7 @@ import com.earth2me.essentials.CommandSource; import lombok.val; import net.ess3.api.events.AfkStatusChangeEvent; import net.ess3.api.events.MuteStatusChangeEvent; +import net.ess3.api.events.NickChangeEvent; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -144,4 +145,9 @@ class MCListener implements Listener { //Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s")); } + + @EventHandler + public void onNickChange(NickChangeEvent event) { + MCChatUtils.updatePlayerList(); + } } From 1911672b103c3da7349f47a1dfc3f4f484430154 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Wed, 26 Dec 2018 01:35:36 +0100 Subject: [PATCH 11/12] Christmas hotfix --- .../discordplugin/listeners/CommandListener.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java index 85f0fd4..73e827d 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java @@ -4,6 +4,7 @@ import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.commands.DiscordCommandBase; import sx.blah.discord.handle.obj.IChannel; import sx.blah.discord.handle.obj.IMessage; +import sx.blah.discord.handle.obj.IRole; public class CommandListener { /** @@ -14,6 +15,8 @@ public class CommandListener { * @return Whether it ran the command */ public static boolean runCommand(IMessage message, boolean mentionedonly) { + if (message.getContent().length() == 0) + return false; //Pin messages and such, let the mcchat listener deal with it final IChannel channel = message.getChannel(); if (!mentionedonly) { //mentionedonly conditions are in CommonListeners if (!message.getChannel().isPrivate() @@ -27,7 +30,7 @@ public class CommandListener { final String mentionNick = DiscordPlugin.dc.getOurUser().mention(true); boolean gotmention = checkanddeletemention(cmdwithargs, mention, message); gotmention = checkanddeletemention(cmdwithargs, mentionNick, message) || gotmention; - for (String mentionRole : (Iterable) message.getRoleMentions().stream().filter(r -> DiscordPlugin.dc.getOurUser().hasRole(r)).map(r -> r.mention())::iterator) + for (String mentionRole : (Iterable) message.getRoleMentions().stream().filter(r -> DiscordPlugin.dc.getOurUser().hasRole(r)).map(IRole::mention)::iterator) gotmention = checkanddeletemention(cmdwithargs, mentionRole, message) || gotmention; // Delete all mentions if (mentionedonly && !gotmention) { message.getChannel().setTypingStatus(false); From f13c8321cd5e70cc46412074756b896d49e49e88 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 27 Dec 2018 01:16:55 +0100 Subject: [PATCH 12/12] Slight API change --- .../buttondevteam/discordplugin/mcchat/MCChatListener.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java index 882921b..c2ec714 100755 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java @@ -121,13 +121,13 @@ public class MCChatListener implements Listener { || ((DiscordSenderBase) e.getSender()).getChannel().getLongID() != ch.getLongID(); if (e.getChannel().isGlobal() - && (e.isFromcmd() || isdifferentchannel.test(DiscordPlugin.chatchannel))) + && (e.isFromCommand() || isdifferentchannel.test(DiscordPlugin.chatchannel))) doit.accept(MCChatUtils.lastmsgdata == null ? MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(DiscordPlugin.chatchannel, null) : MCChatUtils.lastmsgdata); for (MCChatUtils.LastMsgData data : MCChatPrivate.lastmsgPerUser) { - if ((e.isFromcmd() || isdifferentchannel.test(data.channel)) + if ((e.isFromCommand() || isdifferentchannel.test(data.channel)) && e.shouldSendTo(MCChatUtils.getSender(data.channel, data.user))) doit.accept(data); } @@ -135,7 +135,7 @@ public class MCChatListener implements Listener { val iterator = MCChatCustom.lastmsgCustom.iterator(); while (iterator.hasNext()) { val lmd = iterator.next(); - if ((e.isFromcmd() || isdifferentchannel.test(lmd.channel)) //Test if msg is from Discord + if ((e.isFromCommand() || isdifferentchannel.test(lmd.channel)) //Test if msg is from Discord && e.getChannel().ID.equals(lmd.mcchannel.ID) //If it's from a command, the command msg has been deleted, so we need to send it && e.getGroupID().equals(lmd.groupID)) { //Check if this is the group we want to test - #58 if (e.shouldSendTo(lmd.dcp)) //Check original user's permissions