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; }