From 649fd4611fcec488fe49c537bda4f062ed7ded8b Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sat, 5 Aug 2017 15:45:31 +0200 Subject: [PATCH] Excluding ProtocolLib from fake player events --- .../listeners/MCChatListener.java | 4 +- .../discordplugin/listeners/MCListener.java | 70 ++++++++++++++++++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java index 9a2763a..138c154 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java @@ -134,11 +134,11 @@ public class MCChatListener implements Listener, IListener val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID()); ConnectedSenders.put(user.getStringID(), sender); if (p == null)// Player is offline - If the player is online, that takes precedence - Bukkit.getPluginManager().callEvent(new PlayerJoinEvent(sender, "")); + MCListener.callEventExcluding(new PlayerJoinEvent(sender, ""), "ProtocolLib"); } else { val sender = ConnectedSenders.remove(user.getStringID()); if (p == null)// Player is offline - If the player is online, that takes precedence - Bukkit.getPluginManager().callEvent(new PlayerQuitEvent(sender, "")); + MCListener.callEventExcluding(new PlayerQuitEvent(sender, ""), "ProtocolLib"); } } return start // diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java index dc7fcad..c60ca6c 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java @@ -1,14 +1,22 @@ package buttondevteam.discordplugin.listeners; +import java.util.Arrays; +import java.util.logging.Level; + import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.server.ServerCommandEvent; +import org.bukkit.plugin.AuthorNagException; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.RegisteredListener; import com.earth2me.essentials.CommandSource; @@ -41,7 +49,7 @@ public class MCListener implements Listener { new DiscordPlayerSender(user, DiscordPlugin.chatchannel, p)); MCChatListener.ConnectedSenders.values().stream() .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() - .ifPresent(dcp -> Bukkit.getPluginManager().callEvent(new PlayerQuitEvent(dcp, ""))); + .ifPresent(dcp -> callEventExcluding(new PlayerQuitEvent(dcp, ""), "ProtocolLib")); } if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) { IUser user = DiscordPlugin.dc @@ -62,7 +70,7 @@ public class MCListener implements Listener { .removeIf(entry -> entry.getValue().getUniqueId().equals(e.getPlayer().getUniqueId())); MCChatListener.ConnectedSenders.values().stream() .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() - .ifPresent(dcp -> Bukkit.getPluginManager().callEvent(new PlayerJoinEvent(dcp, ""))); + .ifPresent(dcp -> callEventExcluding(new PlayerJoinEvent(dcp, ""), "ProtocolLib")); MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " left the game"); } @@ -121,4 +129,62 @@ public class MCListener implements Listener { ex); } } + + /** + * Calls an event with the given details. + *

+ * This method only synchronizes when the event is not asynchronous. + * + * @param event + * Event details + * @param plugins + * The plugins to exclude. Not case sensitive. + */ + public static void callEventExcluding(Event event, String... plugins) { // Copied from Spigot-API and modified a bit + if (event.isAsynchronous()) { + if (Thread.holdsLock(Bukkit.getPluginManager())) { + throw new IllegalStateException( + event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); + } + if (Bukkit.getServer().isPrimaryThread()) { + throw new IllegalStateException( + event.getEventName() + " cannot be triggered asynchronously from primary server thread."); + } + fireEventExcluding(event, plugins); + } else { + synchronized (Bukkit.getPluginManager()) { + fireEventExcluding(event, plugins); + } + } + } + + private static void fireEventExcluding(Event event, String... plugins) { + HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API + RegisteredListener[] listeners = handlers.getRegisteredListeners(); + val server = Bukkit.getServer(); + + for (RegisteredListener registration : listeners) { + if (!registration.getPlugin().isEnabled() + || Arrays.stream(plugins).anyMatch(p -> p.equalsIgnoreCase(registration.getPlugin().getName()))) + continue; // Modified to exclude plugins + + try { + registration.callEvent(event); + } catch (AuthorNagException ex) { + Plugin plugin = registration.getPlugin(); + + if (plugin.isNaggable()) { + plugin.setNaggable(false); + + server.getLogger().log(Level.SEVERE, + String.format("Nag author(s): '%s' of '%s' about the following: %s", + plugin.getDescription().getAuthors(), plugin.getDescription().getFullName(), + ex.getMessage())); + } + } catch (Throwable ex) { + server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + + registration.getPlugin().getDescription().getFullName(), ex); + } + } + } }