From e718fafd52dfe2d1f5396b7c21da6990901b3ea9 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 15 Jul 2018 01:14:04 +0200 Subject: [PATCH 1/4] Added API changes --- .../discordplugin/listeners/MCChatListener.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java index d4a3ce9..b5ff177 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java @@ -7,6 +7,7 @@ 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; @@ -478,10 +479,11 @@ public class MCChatListener implements Listener, IListener + DPUtils.sanitizeString(dsender.getMcchannel().DisplayName)); } else { // Send single message final String msg = event.getMessage().getContent().substring(spi + 2); + val cmb = ChatMessage.builder(chc, dsender, user, getChatMessage.apply(msg)).fromCommand(true); if (clmd == null) - TBMCChatAPI.SendChatMessage(chc, dsender, getChatMessage.apply(msg), true); + TBMCChatAPI.SendChatMessage(cmb.build()); else - TBMCChatAPI.SendChatMessageDontCheckSender(chc, dsender, getChatMessage.apply(msg), true, clmd.dcp); + TBMCChatAPI.SendChatMessage(cmb.permCheck(clmd.dcp).build()); react = true; } } @@ -495,10 +497,11 @@ public class MCChatListener implements Listener, IListener (dsender instanceof Player ? ((Player) dsender).getDisplayName() : dsender.getName()) + " pinned a message on Discord."); else { + val cmb = ChatMessage.builder(dsender.getMcchannel(), dsender, user, getChatMessage.apply(dmessage)).fromCommand(false); if (clmd != null) - TBMCChatAPI.SendChatMessageDontCheckSender(clmd.mcchannel, dsender, getChatMessage.apply(dmessage), false, clmd.dcp); + TBMCChatAPI.SendChatMessage(cmb.channel(clmd.mcchannel).permCheck(clmd.dcp).build()); else - TBMCChatAPI.SendChatMessage(dsender.getMcchannel(), dsender, getChatMessage.apply(dmessage)); + TBMCChatAPI.SendChatMessage(cmb.build()); react = true; } } @@ -546,7 +549,8 @@ public class MCChatListener implements Listener, IListener cmd = dmessage.substring(0, index); for (Channel channel : Channel.getChannels()) { if (cmd.equalsIgnoreCase(channel.ID) || (channel.IDs != null && Arrays.stream(channel.IDs).anyMatch(cmd::equalsIgnoreCase))) { - TBMCChatAPI.SendChatMessage(channel, dsender, dmessage.substring(index + 1)); + val dp = DiscordPlayer.getUser(dsender.getUser().getStringID(), DiscordPlayer.class); + TBMCChatAPI.SendChatMessage(ChatMessage.builder(channel, dsender, dp, dmessage.substring(index + 1)).build()); return true; } } From de857fef0bfa4953f23744b7bccbb2c5f7365313 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 19 Jul 2018 00:39:17 +0200 Subject: [PATCH 2/4] Channelcon&chat&other fixes #58 fixed Made checkmarks stored separately per channel #55 fixed Correctly handling interrupt events, a local bug might have been fixed where the server didn't always stop. Added a reset command Needs testing --- .../buttondevteam/discordplugin/DPUtils.java | 11 +--- .../discordplugin/DiscordPlugin.java | 62 +++++++++-------- .../commands/ConnectCommand.java | 2 +- .../listeners/MCChatListener.java | 66 ++++++++++++++----- .../mccommands/ResetMCCommand.java | 35 ++++++++++ 5 files changed, 121 insertions(+), 55 deletions(-) create mode 100644 src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java diff --git a/src/main/java/buttondevteam/discordplugin/DPUtils.java b/src/main/java/buttondevteam/discordplugin/DPUtils.java index abc1f8f..25adff8 100755 --- a/src/main/java/buttondevteam/discordplugin/DPUtils.java +++ b/src/main/java/buttondevteam/discordplugin/DPUtils.java @@ -1,6 +1,5 @@ package buttondevteam.discordplugin; -import buttondevteam.lib.TBMCCoreAPI; import org.bukkit.Bukkit; import sx.blah.discord.util.EmbedBuilder; import sx.blah.discord.util.RequestBuffer; @@ -9,6 +8,7 @@ import sx.blah.discord.util.RequestBuffer.IVoidRequest; import javax.annotation.Nullable; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public final class DPUtils { @@ -39,18 +39,13 @@ public final class DPUtils { * Performs Discord actions, retrying when ratelimited. May return null if action fails too many times or in safe mode. */ @Nullable - public static T perform(IRequest action, long timeout, TimeUnit unit) { + public static T perform(IRequest action, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException { if (DiscordPlugin.SafeMode) return null; if (Thread.currentThread() == DiscordPlugin.mainThread) // TODO: Ignore shutdown message <-- // throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); Bukkit.getLogger().warning("Waiting for a Discord request on the main thread!"); - try { - return RequestBuffer.request(action).get(timeout, unit); // Let the pros handle this - } catch (Exception e) { - TBMCCoreAPI.SendException("Couldn't perform Discord action!", e); - return null; - } + return RequestBuffer.request(action).get(timeout, unit); // Let the pros handle this } /** diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 170c789..c5e6ded 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -15,6 +15,7 @@ import com.google.gson.JsonParser; 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.plugin.java.JavaPlugin; @@ -35,6 +36,7 @@ import java.nio.charset.StandardCharsets; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; public class DiscordPlugin extends JavaPlugin implements IListener { @@ -210,16 +212,8 @@ public class DiscordPlugin extends JavaPlugin implements IListener { TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this); TBMCChatAPI.AddCommands(this, DiscordMCCommandBase.class); TBMCCoreAPI.RegisterUserClass(DiscordPlayer.class); - new Thread(this::AnnouncementGetterThreadMethod).start(); + new Thread(this::AnnouncementGetterThreadMethod).start(); //TODO: Handle relogging (test) setupProviders(); - /* - * IDiscordOAuth doa = new DiscordOAuthBuilder(dc).withClientID("226443037893591041") .withClientSecret(getConfig().getString("appsecret")) .withRedirectUrl("https://" + - * (TBMCCoreAPI.IsTestServer() ? "localhost" : "server.figytuna.com") + ":8081/callback") .withScopes(Scope.IDENTIFY).withHttpServerOptions(new HttpServerOptions().setPort(8081)) - * .withSuccessHandler((rc, user) -> { rc.response().headers().add("Location", "https://" + (TBMCCoreAPI.IsTestServer() ? "localhost" : "server.figytuna.com") + ":8080/login?type=discord&" - * + rc.request().query()); rc.response().setStatusCode(303); rc.response().end("Redirecting"); rc.response().close(); }).withFailureHandler(rc -> { rc.response().headers().add("Location", - * "https://" + (TBMCCoreAPI.IsTestServer() ? "localhost" : "server.figytuna.com") + ":8080/login?type=discord&" + rc.request().query()); rc.response().setStatusCode(303); - * rc.response().end("Redirecting"); rc.response().close(); }).build(); getLogger().info("Auth URL: " + doa.buildAuthUrl()); - */ } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while enabling DiscordPlugin!", e); } @@ -260,22 +254,28 @@ public class DiscordPlugin extends JavaPlugin implements IListener { } saveConfig(); - MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannelWait(ch, "", - new EmbedBuilder().withColor(Restart ? Color.ORANGE : Color.RED) - .withTitle(Restart ? "Server restarting" : "Server stopping") - .withDescription( - Bukkit.getOnlinePlayers().size() > 0 - ? (DPUtils - .sanitizeString(Bukkit.getOnlinePlayers().stream() - .map(p -> p.getDisplayName()).collect(Collectors.joining(", "))) - + (Bukkit.getOnlinePlayers().size() == 1 ? " was " : " were ") - + "asked *politely* to leave the server for a bit.") - : "") - .build(), 5, TimeUnit.SECONDS)); + MCChatListener.forAllMCChat(ch -> { + try { + DiscordPlugin.sendMessageToChannelWait(ch, "", + new EmbedBuilder().withColor(Restart ? Color.ORANGE : Color.RED) + .withTitle(Restart ? "Server restarting" : "Server stopping") + .withDescription( + Bukkit.getOnlinePlayers().size() > 0 + ? (DPUtils + .sanitizeString(Bukkit.getOnlinePlayers().stream() + .map(Player::getDisplayName).collect(Collectors.joining(", "))) + + (Bukkit.getOnlinePlayers().size() == 1 ? " was " : " were ") + + "asked *politely* to leave the server for a bit.") + : "") + .build(), 5, TimeUnit.SECONDS); + } catch (TimeoutException | InterruptedException e) { + e.printStackTrace(); + } + }); ChromaBot.getInstance().updatePlayerList(); try { SafeMode = true; // Stop interacting with Discord - MCChatListener.stop(); + MCChatListener.stop(true); ChromaBot.delete(); dc.changePresence(StatusType.IDLE, ActivityType.PLAYING, "Chromacraft"); //No longer using the same account for testing dc.logout(); @@ -359,26 +359,30 @@ public class DiscordPlugin extends JavaPlugin implements IListener { } public static void sendMessageToChannel(IChannel channel, String message, EmbedObject embed) { - sendMessageToChannel(channel, message, embed, false); + try { + sendMessageToChannel(channel, message, embed, false); + } catch (TimeoutException | InterruptedException e) { + e.printStackTrace(); //Shouldn't happen, as we're not waiting on the result + } } - public static IMessage sendMessageToChannelWait(IChannel channel, String message) { + public static IMessage sendMessageToChannelWait(IChannel channel, String message) throws TimeoutException, InterruptedException { return sendMessageToChannelWait(channel, message, null); } - public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed) { + public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed) throws TimeoutException, InterruptedException { return sendMessageToChannel(channel, message, embed, true); } - public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed, long timeout, TimeUnit unit) { + public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException { return sendMessageToChannel(channel, message, embed, true, timeout, unit); } - private static IMessage sendMessageToChannel(IChannel channel, String message, EmbedObject embed, boolean wait) { + private static IMessage sendMessageToChannel(IChannel channel, String message, EmbedObject embed, boolean wait) throws TimeoutException, InterruptedException { return sendMessageToChannel(channel, message, embed, wait, -1, null); } - private static IMessage sendMessageToChannel(IChannel channel, String message, EmbedObject embed, boolean wait, long timeout, TimeUnit unit) { + private static IMessage sendMessageToChannel(IChannel channel, String message, EmbedObject embed, boolean wait, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException { if (message.length() > 1980) { message = message.substring(0, 1980); Bukkit.getLogger() @@ -404,6 +408,8 @@ public class DiscordPlugin extends JavaPlugin implements IListener { DPUtils.performNoWait(r); return null; } + } catch (TimeoutException | InterruptedException e) { + throw e; } catch (Exception e) { Bukkit.getLogger().warning( "Failed to deliver message to Discord! Channel: " + channel.getName() + " Message: " + message); diff --git a/src/main/java/buttondevteam/discordplugin/commands/ConnectCommand.java b/src/main/java/buttondevteam/discordplugin/commands/ConnectCommand.java index 670b522..a339c4d 100755 --- a/src/main/java/buttondevteam/discordplugin/commands/ConnectCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/ConnectCommand.java @@ -27,7 +27,7 @@ public class ConnectCommand extends DiscordCommandBase { @Override public boolean run(IMessage message, String args) { if (args.length() == 0) - return true; + return false; if (args.contains(" ")) { DiscordPlugin.sendMessageToChannel(message.getChannel(), "Too many arguments.\nUsage: connect "); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java index b5ff177..12d706b 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java @@ -12,6 +12,7 @@ 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.val; @@ -38,6 +39,7 @@ import java.time.Instant; import java.util.*; import java.util.List; 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; @@ -53,7 +55,7 @@ public class MCChatListener implements Listener, IListener @EventHandler // Minecraft public void onMCChat(TBMCChatEvent ev) { - if (ev.isCancelled()) + if (DiscordPlugin.SafeMode || ev.isCancelled()) //SafeMode: Needed so it doesn't restart after server shutdown return; sendevents.add(new AbstractMap.SimpleEntry<>(ev, Instant.now())); if (sendtask != null) @@ -71,15 +73,10 @@ public class MCChatListener implements Listener, IListener try { TBMCChatEvent e; Instant time; - try { - val se = sendevents.take(); // Wait until an element is available - e = se.getKey(); - time = se.getValue(); - } catch (InterruptedException ex) { - sendtask.cancel(); - sendtask = null; - return; - } + val se = sendevents.take(); // Wait until an element is available + e = se.getKey(); + time = se.getValue(); + final String authorPlayer = "[" + DPUtils.sanitizeString(e.getChannel().DisplayName) + "] " // + (e.getSender() instanceof DiscordSenderBase ? "[D]" : "") // + (DPUtils.sanitizeString(e.getSender() instanceof Player // @@ -102,7 +99,7 @@ public class MCChatListener implements Listener, IListener // embed.withFooterText(e.getChannel().DisplayName); embed.withTimestamp(time); final long nanoTime = System.nanoTime(); - Consumer 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()) @@ -144,14 +141,19 @@ public class MCChatListener implements Listener, IListener while (iterator.hasNext()) { //TODO: Add cmd to fix mcchat val lmd = iterator.next(); if ((e.isFromcmd() || 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 - if (e.shouldSendTo(lmd.dcp) && e.getGroupID().equals(lmd.groupID)) //Check original user's permissions + && 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 doit.accept(lmd); else { iterator.remove(); //If the user no longer has permission, remove the connection DiscordPlugin.sendMessageToChannel(lmd.channel, "The user no longer has permission to view the channel, connection removed."); } + } } + } catch (InterruptedException ex) { //Stop if interrupted anywhere + sendtask.cancel(); + sendtask = null; } catch (Exception ex) { TBMCCoreAPI.SendException("Error while sending message to Discord!", ex); } @@ -216,6 +218,7 @@ public class MCChatListener implements Listener, IListener * 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); @@ -233,6 +236,8 @@ public class MCChatListener implements Listener, IListener MCListener.callEventExcludingSome(new PlayerQuitEvent(sender, "")); } } + if (!start) + lastmsgfromd.remove(channel.getLongID()); return start // ? lastmsgPerUser.add(new LastMsgData(channel, user, dp)) // Doesn't support group DMs : lastmsgPerUser.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID()); @@ -273,6 +278,7 @@ public class MCChatListener implements Listener, IListener } public static boolean removeCustomChat(IChannel channel) { + lastmsgfromd.remove(channel.getLongID()); return lastmsgCustom.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID()); } @@ -337,14 +343,32 @@ public class MCChatListener implements Listener, IListener .map(data -> data.channel).forEach(action); } - public static void stop() { + /** + * Stop the listener. Any calls to onMCChat will restart it as long as we're not in safe mode. + * + * @param wait Wait 5 seconds for the threads to stop + */ + public static void stop(boolean wait) { if (sendthread != null) sendthread.interrupt(); if (recthread != null) recthread.interrupt(); + try { + if (sendthread != null) { + sendthread.interrupt(); + if (wait) + sendthread.join(5000); + } + if (recthread != null) { + recthread.interrupt(); + if (wait) + recthread.join(5000); + } + } catch (InterruptedException e) { + e.printStackTrace(); //This thread shouldn't be interrupted + } } private BukkitTask rectask; private LinkedBlockingQueue recevents = new LinkedBlockingQueue<>(); - private IMessage lastmsgfromd; // Last message sent by a Discord user, used for clearing checkmarks private Runnable recrun; private static Thread recthread; @@ -507,14 +531,15 @@ public class MCChatListener implements Listener, IListener } if (react) { try { - if (lastmsgfromd != null) { - DPUtils.perform(() -> lastmsgfromd.removeReaction(DiscordPlugin.dc.getOurUser(), + val lmfd = 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 } } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while removing reactions from chat!", e); } - lastmsgfromd = event.getMessage(); + lastmsgfromd.put(event.getChannel().getLongID(), event.getMessage()); DPUtils.perform(() -> event.getMessage().addReaction(DiscordPlugin.DELIVERED_REACTION)); } } catch (Exception e) { @@ -573,4 +598,9 @@ public class MCChatListener implements Listener, IListener return Optional.of(dsender); }).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/mccommands/ResetMCCommand.java b/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java new file mode 100644 index 0000000..5d571a7 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java @@ -0,0 +1,35 @@ +package buttondevteam.discordplugin.mccommands; + +import buttondevteam.discordplugin.DiscordPlugin; +import buttondevteam.discordplugin.listeners.MCChatListener; +import buttondevteam.lib.chat.CommandClass; +import buttondevteam.lib.chat.TBMCCommandBase; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; + +@CommandClass(path = "discord reset", modOnly = true) +public class ResetMCCommand extends TBMCCommandBase { //Not player-only, so not using DiscordMCCommandBase + @Override + public boolean OnCommand(CommandSender sender, String s, String[] strings) { + Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> { + sender.sendMessage("§bStopping MCChatListener..."); + DiscordPlugin.SafeMode = true; + MCChatListener.stop(true); + if (DiscordPlugin.dc.isLoggedIn()) { + sender.sendMessage("§bLogging out..."); + DiscordPlugin.dc.logout(); + } else + sender.sendMessage("§bWe're not logged in."); + sender.sendMessage("§bLogging in..."); + DiscordPlugin.dc.login(); + DiscordPlugin.SafeMode = false; + sender.sendMessage("§bChromaBot has been reset!"); + }); + return false; + } + + @Override + public String[] GetHelpText(String s) { + return new String[0]; + } +} From 557eac2292620cf9fc3e8dc723478acbd1a06d79 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Fri, 20 Jul 2018 12:43:17 +0200 Subject: [PATCH 3/4] Reset command fixes Now it's disabling and enabling the plugin Some changes were made to handle this as well Fixed main thread checks, the plugin may not be enabled in the main thread --- .../buttondevteam/discordplugin/DPUtils.java | 6 +-- .../discordplugin/DiscordPlugin.java | 45 ++++++++++++------- .../listeners/MCChatListener.java | 10 ++++- .../mccommands/ResetMCCommand.java | 27 +++++------ 4 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/DPUtils.java b/src/main/java/buttondevteam/discordplugin/DPUtils.java index 25adff8..89c0b82 100755 --- a/src/main/java/buttondevteam/discordplugin/DPUtils.java +++ b/src/main/java/buttondevteam/discordplugin/DPUtils.java @@ -42,7 +42,7 @@ public final class DPUtils { public static T perform(IRequest action, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException { if (DiscordPlugin.SafeMode) return null; - if (Thread.currentThread() == DiscordPlugin.mainThread) // TODO: Ignore shutdown message <-- + if (Bukkit.isPrimaryThread()) // TODO: Ignore shutdown message <-- // throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); Bukkit.getLogger().warning("Waiting for a Discord request on the main thread!"); return RequestBuffer.request(action).get(timeout, unit); // Let the pros handle this @@ -55,7 +55,7 @@ public final class DPUtils { public static T perform(IRequest action) { if (DiscordPlugin.SafeMode) return null; - if (Thread.currentThread() == DiscordPlugin.mainThread) // TODO: Ignore shutdown message <-- + if (Bukkit.isPrimaryThread()) // TODO: Ignore shutdown message <-- // throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); Bukkit.getLogger().warning("Waiting for a Discord request on the main thread!"); return RequestBuffer.request(action).get(); // Let the pros handle this @@ -67,7 +67,7 @@ public final class DPUtils { public static Void perform(IVoidRequest action) { if (DiscordPlugin.SafeMode) return null; - if (Thread.currentThread() == DiscordPlugin.mainThread) + if (Bukkit.isPrimaryThread()) throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); return RequestBuffer.request(action).get(); // Let the pros handle this } diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index c5e6ded..9ed6232 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -3,6 +3,7 @@ package buttondevteam.discordplugin; import buttondevteam.discordplugin.commands.DiscordCommandBase; import buttondevteam.discordplugin.listeners.*; import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase; +import buttondevteam.discordplugin.mccommands.ResetMCCommand; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.chat.Channel; import buttondevteam.lib.chat.TBMCChatAPI; @@ -42,7 +43,6 @@ import java.util.stream.Collectors; public class DiscordPlugin extends JavaPlugin implements IListener { private static final String SubredditURL = "https://www.reddit.com/r/ChromaGamers"; private static boolean stop = false; - static Thread mainThread; public static IDiscordClient dc; public static DiscordPlugin plugin; public static boolean SafeMode = true; @@ -52,6 +52,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { @SuppressWarnings("unchecked") @Override public void onEnable() { + stop = false; //If not the first time try { Bukkit.getLogger().info("Initializing DiscordPlugin..."); try { @@ -69,7 +70,6 @@ public class DiscordPlugin extends JavaPlugin implements IListener { cb.withToken(Files.readFirstLine(new File("TBMC", "Token.txt"), StandardCharsets.UTF_8)); dc = cb.login(); dc.getDispatcher().registerListener(this); - mainThread = Thread.currentThread(); } catch (Exception e) { e.printStackTrace(); Bukkit.getPluginManager().disablePlugin(this); @@ -105,7 +105,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { } if (mainServer == null || devServer == null) return; // Retry - if (!TBMCCoreAPI.IsTestServer()) { + if (!TBMCCoreAPI.IsTestServer()) { //Don't change conditions here, see mainServer=devServer=null in onDisable() botchannel = mainServer.getChannelByID(209720707188260864L); // bot annchannel = mainServer.getChannelByID(126795071927353344L); // announcements genchannel = mainServer.getChannelByID(125813020357165056L); // general @@ -157,7 +157,10 @@ public class DiscordPlugin extends JavaPlugin implements IListener { } DiscordCommandBase.registerCommands(); - if (getConfig().getBoolean("serverup", false)) { + if (ResetMCCommand.resetting) + ChromaBot.getInstance().sendMessage("", new EmbedBuilder().withColor(Color.CYAN) + .withTitle("Discord plugin restarted - chat connected.").build()); //Really important to note the chat, hmm + else if (getConfig().getBoolean("serverup", false)) { ChromaBot.getInstance().sendMessage("", new EmbedBuilder().withColor(Color.YELLOW) .withTitle("Server recovered from a crash - chat connected.").build()); val thr = new Throwable( @@ -167,6 +170,9 @@ public class DiscordPlugin extends JavaPlugin implements IListener { } else ChromaBot.getInstance().sendMessage("", new EmbedBuilder().withColor(Color.GREEN) .withTitle("Server started - chat connected.").build()); + + ResetMCCommand.resetting = false; //This is the last event handling this flag + getConfig().set("serverup", true); saveConfig(); DPUtils.performNoWait(() -> { @@ -237,6 +243,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { stop = true; for (val entry : MCChatListener.ConnectedSenders.entrySet()) MCListener.callEventExcludingSome(new PlayerQuitEvent(entry.getValue(), "")); + MCChatListener.ConnectedSenders.clear(); getConfig().set("lastannouncementtime", lastannouncementtime); getConfig().set("lastseentime", lastseentime); getConfig().set("serverup", false); @@ -256,18 +263,22 @@ public class DiscordPlugin extends JavaPlugin implements IListener { saveConfig(); MCChatListener.forAllMCChat(ch -> { try { - DiscordPlugin.sendMessageToChannelWait(ch, "", - new EmbedBuilder().withColor(Restart ? Color.ORANGE : Color.RED) - .withTitle(Restart ? "Server restarting" : "Server stopping") - .withDescription( - Bukkit.getOnlinePlayers().size() > 0 - ? (DPUtils - .sanitizeString(Bukkit.getOnlinePlayers().stream() - .map(Player::getDisplayName).collect(Collectors.joining(", "))) - + (Bukkit.getOnlinePlayers().size() == 1 ? " was " : " were ") - + "asked *politely* to leave the server for a bit.") - : "") - .build(), 5, TimeUnit.SECONDS); + if (ResetMCCommand.resetting) + DiscordPlugin.sendMessageToChannelWait(ch, "", + new EmbedBuilder().withColor(Color.ORANGE).withTitle("Discord plugin restarting").build()); + else + DiscordPlugin.sendMessageToChannelWait(ch, "", + new EmbedBuilder().withColor(Restart ? Color.ORANGE : Color.RED) + .withTitle(Restart ? "Server restarting" : "Server stopping") + .withDescription( + Bukkit.getOnlinePlayers().size() > 0 + ? (DPUtils + .sanitizeString(Bukkit.getOnlinePlayers().stream() + .map(Player::getDisplayName).collect(Collectors.joining(", "))) + + (Bukkit.getOnlinePlayers().size() == 1 ? " was " : " were ") + + "asked *politely* to leave the server for a bit.") + : "") + .build(), 5, TimeUnit.SECONDS); } catch (TimeoutException | InterruptedException e) { e.printStackTrace(); } @@ -279,6 +290,8 @@ public class DiscordPlugin extends JavaPlugin implements IListener { ChromaBot.delete(); dc.changePresence(StatusType.IDLE, ActivityType.PLAYING, "Chromacraft"); //No longer using the same account for testing dc.logout(); + mainServer = devServer = null; //Fetch servers and channels again + sent = false; } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while disabling DiscordPlugin!", e); } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java index 12d706b..49bcf63 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java @@ -138,7 +138,7 @@ public class MCChatListener implements Listener, IListener } val iterator = lastmsgCustom.iterator(); - while (iterator.hasNext()) { //TODO: Add cmd to fix mcchat + while (iterator.hasNext()) { val lmd = iterator.next(); if ((e.isFromcmd() || 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 @@ -362,6 +362,14 @@ public class MCChatListener implements Listener, IListener if (wait) recthread.join(5000); } + lastmsgdata = null; + lastmsgPerUser.clear(); + lastmsgCustom.clear(); + lastmsgfromd.clear(); + ConnectedSenders.clear(); + lastlist = lastlistp = ListC = 0; + UnconnectedSenders.clear(); + recthread = sendthread = null; } catch (InterruptedException e) { e.printStackTrace(); //This thread shouldn't be interrupted } diff --git a/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java b/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java index 5d571a7..dcfd00d 100644 --- a/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java +++ b/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java @@ -1,7 +1,6 @@ package buttondevteam.discordplugin.mccommands; import buttondevteam.discordplugin.DiscordPlugin; -import buttondevteam.discordplugin.listeners.MCChatListener; import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.TBMCCommandBase; import org.bukkit.Bukkit; @@ -9,27 +8,25 @@ import org.bukkit.command.CommandSender; @CommandClass(path = "discord reset", modOnly = true) public class ResetMCCommand extends TBMCCommandBase { //Not player-only, so not using DiscordMCCommandBase + public static boolean resetting = false; @Override public boolean OnCommand(CommandSender sender, String s, String[] strings) { Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> { - sender.sendMessage("§bStopping MCChatListener..."); - DiscordPlugin.SafeMode = true; - MCChatListener.stop(true); - if (DiscordPlugin.dc.isLoggedIn()) { - sender.sendMessage("§bLogging out..."); - DiscordPlugin.dc.logout(); - } else - sender.sendMessage("§bWe're not logged in."); - sender.sendMessage("§bLogging in..."); - DiscordPlugin.dc.login(); - DiscordPlugin.SafeMode = false; - sender.sendMessage("§bChromaBot has been reset!"); + resetting = true; //Turned off after sending enable message (ReadyEvent) + sender.sendMessage("§bDisabling DiscordPlugin..."); + Bukkit.getPluginManager().disablePlugin(DiscordPlugin.plugin); + sender.sendMessage("§bEnabling DiscordPlugin..."); + Bukkit.getPluginManager().enablePlugin(DiscordPlugin.plugin); + sender.sendMessage("§bReset finished!"); }); - return false; + return true; } @Override public String[] GetHelpText(String s) { - return new String[0]; + return new String[]{ // + "§6---- Reset ChromaBot ----", // + "This command stops the Minecraft chat and relogs the bot." // + }; } } From 4f6612c21bb818d5ca21a17888c1d830d38869ce Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Fri, 20 Jul 2018 13:18:33 +0200 Subject: [PATCH 4/4] Updated help text --- src/main/java/buttondevteam/discordplugin/DiscordPlugin.java | 2 +- .../buttondevteam/discordplugin/mccommands/ResetMCCommand.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 9ed6232..34669c4 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -218,7 +218,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this); TBMCChatAPI.AddCommands(this, DiscordMCCommandBase.class); TBMCCoreAPI.RegisterUserClass(DiscordPlayer.class); - new Thread(this::AnnouncementGetterThreadMethod).start(); //TODO: Handle relogging (test) + new Thread(this::AnnouncementGetterThreadMethod).start(); setupProviders(); } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while enabling DiscordPlugin!", e); diff --git a/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java b/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java index dcfd00d..fce8d04 100644 --- a/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java +++ b/src/main/java/buttondevteam/discordplugin/mccommands/ResetMCCommand.java @@ -26,7 +26,7 @@ public class ResetMCCommand extends TBMCCommandBase { //Not player-only, so not public String[] GetHelpText(String s) { return new String[]{ // "§6---- Reset ChromaBot ----", // - "This command stops the Minecraft chat and relogs the bot." // + "This command disables and then enables the plugin." // }; } }